为什么“scanf”有效,但fgets在C中不起作用?

时间:2015-11-18 10:27:04

标签: c

在这看,这两个程序在我看来应该是等同的。但显然它们不是,因为第一个程序可行,第二个不可行。有人可以向我解释,为什么fgets()不能完成这项工作?

// FIRST PROGRAM : WORKS FINE
#include <stdio.h>
#include <stdlib.h>
int main()
{
    FILE *stream;
    char fileName[67];
    scanf("%s", fileName);
    printf("%s", fileName);
    stream = fopen(fileName, "r");
    char ch;
    if(stream){
        ch = fgetc(stream);
        while(!feof(stream)){
            putchar(ch);
            ch = fgetc(stream);
        }
        fclose(stream);
    }
}


// SECOND PROGRAM: DOES NOT WORK 

#include <stdio.h>
#include <stdlib.h>
int main()
{
    FILE *stream;
    char fileName[67];
    fgets(fileName, 67, stdin);
    printf("%s", fileName);
    stream = fopen(fileName, "r");
    char ch;
    if(stream){
        ch = fgetc(stream);
        while(!feof(stream)){
            putchar(ch);
            ch = fgetc(stream);
        }
        fclose(stream);
    }
}

我在控制台中输入“test.txt”两次,然后按Enter键。当然test.txt存在于正确的目录

2 个答案:

答案 0 :(得分:4)

原因是fgets()保留了输入的newline。您可以通过将打印语句更改为

来验证它是否存在
printf("[%s]", filename);

]出现在下一行时。您可以删除这样的尾随newline

#include <string.h>

...

filename [ strcspn(filename, "\r\n") ] = 0;

答案 1 :(得分:1)

您遇到的主要问题是由Weather Vane正确解决的,但我想指出您的代码的另一个问题:用于读取和写入文件内容的循环不正确。使用feof(stream)测试文件末尾会导致大多数时间的行为不正确。在您的情况下,来自stream的读取错误将导致程序无休止地循环,将0xFF个字节写入stdout

实现此循环有一种更简单和惯用的方法:

if (stream) {
    int ch;

    while ((ch = fgetc(stream)) != EOF) {
        putchar(ch);
    }
    fclose(stream);
}

正如您所看到的,当输入失败时,它会在正确的时间更简单且正确地测试EOF。它将fgetc()的返回值存储到int变量中,该变量能够保存fgetc()的所有可能返回值。使用int是必要的,因为将char值与EOF进行比较,如果char类型未签名,或者如果char已签名则可能会出现误报,则始终会失败并且值为'\377'

相关问题