2011-08-24 74 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

我不知道這是否是一個錯字,但它看起來像你的NULL終結符是使用正斜槓而不是轉義字符。 – Dawson

+0

你不需要在析構函數中檢查'if(strPtr)'。 delete []'NULL'指針是一個nop,不會崩潰。 –

+0

另外你可能不應該使用'assert',因爲它在發佈版本中被刪除。使用例外。 –

回答

2

你的構造函數是相當太亂了。

你使用我的兩個不同的東西 - 在同一時間。你也可以將str的全部內容複製到str中的每個字符一次strPtr中。

基本上,你必須決定,你打算使用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

即使你已經分配了一個大小爲'i + 1'的字符串,我不相信這段代碼將會終止新的字符串...如果for循環測試改爲'i <= strSize',那麼'str'結尾的空終止字符被複制到'strPtr'中?或者是不需要空終止的字符? – Jason

+0

@RedFred:你的講師是一個堅果。此外,整個任務非常愚蠢,因爲我完全沒有理由認爲std lib的字符串類不能很好地爲您服務。 –

3

總結:

  • 我重新初始化中的指示線
  • 了strsize用於初始化(天知道那裏的東西),在上述同樣的線;應該是strSize = strlen(str);
  • 一個字符串結束chracter是錯誤的
  • 的男子說這是一種亂

    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; 
    

更建設性的:

// 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; 
} 

問題:

  • 你想連接字符串,這意味着你需要一個更大的存儲空間來把兩個字符串放在一起,這意味着你需要重新分配你的字符數組,你不這樣做
  • 你不更新你的字符串的大小,它現在更大isn是嗎?
  • 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卡內基完全錯過了;我第一眼就跳進了我的眼簾;糾正;謝謝 – 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'正在簡單的解決你的問題。 –