【问题标题】:std::cin in an Array数组中的 std::cin
【发布时间】:2010-09-27 19:33:54
【问题描述】:

我是一名 CS 学生,试图掌握一些 C++ 基本概念。 我正在尝试从 std::cin 获取用户的输入并将其放入数组中。

示例:

输入 > ab ba cd[Entey 键被按下] 那么我希望数组包含 [ab][ba][cd]。

到目前为止我有:

#include <iostream>
#include <string>

int main(int argc, char** argv)
{
    std::cout << "Please give all strings seperated with white space (eg. ab ba cd) : ";
    std::string input[12];
    int i=0;

    while(std::cin >> input[i])
    {
        if(input[i].compare("\n")) break;
        i++;
    }
    //This will print contents of input[].
    for(int k = 0 ; k < 12 ; k++)
    {
        std::cout << "input[" << k << "] = " << input[k] << std::endl;
    }
    return 0;
}

但不幸的是,这仅将第一个字符串(在本例中为“ab”)存储在数组的第一个索引中。

如果我注释掉 if(input[i].compare("\n")) break;将产生分段错误。我猜是因为我超出了为数组分配的内存并写在了我不应该写的地方。

据我目前所知,std::cin 将首先将 ab 放入数组的 input[0] 中,并将剩余的字符串 [ba cd] 保留在流中,然后在下一个循环中(在 i++ 之后)[ba cd] 仍将在流中,cin 不会从键盘进一步读取(因为流中有东西),它应该将字符串 ba 放在 input[1] 上,等等。如果我错了,请纠正我。

注意:这不是家庭作业。我的课程大约在 1 个月后开始。非常感谢任何帮助。提前致谢

【问题讨论】:

    标签: c++


    【解决方案1】:

    std::string::compare 不返回布尔值——它返回一个整数。这用于对字符串进行排序。如果左侧字符串小于,它将返回 0,如果它们相同,则返回 0。 0 与布尔值 false 相同,因此只要字符串不是 "\n",您的 if 语句实际上就会中断——这就是您在第一次迭代时跳出循环的原因。

    另外,cin 不会给你换行符——所以检查“\n”是行不通的。在这里使用 getline 会有所帮助。

    这个页面对于使用cin/cout, istream/ostream, istringstream/ostringstream 非常有用:http://www.cplusplus.com/reference/iostream/istream/

    我将它保存在我的书签中,并定期使用它。

    所以,这可能是您想要做的:

    #include <sstream>
    std::string line;
    getline(std::cin, line);  // get the entire line
    
    // parse each string from the line
    std::istringstream stream(line);
    for (int i=0; stream.good(); i++) {
      stream >> input[i];
    }
    

    请注意,您还应该尝试允许超过 12 个输入字符串而不会崩溃,这可以通过向量来完成:

    // parse each string from the line
    std::vector< std::string > input;
    std::istringstream stream(line);
    while (stream.good())
    {
      std::string temp;
      stream >> temp;
      input.push_back(temp);
    }
    

    向量将随着您向其添加新字符串而动态增长。从这个意义上说,它有点像一个“更智能”的数组——你不需要在一开始就知道它是全尺寸的。您可以一次构建它。

    【讨论】:

    • 谢谢。它做了我想要的。我不得不#include 虽然我得到了错误:变量'std :: istringstream stream'有初始化程序但类型不完整。再次感谢!
    • 为什么不是惯用的while(stream &gt;&gt; input[i]) / while(stream &gt;&gt; temp)
    • @Cubbi - 个人喜好,有两个帐户。如果可能,我更喜欢“for”而不是“while”——它将索引的范围限制在最小的范围内(这通常是可取的)。此外,我已经看到太多通过尝试压缩代码和在“while”条件下进行实际工作而引入的错误。通过将其保留为布尔值,代码更清晰,更便于维护。您的建议同样有效,但归结为偏好(以及我上一份工作的严格编码标准)。
    • 我敢打赌,通过在输入操作之前检查流状态并忽略operator&gt;&gt;/getline() 的返回值(或忘记检查)会引入更多错误之后)。但我确实同意限制范围,在 Stroustrup 的示例中,总是在 while() 之前声明的临时变量也让我感到厌烦。
    • @Cubbi:优秀的点。是的,我已经看到了不检查返回值的错误(或者在一种情况下,试图检查,但把它搞砸了)。
    【解决方案2】:

    该代码可能会遇到的一个明显问题是空格被用作分隔符,因此您可能不会获得所需的行为。

    #include <iomanip>
    
    ...
    cin << ws;
    

    ... 在阅读任何内容之前。这可能会消除空格的问题,不过,我更愿意以其他方式读取字符串:

    #include <utility>
    #include <string>
    
    ...
    string str;
    getline( cin, str );
    

    这样,您的向量将永远不会出现缓冲区溢出问题。

    【讨论】:

    • 这会将输入存储到一个字符串中。因此,您建议将输入保存到一个字符串中,然后尝试分解子字符串(在这种情况下,它们之间有空格的单词)并将子字符串放入一个数组中。我也想过这个问题,但我想知道是否有可能。
    【解决方案3】:

    使用std::vector

    std::string tmp_str;
    std::vector<std::string> input_array;
    
    while(std::cin.peek() != '\n' &&  std::cin >> tmp_str) {
        input_array.push_back(tmp_str);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-10-12
      • 2011-06-12
      • 2020-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多