Как передать двумерный массив строк в функцию другого класса - PullRequest
1 голос
/ 30 сентября 2011

Я столкнулся с небольшой дилеммой, которая поставила меня в тупик в последние несколько дней.

Я работаю над проектом, просто для практики, цель которого состоит в том, чтобы побудить пользователя ввести слово ираспечатать (на экран) то же самое слово, но большими буквами, нарисованными ASCII-символами.Например, если пользователь наберет слово «Hello», на выходе будет:

H    H EEEEE L     L       OOO
H    H E     L     L      O   O
HHHHHH EEE   L     L     O     O
H    H E     L     L      O   O
H    H EEEEE LLLLL LLLLL   OOO

Я создал двумерный строковый массив с именем 'letters' в пространстве имен с именем "UpperCaseFont".Затем я создал класс с именем BigWord, целью которого было бы сохранить слово, введенное пользователем, и предоставить несколько полезных функций: printWord (), setWord (), getWord () и т. Д.

Вместо сохранениядвумерный строковый массив внутри класса BigWord (что на самом деле я и собирался сделать, но не смог работать), позже я подумал, что было бы лучше передать массив букв в функцию (setAsciiFont ())определены в BigWord и имеют указатель в классе BigWord, указывающий на адрес массива букв.Таким образом, вместо создания нового массива букв каждый раз, когда создается новый объект BigWord, все объекты BigWord могут просто ссылаться на один и тот же массив букв.Экономия памяти и несколько тактов (не то, чтобы это имело значение в проекте такого размера, но я все еще хочу развить хорошие привычки кодирования).

Однако я не могу заставить его работать.Мой код ниже:

Основной файл .cpp:

#include <iostream>
#include "Characters.h"

using namespace std;

int main(int argc, char** argv) {

   BigWord b;
   char temp[20];

   cin >> temp; // prompt user for word

   b.setWord(temp);
   cout << "Your word is: " << b.getWord() << endl;

   //Set the ASCII font for the BigWord object to use 
   b.setAsciiFont(UpperCaseFont::letters);

   b.printWord();

   return 0;
}

Файл заголовка (Characters.h):

#ifndef CHARACTERS
#define CHARACTERS

#include <iostream>

using namespace std;

namespace UpperCaseFont {
    // constant; font should not be changeable
    // all characters will have 5 rows.
    const string letters[][5] = {
        {
            "    A    ",
            "   A A   ",
            "  AAAAA  ",
            " A     A ",
            "A       A"
        },
        {
            "  BBBB   ",
            "  B   B  ",
            "  BBB    ",
            "  B   B  ",
            "  BBBB   "
        },
        {
            "   CCCC  ",
            "  C      ",
            " C       ",
            "  C      ",
            "   CCCC  "
        }
    }; // not finished making all letters yet.
}

class BigWord {
private:
    int wordLength;
    char word[];

    // letters[][5] will point to the location of UpperCaseFont::letters array.
    const string* letters[][5];

    void toUpperCase(char* str);
public:

    void setWord(char w[]);

    string getWord() {
        return word;
    }

    void setAsciiFont(const string [][5]); // PROBLEM WITH THIS FUNCTION

    void printWord(void);

};

void BigWord::setWord(char* w) {
    wordLength = strlen(w);
    //    cout << "Word Length: " << wordLength << endl;
    std::copy(w, w + wordLength, word);
    BigWord::toUpperCase(word);
}

void BigWord::toUpperCase(char* str) {
    // convert a string to Upper case letters for printWord algorithm to work
    for (int i = 0; i < wordLength; i++) {
        if (str[i] > 'Z') {
            str[i] -= ('a' - 'A');
        }
    }
}

void BigWord::setAsciiFont(const string font[][5]) { // ***PROBLEM***
    letters = &font; // How can I get this to work??
}

void BigWord::printWord() {
    // print top line of all ASCII Font letters, move to next line, repeat etc.
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < wordLength; j++) {
            // subtracts 65 (ASCII 'A') to arrive at index 0 if character == A.
            cout << *letters[word[j] - 'A'][i];
        }
        cout << endl;
    }
}


#endif

Когда я пытаюсь скомпилировать этокод, я получаю следующую ошибку:

Characters.h: 81: ошибка: несовместимые типы в присваивании const std::string (**)[5]' to const std :: string * [0u] [5] '

Я довольно новичок в C ++ (начался пару недель назад, но у меня есть некоторый опыт Java, чтобы поддержать меня), и еще новее в указателях, так что я точно не знаю, что я делаю неправильно.... и любые поиски в Google были безрезультатны.Я понимаю, что использование имени массива будет служить указателем на первый индекс этого массива, но как оно работает с двумерными (или многомерными) массивами?При необходимости я могу написать функцию для преобразования массива UpperCaseFont :: letters в одномерный массив, если выясняется, что двухмерные массивы слишком сложны для работы.

По сути, чтобы перейти к тому, что ядействительно спрашиваю: как я могу назначить указатель на двумерный массив строк, который был передан в функцию в классе, расположенном в заголовочном файле?

Ответы [ 3 ]

2 голосов
/ 30 сентября 2011

Проблема в том, что C ++ не поддерживает передачу массивов в качестве аргументов. Когда вы пишете:

void setAsciiFont( std::string const font[][ 5] );

компилятор преобразует это в:

void setAsciiFont( std::string const (*font)[5] );

Когда вы передаете массив, происходит аналогичное преобразование.

Самое простое решение - просто изменить объявление переменной в класс, чтобы отразить это:

std::string const (*letters)[5];

Из-за способа определения индексации в C ++ это будет работать точно как если бы вы имели полный массив в качестве члена, то есть letters['n'][line] подберут правильную строку.

И кстати: я бы передал шрифт в качестве параметра конструктору BigWord. Таким образом, вы не сможете случайно попытаться вывести не установив его.

0 голосов
/ 30 сентября 2011

Вам просто нужно правильно ввести переменную-член букв. Вы хотите присвоить ему const string (*)[5] (то есть то, к чему распадается const string [][5]), поэтому он должен иметь этот тип

// letters[][5] will point to the location of UpperCaseFont::letters array.
const string (*letters)[5];

В противном случае, это должно работать.

0 голосов
/ 30 сентября 2011

Массивы могут быть переданы по ссылке.Итак, следующая функция,

void setAsciiFont(const string [][5]); // PROBLEM WITH THIS FUNCTION

должна быть (с объявлением обоих размеров),

void setAsciiFont(const string (&letters)[3][5]); // ok
                              ^^^^ pass by reference

Вы можете шаблонизировать эту функцию, если вы не уверены в размере всегда:

template<size_t ROW, size_t COL>
void setAsciiFont(const string (&letters)[ROW][COL]); // ok
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...