Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;关于字符串类实现的考试_C++_String_Character - Fatal编程技术网

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

C++ C++;关于字符串类实现的考试,c++,string,character,C++,String,Character,我刚刚参加了一次考试,被问到以下问题: 为下面给定的代码编写GenStrLen、InsertChar和StrReverse方法的函数体。你必须考虑以下几点: 如何在C中构造字符串++ 字符串不能溢出 插入字符会使其长度增加1 空字符串由StrLen=0表示 我给出的答案是这样的(见下文)。我的一个问题是使用了许多额外的变量,这让我相信我没有尽可能地做到最好,另一个问题是,这不起作用 class Strings { private: char str[80]; int Str

我刚刚参加了一次考试,被问到以下问题:

为下面给定的代码编写GenStrLen、InsertChar和StrReverse方法的函数体。你必须考虑以下几点:

  • 如何在C中构造字符串++
  • 字符串不能溢出
  • 插入字符会使其长度增加1
  • 空字符串由StrLen=0表示

我给出的答案是这样的(见下文)。我的一个问题是使用了许多额外的变量,这让我相信我没有尽可能地做到最好,另一个问题是,这不起作用

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

如果有人能向我大致解释一下什么是回答这个问题的最佳方式,以及为什么,我将不胜感激。还有,为什么我的教授会关闭每个类函数,比如“};”,我认为它只用于结束类和构造函数

非常感谢你的帮助

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

您得到一个奇怪的值,因为您从未初始化索引,只是开始递增它。

初始化字符数组时,应将其第一个元素设置为0,对于
索引
,也应设置为0。因此,在
GetStrLen
中你会得到一个奇怪的长度,因为当你找到你正在寻找的0时,这取决于神

[Update]在C/C++中,如果不显式初始化变量,通常会用随机垃圾(分配给它们的原始内存的内容)填充它们。此规则也有一些例外,但最佳实践是始终显式初始化变量[/Update]

InsertChar
中,您应该(在检查溢出后)使用
StrLen
索引数组(因为注释指定“在字符串“str”的末尾插入字符“ch”),然后设置新的终止0字符并递增
StrLen
您的
GetStrLen()
函数不起作用,因为
str
数组未初始化。它可能不包含任何零元素

您不需要
索引
成员。只需使用
StrLen
跟踪当前字符串长度

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

str[strlen-1]=ch; //overwrite the null with ch
str[strlen]='\0'; //re-add the null
strlen++;

你不需要计算长度。你已经知道了,是斯特伦。此外,原始问题中没有任何内容表明缓冲区应包含以null结尾的字符串

int GetStrLen(void){
    return strLen;
}
这里只使用断言,但另一个选项是抛出异常

void InsertChar(char ch){
    assert(strLen < 80);
    str[strLen++] = ch;
}
void InsertChar(char-ch){
断言(strLen<80);
str[strLen++]=ch;
}
反转字符串只是交换str缓冲区中的元素的问题

