为什么我的文件IO在c中无限循环?

dan*_*007 1 c file-io

我是新来的c文件IO.我决定在c中编写一个简单的脚本,将文件复制到新文件中进行练习:

#include <stdio.h>

void main(int argc, char* argv[])
{
    if (argc != 3)
    {
        printf("Usage: ./myFile source destination");
        exit(-1);
    }

    FILE * src = fopen(argv[1], "r");
    if (src == NULL)
    {
        printf("source file not found", argv[1]);
        exit(-1);
    }

    FILE* dest = fopen(argv[2], "w");
    unsigned char c;
    do {
        c = fgetc(src);
        fputc(c, dest);
    } while (c != EOF);
}
Run Code Online (Sandbox Code Playgroud)

但是,我得到了一个无限循环.这是因为我从未真正打过一个名为EOF的角色吗?

另外,除了一次读取每个字符1之外,还有更快的方法来编写此脚本吗?

Ilm*_*nen 6

声明c为它int并且它将起作用.

EOF不是字符的有效值,因为如果是,则文件中存在该字符可能会误导代码,使其认为文件实际上没有结束.这正是为什么fgetc()实际上会返回一个int而不是一个char.


编辑:您的代码还有另一个错误:何时fgetc()返回EOF,您fputc()在结束循环之前传递该值,导致在输出文件的末尾出现一个额外的字符.(额外的字符将是你得到什么,当你投EOFunsigned char你的系统,通常是性格上的255 == 0xFF == (unsigned char) -1).为了解决这个问题,你可以重写你的循环是这样的:

int c;
while ((c = fgetc(src)) != EOF) {
    fputc(c, dst);
}
Run Code Online (Sandbox Code Playgroud)

或者,如果你不喜欢循环条件下的分配:

while (1) {
    int c = fgetc(src);
    if (c == EOF) break;
    fputc(c, dst);
}
Run Code Online (Sandbox Code Playgroud)

无论如何,使用fread()和以块为单位读取和写入数据会更有效率fwrite(),例如:

unsigned char buf[65536];
while (1) {
    int n = fread(buf, 1, sizeof(buf), src);
    fwrite(buf, 1, n, dst);
    if (n < sizeof(buf)) break;  /* end of file or read error */
}
Run Code Online (Sandbox Code Playgroud)

此外,包含一些错误检查是个好主意,因为读取和写入文件都会因各种意外原因而失败.您可以ferror()用来判断特定I/O流上是否发生了错误.