fgets()和Ctrl + D,是否可以结束3次? [英] fgets() and Ctrl+D, three times to end?

查看:54
本文介绍了fgets()和Ctrl + D,是否可以结束3次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我不明白为什么需要按三下 Ctrl + D 来发送EOF.

I don't understand why I need press Ctrl+D for three times to send the EOF.

此外,如果我按Enter键,则只需一个 Ctrl + D 即可发送EOF.

In addition, if I press Enter then it only took one Ctrl+D to send the EOF.

我如何进行更改,以便只用一个 Ctrl + D 即可检测到EOF?

How Can I make the change so that only took one Ctrl+D then it can detect the EOF?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUF_SIZE 1024

int main(){
    char buffer[BUF_SIZE];
    size_t msgLength = 1;
    char *msg = malloc(sizeof(char) * BUF_SIZE);

    msg[0] = '\0';
    printf("Message: ");
    while (fgets(buffer, BUF_SIZE, stdin)){
        char *old = msg;
        msgLength += strlen(buffer);
        msg = realloc(msg, msgLength);

        strcat(msg, buffer);
    }
    return 0;
}

推荐答案

您遇到的问题是终端没有EOF,因为它们不是文件,所以文件结尾"实际上并没有任何作用.感觉.相反,它们具有EOT(传输结束- Ctrl + D ),通常由于(高兴?)事故而被注册为stdio的EOF.

The problem you are having is that terminals don't have EOFs -- they're not files, so "end of file" doesn't really make any sense. Instead, they have EOT (end of transmission -- Ctrl+D), which generally registers as an EOF to stdio due to a (happy?) accident.

UNIX上的文件通过返回读取的大小为0来发出EOF信号,并且stdio会将任何大小为0的读取都视为EOF,而不管它是否从文件中读取.EOT导致终端立即返回,并且仅当输入缓冲区为空时,读取的大小将为0(触发stdio中的EOF).

Files on UNIX signal EOF by returning a size 0 read, and stdio treats any size 0 read as an EOF regardless of whether it is reading from a file or not. EOT causes a terminal to return immediately, which will be a size 0 read (triggering an EOF in stdio) if and only if the input buffer is empty.

最简单的解决方案就是不用担心-如果用户想在此处发出EOF,只需让用户多次按 Ctrl + D 即可.除非您遇到奇怪的计时问题,否则应该只需要两个.

The easiest solution is not to worry about it -- just let the user hit Ctrl+D multiple times if they want to signal an EOF here. It should only require two, unless you have odd timing issues going on.

如果确实要,您可以尝试确定是否遇到了EOT -如果fgets的结果未填充缓冲区且未以换行符结尾,则用户单击EOT进行传输,因此您可以对此进行测试并跳出循环.如果用户输入的数据恰好足以填充fgets缓冲区,然后达到EOT,则此操作将失败.如果用户键入"速度太快而使程序无法跟上(如果程序实际上没有等待输入时的EOT无效),它也可能会失败.我说输入"是因为该终端可能是伪终端,在另一端伪造了非常快的输入内容(包括EOT)

If you really want to, you can attempt to figure out if an EOT was hit -- if the result of fgets does not fill the buffer and does not end with a newline, then the user hit EOT to transmit it, so you could test for that and break out of the loop. This fails if the user enters exactly enough data to fill the fgets buffer and then hits EOT. It can also fail if the user is "typing" too fast for the program to keep up (an EOT while the program is not actually waiting for input has no effect). I say "typing" since the terminal might be a pseudo-terminal with something faking very fast input on the other end (including EOTs)

这篇关于fgets()和Ctrl + D,是否可以结束3次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