Can';使用STDIN在fgetc()缓冲区中找不到EOF

Can';使用STDIN在fgetc()缓冲区中找不到EOF,c,eof,fgetc,C,Eof,Fgetc,编辑 问题的解决办法是理解Ctrl-D实际上在做什么。 在新的空行上,单个Ctrl-D将发出EOF信号。 但是,如果行中已经有字符,则第一个Ctrl-D会使行的内容回显到屏幕上(但不会写入STDOUT)。当缓冲区中已经有字符时,必须发出第二个Ctrl-D来发送信号EOF,从而将缓冲区写入STDOUT 这可以通过将输出重定向到文件来演示。 编辑 我正在使用fgetc()从stdin读取输入。我循环直到收到EOF。在循环中,我根据按下Ctrl-D之前键入的字符构建了一个字符串。但我无法找到退出循环的

编辑
问题的解决办法是理解Ctrl-D实际上在做什么。
在新的空行上,单个Ctrl-D将发出EOF信号。
但是,如果行中已经有字符,则第一个Ctrl-D会使行的内容回显到屏幕上(但不会写入
STDOUT
)。当缓冲区中已经有字符时,必须发出第二个Ctrl-D来发送信号
EOF
,从而将缓冲区写入
STDOUT

这可以通过将输出重定向到文件来演示。
编辑

我正在使用fgetc()从
stdin
读取输入。我循环直到收到EOF。在循环中,我根据按下Ctrl-D之前键入的字符构建了一个字符串。但我无法找到退出循环的方法,因为从中读取的缓冲区ch=fgetc()不包含EOF。(EOF仅触发fgetc()返回其第一个值。)

ungect()不允许将EOF推入缓冲区,推入任何其他字符都有可能与真实数据混淆,我被卡住了!!我已经阅读了很多答案,但它们没有解决这个问题,或者不适用于我试图实现的用例

我想能够计数,偷看,在标准输入缓冲区等

我真的不想读整行(或一次读X个字符),因为我正在处理从fgetc()到达(编辑)的每个字符

有没有关于如何克服这一困境的建议?(不使用NCurses)

我在用Ubuntu。EOF=Ctrl-D 以下是我正在使用的一些代码:

这与Jonathan的简单示例相同,但不是我想要的:

int main(int argc, char **argv) {

    int inputChr;

    do {
        inputChr = fgetc(stdin);
        if (inputChr != EOF) {
            fputc( inputChr, stdout);
        }
        if (feof(stdin)) {
            if (ferror(stdin)) {
                perror(NULL);
                return errno;
            }
        }
    } while (inputChr != EOF);
    return EXIT_SUCCESS;
}
但是,这会被卡住,但正在尝试执行我想要的操作(编辑),但第二次需要Ctrl-D:

char *buildLine (FILE *inputSource, char *currLine, int showTabs, int showNonPrint, int *haveLF) {

    int inputChr;
    char *thisLine = malloc(1);
    int inputSize;

    *haveLF = FALSE;
    while ( (inputChr = fgetc(inputSource)) != EOF ) {

        if (ferror(inputSource)) {
            perror(NULL);
        } else {
            if (inputChr == LF) {
                *haveLF = TRUE;
            } else {
                thisLine = strconcat(thisLine,(char *)&inputChr);
            }
        }
    }

    return thisLine;
}
还有一些被问及的代码:

char * strconcat ( char *str1, char * str2) {

    char *newStr = malloc(strlen(str1)+strlen(str2)+1);
    if (newStr == NULL) {
        return NULL;
    }
    strcpy(newStr,str1);
    strcat(newStr,str2);

    return newStr;
}
下面的版本逐个字符处理输入字符,其工作原理与
cat
类似。但我决定先将每个字符处理成一行,然后再应用一些需要实现的额外转换。这简化了状态机设计,但可能尝试构建行不是好的选择(不使用NCurses)(

int-echoint(文件*inputSource,文件*outputDestination,整数编号,整数显示端){
int haveNewLine=TRUE;
int lineNo=1;
int-inputChr;
做{
inputChr=fgetc(inputSource);
if(inputChr!=EOF){
if(编号和换行符(&H){
long lineNoSize=(long)log10(lineNo)+1;//有效楼层(log10(lineNo)+1)=数字

char*lineNoStr=(lineNoSize
EOF
通常是一个整数(不是
char
),并且它与任何有效字符的值都不相同


正常的C风格是终止用
\0
构建的字符串。当然,理论上可以读取
NUL
字符,如果您想处理这些可能性,您需要记录读取的字符数以及它们被读入的缓冲区。

必须有其他变化这个问题的答案已经足够好了,但这里还有一个

fgetc()
(和
getc()
getchar()
)返回的值是
int
,而不是
char
。它必须是
int
,因为可以返回的值集包括
char
的所有可能值和一个额外的值EOF,即负值虽然EOF通常是
-1
,但您不应该按照该假设编码

有两件事可能会出问题:

char c;

while ((c = fgetc(stdin)) != EOF)
如果类型
char
是有符号的,则某些字符(通常为0xFF,通常为ÿ,y-umlaut,Unicode U+00FF,带分音符的拉丁小写字母y)将被误解为在达到EOF之前指示EOF

如果类型
char
是无符号的,则您将永远不会检测到EOF,因为分配给
c
的值将是0xFF(正值),并且该值将永远不会与EOF(负值)进行比较

使用
ungect()
无法将EOF推回输入流,这是正确的

请注意,Control-D(或Windows上的Control-Z)不会向输入队列中添加字符。相反,它表示没有更多可用字符(稍微简化了一些事情),这意味着
read()
系统调用返回0字节读取,这意味着EOF

使用
getchar()
putchar()
将标准输入复制到标准输出的一个简单程序是:

int c;
while ((c = getchar()) != EOF)
    putchar(c);

您可以将其调整为使用
fgetc()
getc()
fputc()
putc()
如果您希望打开文件并读取这些文件。关键点是使用
int
来保存读取的值。

您使用的是哪个操作系统?如果要检查
ch
是否为
int
,请确保
int
EOF
。通常在Linux中,键入一些字符后按Ctrl-D会刷新输入流(这样您的程序就可以开始读取它了)但不会结束输入。再次按它,或在换行符后直接按它,会导致流结束。@MattMcNabb:
setvbuf
是标准C的一部分,如果
stdin
是FIFO,它将完美地工作。例如,在Unix系统中,如果
stdin
是tty,它至少不会工作,但这两者都不是必需的C标准也不禁止;不是因为stdin是行缓冲的,而是因为默认情况下,tty设备本身在输入ENTER或某些其他特殊字符之前不会向userland返回任何内容。OK;您需要在
malloc()后面加一个
*thisLine='\0';
在调用代码中;否则,您的读取超出了范围。您也像筛子一样泄漏;您需要
释放(str1);
strconcat()中。
同样,如果内存分配失败
int c;
while ((c = getchar()) != EOF)
    putchar(c);