【问题标题】:Why does this program work?为什么这个程序有效?
【发布时间】:2023-03-07 22:59:01
【问题描述】:

我最近编写了一个程序,它接收输入的 char 数据,测试它是否可接受(a-z,# 标记输入的结尾)并将其放入堆栈中,然后测试它是否是回文。我希望一次输入一个字符,但如果我输入一个以磅结尾的字符串.. 有效。以下是一些相关代码:

char buffer;
bool pound_test = false;
bool palindrome = false;
bool keep_going = true;
stack<char> stack1, stack2, stack3;
string str = "";

cout << "Please enter a string, then end it with the pound sign. " << endl;

while(pound_test == false) {
    cin >> buffer;

    if((buffer >= 97) && (buffer <= 122))
    {
        stack1.push(buffer);
        stack2.push(buffer);
        str += buffer;
    }

    if((buffer >= 65) && (buffer <= 90)) {
        buffer = buffer + 32;
        stack1.push(buffer);
        stack2.push(buffer);
        str += buffer;
    }

    if(buffer == '#')
        pound_test = true;
}

因此,当用户输入一个长字符串(例如“racecar#”)并按下回车键时,程序会正确地将其放入堆栈中。我的问题很简单:为什么?数据是否必须一次输入一个字符才能正常工作,因为 cin 本身就在循环中,并且循环必须重复才能将多个字符输入堆栈,对吗?谢谢!

编辑:感谢大家的回答/cmets!快速而亲切的回复给我留下了深刻的印象。我肯定会再次使用这个网站。

【问题讨论】:

  • 这不是 cin 定义的工作方式。它将读取第一个空白。如果您想一次阅读一篇,请使用 cin.get 或 getchar
  • 我不明白,这甚至无法编译,;stack&lt;char&gt; 之后...
  • @Blindy:抱歉,这是格式错误:P
  • @frankc:如果操作数是std::stringchar*,它只会读取第一个空格。这不是这里的情况,它只是一个char,它只读取一个字符。该行为的原因不是您所建议的。
  • @clifford 你是对的,我没注意到

标签: c++ stack


【解决方案1】:

“系统”(操作系统、库等——取决于实现)吃了来自输入的数据字符串,但您的程序逐个字符地读取它。

【讨论】:

  • 理解“你的程序逐个字符读取”是因为使用了operator &gt;&gt; (char) 而不是operator &gt;&gt; (char*) - cin“知道”你一次只需要一个字符。
  • @Matt 你认为做我所做的 (cin >> char) 还是让用户输入一个 char 字符串然后使用循环输入它会更好,逐个字符 (好吧,输入我想要的字符),进入堆栈?
【解决方案2】:

cin 运算符从标准输入流中读取数据(如果未另外配置)。 stdin 的工作方式如下:您键入,当您按下Enter 时,它会发送到stdin,因此cin 会读取整个字符串,直到您按下Enter

如果你想逐个字符地读取,你应该使用getchar

【讨论】:

  • cin 在 >> 的右侧操作数是字符时不会读取整行。仅在换行符用于行缓冲控制台输入之后,数据才可用于 cin。底层系统级控制台 I/O 执行缓冲而不是 cin 对象。
  • looked 起来了,事实上,istream 的 >> 有一个 char 的特殊情况,它只会从流中提取一个字符。正如您所说,这意味着缓冲是在不同的级别上执行的。谢谢!
  • 这并不是一个真正的“特殊情况”,不同类型的多重重载是 C++ iostreams 如何避免需要格式说明符,例如 C 的 stdio scanf()。这相当于 scanf() 的 %c 格式说明符,而您正在考虑 %s 等价物。与scanf() 不同,它是可扩展的;您可以根据需要添加自己的重载来初始化其他对象类。
【解决方案3】:

cin &gt;&gt; buffer; 看到您的键盘输入的方式不是您的程序的属性,而是操作系统、Shell、C 运行时的组合以及我忘记的上千种东西的组合。

【讨论】:

    【解决方案4】:

    大多数系统中的控制台输入(通过cin std::istream 对象)是行缓冲的。因此,当您为单个字符调用 cin::operator&gt;&gt; 时,该函数实际上在您按下换行符之前不会返回(因为在此之前底层 I/O 系统不会为 cin 提供数据)。任何输入到&lt;newline&gt; 的数据(包括&lt;newline&gt;)都将被缓冲,随后对cin::operator&gt;&gt; 的调用将从缓冲区中得到服务,直到用完为止。

    在这种情况下cin &gt;&gt; buffer,其中buffer 的类型为char 确实会得到一个字符,但在此之前,控制台会缓冲一整行,并将使用它来满足后续控制台输入操作。

    如果您在调试器中单步调试代码,您可能会更清楚操作。

    【讨论】:

    • 谢谢!这几乎回答了我的问题。因此,如果程序中有另一个对 cin 的调用,并且缓冲区中还有字符,它会从那里读取而不是用户输入?
    • @Nathan:是的,我在答案中添加了更多内容,可能会澄清这一点。
    【解决方案5】:

    虽然关于操作系统缓冲的所有答案都是正确的,但我认为混淆可以追溯到cinoperator &gt;&gt; (char);因为 C++ 可以根据参数类型重载方法,operator &gt;&gt; 的 char 版本一次只分配一个字符,即使整个字符串都被缓冲了。我相信您认为operator &gt;&gt; 应该尝试将整个字符串放入您的角色中;但由于它“知道”你一次读一个字符,它一次只分配一个字符。我不确定这是否是 cin 的指定行为,但这似乎是正在发生的事情。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-21
      相关资源
      最近更新 更多