关于字符串类实现的C++考试

Car*_*los 8 c++ string character

我刚参加考试时被问到以下问题:

为下面给出的代码编写GenStrLen,InsertChar和StrReverse方法的函数体.你必须考虑以下因素;

  • 如何在C++中构造字符串
  • 字符串不得溢出
  • 插入字符会使其长度增加1
  • StrLen = 0表示空字符串
class Strings {
  private:
    char str[80];
    int StrLen;
  public:

  // Constructor
  Strings() {
    StrLen=0;
  };

  // A function for returning the length of the string 'str'
  int GetStrLen(void) {

  };

  // A function to inser a character 'ch' at the end of the string 'str'
  void InsertChar(char ch) {

  };

  // A function to reverse the content of the string 'str'
  void StrReverse(void) {

  };

};
Run Code Online (Sandbox Code Playgroud)

我给出的答案是这样的(见下文).我的一个问题是,使用了许多额外的变量,这让我相信我没有以最好的方式做到这一点,而另一件事是不能正常工作....

class Strings {
private:
    char str[80];
    int StrLen;
    int index; // *** Had to add this ***
public:

    Strings(){
        StrLen=0;
    }

    int GetStrLen(void){
        for (int i=0 ; str[i]!='\0' ; i++)
            index++;
        return index;   // *** Here am getting a weird value, something like 1829584505306 ***
    }

    void InsertChar(char ch){    
        str[index] = ch;  // *** Not sure if this is correct cuz I was not given int index ***
    }

    void StrRevrse(void){
        GetStrLen();
        char revStr[index+1];
        for (int i=0 ; str[i]!='\0' ; i++){
            for (int r=index ; r>0 ; r--)
                revStr[r] = str[i];
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

如果有人能够大致解释一下回答问题的最佳方式和原因,我将不胜感激.我的教授怎么关闭每个类函数如"};",我认为它只用于结束类和构造函数.

非常感谢你的帮助.

Tyl*_*nry 17

首先,琐碎的};问题只是风格问题.当我将函数体放在类声明中时,我也这样做.在这种情况下,;它只是一个空语句,并不会改变程序的含义.它可以被排除在函数的末尾(但不是类的末尾).

这是你写的一些主要问题:

  1. 你永远不会初始化的内容str.它不能保证以\0字节开头.
  2. 你从不初始化index,你只在其中设置GetStrLen.程序启动时它可能具有值-19281281.如果有人在打电话InsertChar前打电话GetStrLen怎么办?
  3. 你永远不更新indexInsertChar.如果有人InsertChar连续两次打电话怎么办?
  4. StrReverse,你创建一个名为的反向字符串revStr,但是你永远不会对它做任何事情.字符串str保持相同的后缀.

对我来说令人困惑的部分是为什么你创建了一个新的变量index,可能是为了跟踪字符串的最后一个字符的索引,当已经有一个StrLen为此目的而调用的变量时,你完全忽略了它.一个过去的最后一个字符的索引字符串的长度,所以你应该保持字符串的长度是最新的,并使用它,例如

int GetStrLen(void){
  return StrLen; 
}

void InsertChar(char ch){    
  if (StrLen < 80) {
    str[StrLen] = ch;
    StrLen = StrLen + 1; // Update the length of the string
  } else {
    // Do not allow the string to overflow. Normally, you would throw an exception here
    // but if you don't know what that is, you instructor was probably just expecting
    // you to return without trying to insert the character.
    throw std::overflow_error();
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,您的字符串反转算法完全错误.仔细考虑代码所说的内容(假设index在其他地方正确初始化和更新).它说"对于每一个角色,用这个角色str覆盖整个revStr,向后,".如果str开始的话"Hello World",revStr最终会是"ddddddddddd",因为d是最后一个角色str.

你应该做的是这样的事情:

void StrReverse() {
   char revStr[80];
   for (int i = 0; i < StrLen; ++i) {
     revStr[(StrLen - 1) - i] = str[i];
   }
}
Run Code Online (Sandbox Code Playgroud)

注意它是如何工作的.这么说StrLen = 10.然后,我们复制位置0 str到9的位置revStr,然后放置1 str到位9revStr,等等,等等,直到我们拷贝位置StrLen - 1str成0位置revStr.

但是你有一个反向的字符串revStr,你仍然缺少你把它放回去的部分str,所以完整的方法看起来像

void StrReverse() {
   char revStr[80];
   for (int i = 0; i < StrLen; ++i) {
     revStr[(StrLen - 1) - i] = str[i];
   }
   for (int i = 0; i < StrLen; ++i) {
     str[i] = revStr[i];
   }
}
Run Code Online (Sandbox Code Playgroud)

并且有更聪明的方法可以做到这一点,你不必拥有一个临时字符串revStr,但上述功能完全正常,并且是问题的正确答案.

顺便说一句,你真的不需要担心\0这段代码中的NULL字节.您(或者至少应该)使用StrLen变量跟踪字符串长度的事实使得最终的哨兵不必要,因为使用StrLen您已经知道str应该忽略其内容的点.