2011-09-30 4 views
1

나는 지난 며칠간 나를 괴롭혔던 약간의 딜레마를 만났다.2 차원 문자열 배열을 다른 클래스의 함수로 전달하는 방법

나는 연습을 위해서, 사용자가 단어를 입력하고 (화면에) 같은 단어를 인쇄하도록하지만 ASCII 문자로 그려진 큰 글씨로 작업하는 것이 목표입니다. 사용자가 단어 "안녕하세요"에 입력 한 경우, 예를 들어, 출력은 다음과 같습니다

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 

내가 "UpperCaseFont"라는 네임 스페이스 내부에 두 개의 차원 문자열 배열 소위 '문자'를 만들었습니다. 그런 다음 BigWord라는 클래스를 만들었습니다.이 클래스의 목적은 사용자 입력 단어를 저장하고 printWord(), setWord(), getWord() 등과 같은 유용한 함수를 제공하는 것입니다.

BigWord 클래스 내에서 2 차원 문자열 배열 (실제로는 원래 의도 한 것이지만 작동하지 않을 수 있음)을 사용하여 나중에 letters 배열에 정의 된 함수 (setAsciiFont())에 문자 배열을 전달하는 것이 더 좋을 것이라고 생각했습니다. BigWord를 사용하고 BigWord 클래스의 포인터가 letters 배열의 주소를 가리 키도록하십시오. 이렇게하면 새로운 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 

, 내가 얻을 다음 오류 :

나는 C++에 상당히 익숙하다. (몇 주 전에 시작되었지만, 나는 약간의 자바 경험을 가지고있다. p), 심지어 포인터에 새로운, 그래서 내가 뭘 잘못하고 있는지 정확히 모르겠다 ... 그리고 인터넷 검색은 아무 소용이있다. 배열의 이름을 사용하면 해당 배열의 첫 번째 인덱스에 대한 포인터 역할을하지만 2 차원 (또는 다차원) 배열에서는 어떻게 작동하는지 이해합니다. 필요한 경우 UpperCaseFont :: letters 배열을 1 차원 배열로 변환하는 함수를 작성할 수 있습니다. 2 차원 배열은 다루기가 너무 까다 롭습니다.

본질적으로 내가 진정으로 묻는 것에서 벗어나기 : 헤더 파일에있는 클래스 내의 함수에 전달 된 2 차원 문자열 배열에 대한 포인터를 어떻게 할당 할 수 있습니까?

답변

2

문제는 C++에서 배열을 인수로 전달할 수 없다는 것입니다. 당신이 쓸 때 :

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

컴파일러는이 변환 : 당신이 배열을 전달하는 경우

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

, 유사한 변환이 발생합니다.

단지 클래스에 변수 선언을 변경하는 가장 간단한 해결책은이를 반영하기 : 당신이 전체를 가진 것처럼

이 때문에 연동이 C++에 정의 된 방법의
std::string const (*letters)[5]; 

, 이것은 정확히 를 작동합니다 배열, 즉 letters['n'][line] 은 올바른 문자열을 선택할 것입니다.

그리고 BTW : 글꼴을 BigWord의 생성자에 대한 매개 변수로 전달했습니다. 그렇게하면 실수로 을 설정하지 않고 출력 할 수있는 방법이 없습니다.

+0

고마워요! 나는 그것을 마침내 작동 시켰습니다 =). 아, 그리고 BigWord의 생성자에 글꼴 매개 변수를 넣으라는 조언을 받았으므로 그렇게하는 것이 합리적입니다. 적은 수의 오류가 발생하면 코드가 좋을수록 = P가 좋습니다. – Inventor22

0

배열을 참조로 전달할 수 있습니다. 그래서 기능 다음,

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 
+0

참고 솔루션은 실제로 매우 유용합니다. 그러나 효과적으로 사용하려면 클래스의 데이터 선언을 참조로 변경하고 생성자에 'letters'를 전달해야합니다 (IMHO가 바람직 함). 템플릿 제안을 삭제하십시오. 치수를 모르는 경우 안전하게 배열을 사용할 수 없습니다. –

0

글자 멤버 변수를 올바르게 입력하기 만하면됩니다. 당신은이 const string (*)[5] 그것 (const string [][5]가 붕괴 것입니다), 그래서 그렇지 않으면 이러한 유형의

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

가 있어야 작동합니다 지정할.

관련 문제