1

我是 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);
}

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

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

4

2 回答 2

6

声明c为一个int,它会工作。

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


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

int c;
while ((c = fgetc(src)) != EOF) {
    fputc(c, dst);
}

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

while (1) {
    int c = fgetc(src);
    if (c == EOF) break;
    fputc(c, dst);
}

fread()无论如何,使用and以块的形式读取和写入数据会更有效率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 */
}

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

于 2013-10-22T19:06:13.400 回答
3

EOF 不是一个,unsigned char而是一个int. 见原型fgetc

int fgetc(FILE *stream);
于 2013-10-22T19:06:05.367 回答