cin与CTRL+z的问题

Posted xuan01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cin与CTRL+z的问题相关的知识,希望对你有一定的参考价值。

这个问题源自于之前调试AVL树时,要输入两次值,我在第一次cin时,用CTRL+Z结束输入,之后的cin 程序执行直接就跳过了,不能输入了;;;

解决方法: 在第一次输入后的程序加上以下两句时就可以了;

cin.clear();
//cin.sync();

 分析:CTRL + Z后;eof、fail 位都会true;clear()之后good位位true;

io标准库条件状态成员;

代码测试:

#include <bits/stdc++.h>
using namespace std;
int main()
    int num;
    cout << "first num :" << endl;
    while(cin >> num)  
    cout << "first num  is:" << num << endl;
    cout << "goodbit:" << cin.good() << endl;
    cout << "eofbit :" << cin.eof() << endl;
    cout << "failbit:" << cin.fail() << endl;
    cout << "badbit :" << cin.bad() << endl;
    
    cin.clear();
    cout << "after clear()" << endl;
    cout << "goodbit:" << cin.good() << endl;
    cout << "eofbit :" << cin.eof() << endl;
    cout << "failbit:" << cin.fail() << endl;
    cout << "badbit :" << cin.bad() << endl;

    int tmp;
    cin >> tmp;
    cout << "second num: " << tmp << endl;
    system("pause");
    return 0;

/*
没有cin.clear()的输出:
first num :
10
^Z
first num  is:10
goodbit:0
eofbit :1
failbit:1
badbit :0
second num: 6422400
请按任意键继续. . .
*/

/*
first num :
10
^Z
first num  is:10
goodbit:0
eofbit :1
failbit:1
badbit :0
after clear()
goodbit:1
eofbit :0
failbit:0
badbit :0
11
second num: 11
请按任意键继续. . .
*/

 

为啥我需要多个 EOF (CTRL+Z) 字符?

【中文标题】为啥我需要多个 EOF (CTRL+Z) 字符?【英文标题】:Why do I require multiple EOF (CTRL+Z) characters?为什么我需要多个 EOF (CTRL+Z) 字符? 【发布时间】:2011-08-05 00:51:19 【问题描述】:

作为一点背景知识,我对 C 编程语言很陌生,因此一直在尝试完成 Kernighan & Ritchie 手册第二版中的一些练习。我确实意识到,通过更多地利用标准库,我可能可以更简洁地处理某些问题,但我正在努力使我的有用命令库尽可能与本书保持同步。

如果有什么不同,我将在 Windows XP 环境中使用 Tiny C 编译器 (TCC) 编译我的源代码,并在 XP 控制台 (cmd.exe) 中执行二进制文件。

问题:处理End-of-File (EOF) characters。我整理了一个小测试用例来说明这个问题。该程序似乎处理了 EOF 字符(部分)。我将尝试通过示例输入/输出来演示该问题。

#include <stdio.h>

int main() 

    int character, count;

    character = 0;
    character = getchar();

    for (count = 0; character != EOF; ++count) 
    
        character = getchar();
    

    printf("Count: %d", count);
    return 0;

示例输入 1:abcd^Z[enter](其中 ^Z/CTRL+Z 代表 EOF 字符,[enter] 代表 Enter 键。)

示例输出 1:Count: 4(等待更多输入或在 ^C/^Z[enter] 上正确结束)

示例输入 2:abcd^Zefgh

示例输出 2:Count: 4(等待更多输入或在 ^C/^Z[enter] 正确结束)

正如在两个示例中所指出的,在启动 ^C/^Z[enter] 序列之前不会输出字符计数。在启动之前,程序会等待(实际上是处理)更多输入。但是,如示例 2 中所述,当程序遇到初始 ^Z 时,它会停止处理该行输入,等待更多输入或在启动 ^C/^Z[enter] 序列时返回正确的计数。

我不明白为什么程序只部分处理了 EOF 字符。在我看来,如果它截断样本 2 的结尾,它也应该完全脱离循环。任何想法为什么在识别 EOF 字符后程序不会立即打印当前计数并退出?

【问题讨论】:

