调用系统调用读取会导致无限循环

时间:2018-02-10 21:39:27

标签: c unix file-descriptor

我想创建一个非常简单的控制台应用程序来取代Unix命令wc -c。为此,我只需要将字节计入文件并在控制台中输出。

如果我的应用程序没有提供参数,它会从标准输入中读取它们(这部分我已经完成了工作)。但是,如果我决定提供更多参数(有效和现有文件名),我应该将它们中的每一个都计算在内。

到目前为止一切顺利。这是代码

const int __OPEN_ERROR = 48;

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

    if(argc == 1) {
        char buf[3];
        int count = 0, lines = 0;
        while(read(0, buf, 1) != 0) {
            count++;
            if(buf[0] == '\n')
                lines++;
        }

        printf("Count:%d\n", count);
        printf("Lines:%d\n", lines);
    }
    else {
        int fd, bytes = 0;
        char buf[3];

        for (int arg = 1; arg <= argc; arg++) {
            if ((fd = open(argv[arg], O_RDONLY) < 0)) {
                exit(__OPEN_ERROR);
            }
            while (read(fd, buf, 1) != 0) { // <-- this here leads to infinite loop.
                printf("%s", buf);
                bytes++;
            }

            printf("%d %s", bytes, argv[arg]);
        }
    }

    exit(0);
}

请不要在意这段代码写得多么糟糕,这是我第一天探索C,现在我想要的只是工作解决方案。

注意两个读取是如何相同但后一个读入无限循环,这是我无法理解的原因。是的,打开文件成功。

1 个答案:

答案 0 :(得分:1)

你的循环错了,应该是:

char buf;
...
while (read(fd, buf, 1) == 1) {
    printf("%c", buf);
    bytes++;
}

read允许您从文件描述符中读取字节。给定的数字表示n是一个请求,这意味着read最多读取n个字节,返回的值恰好是有效读取的字节数。如果你想读取1个字节,那么测试它是否读取1个字节。其次,当您逐个读取字节(或字符)时,结果是一个字符,应该打印为。 %c告诉printf将值打印为char(%s是打印C字符串)。

另一个错误是控制arg循环,应该是:

for (int arg = 1; arg < argc; arg++) // strict test...arg from 0 to argc-1 (included) or argc (excluded)

您还必须在每次arg循环时将字节数重置为0,并关闭每个未使用的文件,因此:

for (int arg = 1; arg < argc; arg++) {
    char buf;
    int bytes = 0;
    int fd;
    if ((fd = open(argv[arg], O_RDONLY) < 0)) {
        exit(__OPEN_ERROR);
    }
    while (read(fd, buf, 1) == 1) {
        printf("%c", buf); // optionnal, counting may not print...
        bytes++;
    }
    close(fd);
    printf("%d %s", bytes, argv[arg]);
}