2011-08-24 4 views
1

C++에서 사용자 정의 C 유형 문자열 클래스를 작성해야한다는 지정이 있습니다. 이 문제를 해결하는 데 어려움을 겪고 있습니다. 현재 내 코드가 시작시 런타임 오류와 충돌합니다. 또한 많은 함수가 잘못되었음을 알고 있지만 다른 함수를 수정하기 전에 멤버 함수를 정렬해야합니다. 모든 함수 프로토 타입은 우리에게 주어 졌으므로 변경할 수는 없다는 것을 명심하십시오. 나는 말하기 위해 '배짱'을 쓸 필요가있다.C++에서 사용자 정의 C 유형 문자열 클래스 작성

처음에는 내 생성자가 잘못 되었나요?

#include <iostream> 
#include "tstr.h" 
using namespace std; 

//Default constructor to initialize the string to null 
TStr::TStr() { 
    strPtr = 0; 
    strSize = 0; 
} 
//constructor; conversion from the char string 
TStr::TStr(const char *str) { 
    int i=0; 
    while (str[i] != '/0') { 
     strPtr = new char [strlen(str)+1]; 
     for (i=0; i <strSize;++i) { 
      strPtr[i] = str[i]; 
     } 
     ++i; 
    } 
    strSize = i; 
} 
//Copy constructor 
TStr::TStr(const TStr&) { 
} 
//Destructor 
TStr::~TStr() { 
    if (strPtr) { 
     delete[] strPtr; 
    } 
} 

//subscript operators-checks for range 
char& TStr::operator [] (int i) { 
    assert (i >= 0 && i < strSize); 
    return strPtr[i]; 
} 
const char& TStr::operator [] (int i) const { 
    assert (i >= 0 && i < strSize); 
    return strPtr[i]; 
} 

//overload the concatenation oprerator 
TStr TStr::operator += (const TStr& str) { 
    //this->strPtr += str.strPtr; 
    //this->strSize += str.strSize; 
    return *this; 
} 
//overload the assignment operator 
const TStr& TStr::operator = (const TStr& str) { 
    if (this != &str) { 
     delete[] strPtr; 
     strPtr = new char[strSize = str.strSize]; 
     assert(strPtr); 
     for (int i=0; i<strSize; ++i) { 
      strPtr[i] = str.strPtr[i]; 
     } 
    } 
    return *this; 
} 

//overload two relational operators as member functions 
bool TStr::operator == (const TStr& str) const { 
    return (strPtr == str.strPtr && strSize == str.strSize); 
} 
bool TStr::operator < (const TStr& str) const { 
    return (strPtr < str.strPtr && strSize < str.strSize); 
} 
//the length of the string 
int TStr::size() { 
    return strSize; 
} 

답장/도움 주셔서 감사합니다! :)

편집 1 : 알았습니다. 이제 생성자가 작동하지만 여전히 런타임 오류가 발생하고 90 %가 오버로드 된 + 연산자와 관련이 있다는 것을 확신합니다. 괜찮아 보이지만 괜찮아. 내가 뭘 놓치고 있니?

(참고 :. 만 작은 변화는 위의 코드 변경되었습니다,하지만 당신은 훨씬을보고 싶다면 알려주세요)

//overload the concatenation oprerator 
TStr TStr::operator += (const TStr& str) { 
    for(int i = 0; i < strSize; ++i) { 
     strPtr[i] += str.strPtr[i]; 
    } 
    return *this; 
} 

편집 2 : 좋아 내가 지금 가지고있는이. 컴파일은 잘되지만 두 문자열을 + =와 함께 실제로 추가하지는 않습니다. 누구든지 아이디어가있어?

//overload the concatenation oprerator 
TStr TStr::operator += (const TStr& str) { 
    char *buffer = new char[strSize + str.strSize + 1]; 
    strcpy(buffer, strPtr); 
    strcat(buffer, str.strPtr); 
    delete [] strPtr; 
    strPtr = buffer; 
    return *this; 
} 

//overload the assignment operator 
const TStr& TStr::operator = (const TStr& str) { 
    if (this != &str) { 
     delete[] strPtr; 
     strPtr = new char[strSize = str.strSize]; 
     assert(strPtr); 
     for (int i=0; i<strSize; ++i) { 
      strPtr[i] = str.strPtr[i]; 
     } 
    } 
    return *this; 
} 
+0

오타 (typo)인지 모르겠지만 NULL 종결자가 이스케이프 문자 대신 슬래시를 사용하고있는 것 같습니다. – Dawson

+0

소멸자에서'if (strPtr)'를 확인할 필요가 없습니다. 'delete []'NULL 포인터는 nop이며 충돌하지 않습니다. –

+0

또한 릴리즈 빌드에서 remove이기 때문에 아마'assert'를 사용해서는 안됩니다. 예외 사용. –

답변

2

귀하의 ctor에 꽤입니다 많은 혼란.

i를 두 가지 다른 용도로 동시에 사용합니다. 또한 str의 모든 내용을 strPtr에 한 번씩 str의 각 문자에 대해 복사합니다.

기본적으로 C 런타임 라이브러리를 사용할지 여부를 결정해야합니다.

를 사용 :