作为更新,我确定 Tiny C 编译器确实可以识别 EOF 字符 ^Z。 ^Z(输入)和 EOF(符号常数)都被识别为值 -1。 另一个更新,我将另一个符号常量 EOT(传输结束)定义为 4。现在,当我针对这个常量进行测试时,通过发出 ^D(识别为值 4),一切都按计划进行。但是,如果将 EOT 定义为 -1,作为 EOF,程序会再次中断。这看起来确实很奇怪,因为 ^Z 被程序识别为值 -1。 您误将^Z 视为一个角色。在终端/控制台级别指定生成 EOF 的任何字符都会在到达您的应用程序之前由另一层解释。在 Windows 上,^D 默认情况下并不特殊,因此您只需获取字节 ^D (4)。 @R.. 是的,我相信你是对的。在进一步思考了这个问题之后,我得出的结论是 ^Z 在单独读取时被识别为-1(可能是因为 cmd 截断了进一步的输入,导致读取长度为零)。我只是在这里猜测,但是在考虑场景 2 时这是有道理的,因为程序在等待进一步输入时只读取“abcd”。似乎 ^Z(不像 ^D 实际代表 ASCII 字符 4)只是虚无/虚无的符号表示。再次感谢您的洞察力。你肯定帮助我巩固了这个概念。 【参考方案1】:

我猜标准输入是行缓冲的(它在 Unix 上)。 DOS 有一些getch()getche() 函数比stdio 低级,因此它们绕过stdio 缓冲。我不知道如何在 Windows 上禁用输入缓冲,在 Unix 上是通过将终端设置为非规范模式来完成的。

【讨论】:

【参考方案2】:

这可以追溯到计算的石器时代。至少 CP/M,在早期的 DEC 操作系统中可能更久。 CP/M 不存储文件的大小,它只记录磁盘扇区的数量,每个扇区 128 字节。二进制文件不是问题,当程序足够时,程序就会停止读取。但是对于文本文件来说肯定是个问题。

因此,按照惯例,文本文件的文件结尾标记为代码 0x1a,Control+Z。由于遗留的文本文件大于其中的文本量,因此必须在每一代 CRT 实现中延续这一点。 Windows 对此并不在意,这纯粹是一个 CRT 实现细节。这就是为什么在控制台输入 Ctrl+Z 并没有做任何特别的事情的原因。按下 Enter 后,cmd.exe 中的 CRT 将再次调用旧行为并声明 EOF。

【讨论】:

【参考方案3】:

这个答案是 unix-ish,但我认为类似的现象正在 Windows 上发生。 EOF 的基本形式是长度为零的read。在交互式输入设备(终端)上,有一种特殊机制可以在输入流中包含 EOF,但如果已经有输入要读取,它将与该输入一起被消耗(导致非零长度 read)因此从未被应用程序注意到。只有当 EOF 发生而没有预先缓冲的输入时,应用程序才能注意到并采取行动。

如果您可以访问 Linux(或其他 *nix)系统,请编写一个类似的测试程序并在 strace 下运行它。观察发生的底层read 调用,这种不直观的行为的原因是有道理的。

【讨论】:

非常感谢您提供的信息。我目前没有运行 *nix 机器,但必须在接下来的几天内设置一台,唯一目的是测试这个假设。但是,如果按照建议使用 EOF 信号,我想知道为什么程序不能继续愉快地读取行中剩下的任何内容(除非 cmd 在程序到达那么远之前在 ^Z 之后截断。) 这可能是我不熟悉的 Windows 的一个特性。 :-)【参考方案4】:

当您键入 ^Z 时,Windows 不会自动生成 EOF;这只是从 DOS 继承下来的约定。 C 编译器的运行时必须识别它并设置 EOF 标志,我猜 Tiny C 不会这样做。

^C 另一方面 被 Windows 命令环境识别。这并不一定意味着EOF,我认为它更像是一个中止信号。

【讨论】:

是的,^C/CTRL+C 发送一个 SIGINT 信号或导致当前正在运行的进程退出的东西(这就是它无论如何都可以工作的原因)。但是,我仍然不明白为什么 abcd^Zefgh 仅在未处理 EOF 字符时才计算 abcd 。如果是的话,为什么程序会继续循环并收集输入。 @bfisher,我认为现在接受这个答案还为时过早 - 我没有完全回答这个问题,是吗?【参考方案5】:

我不确定 TCC,但在很多(大多数?)情况下,您需要或多或少地单独输入 ^Z 才能将其识别为 EOF(即,您需要一个序列的 [enter]^z[enter])。

【讨论】:

以上是关于cin与CTRL+z的问题的主要内容,如果未能解决你的问题,请参考以下文章

关于cin.get输入一段字符加ctrl+z函数返回值不为0的问题

cin 字符串输入

while(cin>>str)循环结束问题&cin相关问题

cin函数返回的是啥??

Linux Ctrl+c与ctrl+z的区别

意外 ctrl + Z 后 localhost 超时