void StrRevrse(void){
    int n = strLen >> 1;
    for (int i = 0; i < n; i++) {
        char c = str[i];
        str[i] = str[strLen - i];
        str[strLen - i] = c;
    }
}
void strevrse(void){
int n=strLen>>1;
对于(int i=0;i
首先,琐碎的
}问题只是风格问题。当我将函数体放入类声明中时,我也会这样做。在这种情况下,
只是一个空语句,不会改变程序的含义。它可以不在函数的末尾(但不能在类的末尾)

以下是您所写内容的一些主要问题:

  • 您从不初始化
    str
    的内容。不能保证以
    \0
    字节开始
  • 您从不初始化
    索引
    ,只在
    GetStrLen
    中设置它。当程序启动时,它的值可能为-19281281。如果有人在调用
    GetStrLen
    之前调用
    InsertChar
    ,该怎么办
  • 您从不在
    InsertChar
    中更新
    index
    。如果有人连续两次调用
    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();
      }
    }
    
    注意它是如何工作的。假设StrLen=10
    。然后我们将
    str
    的位置0复制到
    revStr
    的位置9,然后将
    str
    的位置1复制到
    revStr
    的位置
    9
    等,直到我们将
    str
    的位置
    StrLen-1
    复制到
    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];
       }
    }
    
    void StrReverse(){
    char revStr[80];
    对于(int i=0;i
    有一些更聪明的方法可以做到这一点,你不必有一个临时字符串
    revStr
    ,但是上面的方法功能完善,可以正确地回答这个问题


    顺便说一下,在这段代码中根本不需要担心空字节(
    \0
    s)。事实上你是(或者至少你应该是)使用
    StrLen
    变量跟踪字符串的长度会使end sentinel变得不必要,因为使用
    StrLen
    您已经知道应该忽略
    str
    内容的点。

    我将使用
    StrLen
    跟踪字符串的长度。由于长度也表示字符串的结尾,因此我们可以使用该长度插入:

    int GetStrLen(void) {
        return StrLen;
    }
    
    int InsertChar(char ch)
    {
        if (strLen < sizeof(str))
        {
            str[StrLen] = ch;
            ++strLen;
        }
    }
    
    void StrReverse(void) {
        for (int n = 0; n < StrLen / 2; ++n)
        {
            char tmp = str[n];
            str[n] = str[StrLen - n - 1];
            str[StrLen - n - 1] = tmp;
        }
    }
    
    int GetStrLen
    
    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];
       }
    }
    
    int GetStrLen(void) {
        return StrLen;
    }
    
    int InsertChar(char ch)
    {
        if (strLen < sizeof(str))
        {
            str[StrLen] = ch;
            ++strLen;
        }
    }
    
    void StrReverse(void) {
        for (int n = 0; n < StrLen / 2; ++n)
        {
            char tmp = str[n];
            str[n] = str[StrLen - n - 1];
            str[StrLen - n - 1] = tmp;
        }
    }
    
    class Strings {
      private:
        char str[80];
        int StrLen;
      public:
    
      // Constructor
      Strings() {
        StrLen=0;
        str[0]=0;
      };
    
      // A function for returning the length of the string 'str'
      int GetStrLen(void) {
        return StrLen;
      };
    
      // A function to inser a character 'ch' at the end of the string 'str'
      void InsertChar(char ch) {
        if(StrLen < 80)
          str[StrLen++]=ch;
      };
    
      // A function to reverse the content of the string 'str'
      void StrReverse(void) {
        for(int i=0; i<StrLen / 2; ++i) {
          char aux = str[i];
          str[i] = str[StrLen - i - 1];
          str[StrLen - i - 1] = aux;
        }
      };
    };
    
    #include <iostream>
    
    void swap_chars(char* left, char* right) {
        char temp = *left;
        *left = *right;
        *right = temp;
    }
    
    class Strings {
    private:
        char m_buffer[80];
        int m_length;
    public:
    
        // Constructor
        Strings() 
            :m_length(0) 
        {
        }
    
        // A function for returning the length of the string 'm_buffer'
        int GetLength() const {
            return m_length;
        }
    
        // A function to inser a character 'ch' at the end of the string 'm_buffer'
        void InsertChar(char ch) {
            if (m_length < sizeof m_buffer) {
                m_buffer[m_length++] = ch;
            }
        }
    
        // A function to reverse the content of the string 'm_buffer'
        void Reverse() {
            char* left = &m_buffer[0];
            char* right = &m_buffer[m_length - 1];
            for (; left < right; ++left, --right) {
                swap_chars(left, right);
            }
        }
    
    
        void Print() const {
            for (int index = 0; index < m_length; ++index) {
                std::cout << m_buffer[index];
            }
            std::cout << std::endl;
        }
    };
    
    int main(int, char**) {
        Strings test_string;
    
        char test[] = "This is a test string!This is a test string!This is a test string!This is a test string!\000";
        for (char* c = test; *c; ++c) {
            test_string.InsertChar(*c);
        }
    
        test_string.Print();
        test_string.Reverse();
        test_string.Print();
    
        // The output of this program should look like this...
        // This is a test string!This is a test string!This is a test string!This is a test
        // tset a si sihT!gnirts tset a si sihT!gnirts tset a si sihT!gnirts tset a si sihT
    
        return 0;
    }