TStr::TStr(const char *str) 
{ 
    strSize = strlen(str); 
    strPtr = new char [strSize+1]; 
    strcpy(strPtr, str); 
} 

를 사용하지 않을 :

TStr::TStr(const char *str) 
{ 
    int i = 0; 
    while (str[i] != '\0') 
     ++i; 
    strSize = i; 
    strPtr = new char [i+1]; 
    for (i=0; i < strSize;++i) 
     strPtr[i] = str[i]; 
} 
+0

고마워! 강사는 항상 C 타입 함수를 사용하는 것이 좋지 않다고 강조하면서 두 번째 옵션을 사용했습니다. C 런타임 라이브러리를 피할 수 있다면 좋을 것입니다. – RedFred

+0

for 루프 테스트가'i <= strSize'로 변경되면이 코드는'i + 1' 크기의 문자열을 할당 했음에도 불구하고 새로운 문자열을 null로 종료 할 것이라고 생각하지 않습니다. 'str'의 끝에있는 널 문자는'strPtr'에 복사됩니까? 또는 null 종결 문자가 필요하지 않습니까? – Jason

+0

@RedFred : 귀하의 강사는 너트입니다. 게다가, std lib의 문자열 클래스가 당신에게 잘 맞지 않는 이유는 전혀 볼 수 없기 때문에 전체 작업은 꽤 바보입니다. –

3

은 요약하면 :

  • 내가
  • strSize가 초기화되지 않은 사용되는 날카로운 라인에 다시 초기화 위와 같은 줄에 (하나님이 무엇을 알고있다); strSize = strlen (str)이어야합니다.

    // as James perfectly illustrated 
    TStr::TStr(const char *str) 
    { 
        int i = 0; 
        while (str[i] != '\0') 
         ++i; 
        strSize = i; 
        strPtr = new char [i+1]; 
    
        while (*strPtr++ = *str++); // with a bit of k&R 
    } 
    
    //overload the concatenation oprerator 
    TStr TStr::operator += (const TStr& str) { 
        for(int i = 0; i < strSize; ++i) { 
         strPtr[i] += str.strPtr[i]; 
        } 
        return *this; 
    } 
    

    문제 :

    사람이이

    int i=0; 
    while (str[i] != '\0') { // as Seth pointed out it's '\0' 
        strPtr = new char [strlen(str)+1]; 
        for (i=0; i <strSize;++i) { // i is reinitialized here !!! 
         strPtr[i] = str[i]; 
        } 
        ++i; 
    } 
    strSize = i; 
    

가 더 건설 될 수있는 혼란의 종류의 말한대로

  • 문자열 터미네이터 chracter는
  • 잘못

    • 문자열을 연결하려는 경우 더 큰 저장소가 필요하므로 두 문자열을 함께 묶어 문자 배열을 다시 할당해야하고 그렇지 않으면
    • 문자열의 크기를 업데이트하지 마십시오. 이제는 더 크지 않습니다. 그것?
    • strPtr [i] + = str.strPtr [i]; 정말 가 이

      솔루션 (나는 그것을 향상시킬 수 절대적으로 확신하지만 당신은 시작 얻어야한다)

    8 비트
  • 에 저장된 정수를 추가하고 여기에 무슨 일을하는지 :

    //overload the concatenation oprerator 
    TStr TStr::operator += (const TStr& str) { 
        unsigned int i = 0; 
        while (str.strPtr[i] != '\0') 
         ++i; 
        // allocate the new buffer 
        char* newStr = new char[i + strSize + 1]; 
        // copy the old string 
        unsigned int j = 0; 
        for (; j < strSize; ++j) 
        { 
         newStr[j] = strPtr[j]; 
        } 
        // update the size 
        strSize += i; 
        // release the old buffer 
        delete[] strPtr; 
        // finally concatenate 
        char* copyPtr = newStr + j; 
        while(*copyPtr++ = *(str.strPtr)++); 
        // and swap the pointers 
        strPtr = newStr;  
        return *this; 
        } 
    
    +0

    또한''\ 0 '', _not_' '/ 0'' –

    +0

    @Seth Carnegie는 완전히 그것을 놓쳤습니다; 나는 첫눈에 내 눈에 뛰어 들었다. 수정; 덕분에 – celavek

    2

    왜 두 개의 루프 다른 내부 하나? 한 문자열에서 다른 문자열로 문자를 복사하는 것은 너무 어렵습니다. 한 루프 만 필요합니다. 여기에 몇 가지 코드가 있습니다

    //constructor; conversion from the char string 
    TStr::TStr(const char *str) { 
        strSize = strlen(str); 
        strPtr = new char [strSize+1]; 
        for (int i=0; i <strSize; ++i) { 
         strPtr[i] = str[i]; 
        } 
        strPtr[strSize] = '\0'; 
    } 
    

    훨씬 더 간단합니다!

    +0

    James Curran이 제안하고 strcpy를 사용하는 작업을 수행해야하지만 루프를 올바르게 작성한 모양을 보여주고 싶습니다. – john

    +0

    나는 동의하지 않는다. 자신 만의 문자열 클래스를 작성한다면, 아마도 손으로 물건을 조작하는 법을 알고 싶을 것입니다. 그래서'strcpy'는 쉬운 방법을 사용하고 스스로를 단락시키고 있습니다. –

    관련 문제