【问题标题】:Ctrl+Z behaviour in terminal终端中的 Ctrl+Z 行为
【发布时间】:2018-01-21 17:51:21
【问题描述】:
string s;
while(getline(cin,s)){
    cout << "---" << endl
    for(auto c: s) cout << int(c) << endl;   
}
cout << "Exiting";

如果我的输入是Ctrl+Z,那么我按一次回车,我的程序立即退出。

^Z
Exiting

如果我在按Ctrl+Z之前输入了一个字符,那么我必须按两次回车,我的程序不会退出。

s^Z

---
115
26

我一直将 Ctrl+Z 解释为 EOF 字符。 getline 将继续直到它到达这个字符,此时 getline 测试为 false 并且我的程序将退出。我很好奇为什么我的程序将 Ctrl+Z 解释为 substitute character 26,这取决于是否有前面的字符,以及为什么它对我来说是必要的在第二个示例中按两次 Enter 键?

【问题讨论】:

  • 行首的 Ctrl+Z 由 Windows 控制台本身处理,但奇怪的是它仅适用于一般的 ReadFile 调用,而不是特定的 ReadConsole 调用。在这种情况下,读取将 lpNumberOfBytesRead 返回为 0,这是 C/C++ 运行时将其解释为 EOF。
  • 在第二个例子中必须按两次回车是奇怪的。它将 SUB ("\x1a") 字符保留在缓冲区中并删除其后的所有内容,包括 CRLF 行结尾。如果它没有在结果中保留 SUB,那几乎是可以理解的,因为 Windows C 和 C++ 运行时将此字符视为 EOF 标记。 ISTM 此处的正确行为应该是从getline 返回,并在 SUB 之前添加任何内容,而不是将其保留在缓冲区中并继续阅读。

标签: windows c++11 iostream windows-console


【解决方案1】:

26 是您平台上的 ^Z 代码,而 ^Z 是终端的 EOF 标记,这是真的。编码小于 32 的字符是 ASCII 兼容平台的控制字符,我希望你知道。 26 不是替代字符,它是实际控制代码,^Z 或一些“错误”字符是替代字符。 getline 读取输入直到 EOL(行尾,由 ASCII 指定为 CR)或 EOF(文件结束,流结束,指定为 SUB)在流中遇到,所以 ^Z 在第二次调用时读取getline。这种行为是绝对正确的。

它是由平台定义的(或者,更准确地说,是终端类型)如果字符被立即发送到输入缓冲区,或者在某些刷新命令发生之后。缓冲区刷新的通常原因是 EOL 字符,即您的 ENTER(CR - 回车)。这就是为什么程序在您的情况下 Enter 后收到 EOF 的原因。请注意,有些平台使用 LF(换行)作为 EOL,有些平台使用一对 LF+CR。 C 文字 '\n' 将被正确翻译成特定的 EOL 标记。

注意,你可以使用不同的分隔符:

template< class CharT, class Traits, class Allocator > 
std::basic_istream<CharT,Traits>& getline( 
         std::basic_istream<CharT,Traits>& input,
         std::basic_string<CharT,Traits,Allocator>& str,
         CharT delim );

带有替代 Control+ 的 ASCII 表:

【讨论】:

    猜你喜欢
    • 2017-05-04
    • 2017-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多