我刚参加考试,要求我回答以下问题:


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) {

  };

};

我给出的答案是这样的(请参见下面的内容)。我的问题之一是,使用了许多额外的变量,这使我相信没有以最好的方式做到这一点,而另一件事是那没有用...。
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];
        }
    }
};

如果有人能大致解释我的问题,为什么?是回答该问题的最佳方式,我将不胜感激。同样,我的教授如何关闭“};”这样的每个类函数,我认为那仅用于结束类和构造函数。

非常感谢你的帮助。

最佳答案

首先,琐碎的};问题只是样式问题。当我将函数体放在类声明中时,我也会这样做。在这种情况下,;只是一个空语句,不会更改程序的含义。可以将其保留在函数末尾(但不能保留在类末尾)。

这是您编写的一些主要问题:

  • 您永远不会初始化str的内容。不能保证以\0字节开始。
  • 您永远不会初始化index,只在GetStrLen中进行设置。程序启动时,其值可能为-19281281。如果有人在调用InsertChar之前先调用GetStrLen怎么办?
  • 您永远不会在index中更新InsertChar。如果有人连续两次调用InsertChar怎么办?
  • 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();
      }
    }
    

    但是,您的字符串反转算法完全是错误的。考虑一下代码中所说的内容(假设index在其他地方已正确初始化和更新)。它说:“对于str中的每个字符,都用此字符向后覆盖整个revStr”。如果str"Hello World"开始,则revStr最终将以"ddddddddddd"结尾,因为dstr中的最后一个字符。

    您应该做的是这样的:
    void StrReverse() {
       char revStr[80];
       for (int i = 0; i < StrLen; ++i) {
         revStr[(StrLen - 1) - i] = str[i];
       }
    }
    

    注意它是如何工作的。说StrLen = 10。然后,我们将str的位置0复制到revStr的位置9,然后将str的位置1复制到9revStr等位置,依此类推,直到将StrLen - 1的位置str复制到revStr的位置0中。

    但是然后您在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];
       }
    }
    

    在不需要临时字符串revStr的情况下,有一些更聪明的方法可以执行此操作,但是以上内容功能完善,可以正确解决此问题。

    顺便说一句,您实际上根本不需要担心此代码中的NULL字节(\0)。您正在使用(或至少应该使用StrLen变量来跟踪字符串的长度)这一事实,因此不需要使用前哨结束符,因为使用StrLen时您已经知道应忽略str的内容。

    关于字符串类实现的C++考试,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2791852/

    10-12 17:54
    查看更多