【问题标题】:odd output from char arraychar 数组的奇数输出
【发布时间】:2013-03-11 12:43:32
【问题描述】:

可以这么说,我目前正在编写一个命令行“解析器”,到目前为止它一直在工作,直到我尝试了几种添加选项/参数的方法。

void parser::nextCom() {

    cout << parser::prompt; // parser::prompt = "> "
    string com;
    getline(cin, com);

    char the_command[5]; //  i want this to store the command e.g. "go" given that go is a command
    for (int i = 0; i < com.size(); i++) {
        if (com[i] == ' ') break;
        else the_command[i] = com[i];
    }

    cout << the_command << endl;
}

命令已复制,但在将the_command 打印到控制台时会显示一些非常不需要的字符。

如果我将“向北”作为命令传递,这就是我得到的结果:

goÌÌÌÌÌÌÌÌÌÌÌÌÌÌØNi

我不太确定 C++ 中的 char 数组,但我不知道如何获得此输出。任何帮助都将不胜感激。有关代码的任何问题或如果您需要更多我的代码,请发表评论,提前感谢

【问题讨论】:

    标签: c++ arrays char


    【解决方案1】:
    cout << the_command << endl;
    

    当您像这样打印char 数组时,会继续插入字符,直到在字符串中找到空字符\0

    在开始将字符从com 复制到the_command 之前,该数组完全未初始化。我将用问号表示这些未知字符(当然,它们实际上可能不是问号):

    ? ? ? ? ?
    

    这意味着您不知道数组中chars 的值是什么。然后,您只将字符 gothe_command 复制到 com,因此您的数组现在包含:

    g o ? ? ?
    

    因此,当您尝试输出此数组时,输出流不知道何时停止。您需要确保在o 之后插入\0。一种方法是:

    for (int i = 0; i < com.size(); i++) {
        if (com[i] == ' ') {
          the_command[i] = '\0';
          break;
        }
        else the_command[i] = com[i];
    }
    

    这将使数组像这样:

    g o \0 ? ?
    

    但是,您最好还是坚持std::string。我不想去想这个数组会给你带来哪些可以避免的麻烦。以下是我将如何编写你的函数:

    void parser::nextCom() {
        std::cout << parser::prompt;
    
        std::string command_line, command;
        std::getline(cin, command_line);
    
        std::stringstream command_line_stream(command_line);
        command_line_stream >> command;
    
        if (command == "go") {
          std::string direction;
          command_line_stream >> direction;
          go(direction);
        }
    }
    

    【讨论】:

    • 我想获取命令并使用 if 语句或 switch 语句来确定要运行的函数
    • 嗯,你有一点我会遇到 char 数组的问题,只是不知道如何使用字符串分隔命令,字符串流是否为我这样做?
    • @PurityLake std::stringstream 让它变得简单。您也可以使用std::string 来完成。
    • 为什么用std::stringstream代替std::istringstream
    • @David 要么就行。你可能是对的,std::istringstream 在这里更合适。
    【解决方案2】:

    在读取最后一个字符后,您不会以空值终止 the_command。或者进行任何边界检查。

    请改用std::string

    【讨论】:

      【解决方案3】:

      将代码改为:

      if (com[i] == ' ')
      {
         com[i] = '\0';
         break;
      }
      

      这将确保您的 char 数组末尾有一个空终止符。您看到垃圾的原因是因为std::cout 会愉快地打印字符,直到它看到一个空终止符。

      【讨论】:

        【解决方案4】:

        这是因为您的代码中有缓冲区溢出。您将不确定长度的字符串复制到 char[5] 缓冲区中...基本上,您的循环将输入字符串确定的字节数复制到 char[5] 数组的末尾,该数组不再以 null 结尾,所以“cout”只是读取,直到找到空字节。

        【讨论】:

        • 我的看法是第一个命令不超过 5 个字符
        • 嗯,理论上,if (com[i] == ' ') break; 应该防止输入 "go north" 的 buf 溢出。 (当然,代码本身仍然不安全,因为您不能保证您可能收到的所有输入的条件。)
        • 不错,不管怎样,缓冲区都不是空终止的,导致 cout 读得太远。
        【解决方案5】:

        基本上the_command[5] 包含垃圾,因为未初始化且不包含字符终止符。你可以先清除它,你会没事的

        for (i = 0; i < 5; i++)  {
            the_command[i] = 0; 
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-09-08
          • 1970-01-01
          • 2014-03-08
          • 2012-11-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多