终端中的 Ctrl+Z 行为

Ctrl+Z behaviour in terminal

提问人:Silversonic 提问时间:8/14/2017 最后编辑:FabrizioSilversonic 更新时间:9/18/2017 访问量:2053

问:

string s;
while(getline(cin,s)){
    cout << "---" << endl
    for(auto c: s) cout << int(c) << endl;   
}
cout << "Exiting";

如果我的输入是 +,那么我按一下回车键,我的程序就会立即退出。CtrlZ

^Z
Exiting

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

s^Z

---
115
26

我一直将 + 解释为 EOF 字符。 会继续,直到它达到这个字符,此时测试为假,我的程序将退出。我很好奇为什么我的程序将 + 解释为替代字符 26,具体取决于是否有前面的字符,以及为什么我需要在第二个示例中按两次 Enter?CtrlZgetlinegetlineCtrlZ

C++11 IOSTREAM Windows 控制台

评论

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

答:

2赞 Swift - Friday Pie 8/14/2017 #1

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

它由平台定义(或者更准确地说,由终端类型定义),如果字符立即发送到输入缓冲区或在发生某些刷新命令后。缓冲区刷新的常见原因是 EOL 字符,即您的 ENTER(CR - 回车)。Tat's 为什么程序在输入后收到 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 表:enter image description here