c while循环即使条件为假也保持运行

时间:2020-07-07 21:30:54

标签: c while-loop

我已经编写了这段代码来处理文件,它以256字节的块大小读取文件

#include <stdio.h>
#include <stdlib.h>

#define CHUNK_SIZE 256


int chunkable(size_t size, int chunk_size){
    return (size - chunk_size) > 0;
}

char * read_file(FILE *f, size_t fsize){
    char * fbuff = (char *) malloc(sizeof(char) * fsize);

    if(chunkable(fsize, CHUNK_SIZE)){
        while(fsize > 0){
            printf("reading chunk..., remaining: %d\n", fsize);
            fread(fbuff, CHUNK_SIZE, 1, f);
            fsize -= CHUNK_SIZE;
        }
    } else {
        fread(fbuff, CHUNK_SIZE, 1, f);
    }
    return fbuff;
}

int main(int argc, char *argv[]){
    FILE * f;
    int fsize;
    char * file_content;

    if(argc == 1){
        fprintf(stderr, "argument missing (filename) exiting...\n");
        return -1;
    }

    f = fopen(argv[1], "r");
    if(f == NULL){
        fprintf(stderr, "couldent open %s, exiting...\n", argv[1]);
        return -1;
    }
    
    fseek(f, 0, SEEK_END);
    fsize = ftell(f);
    fseek(f, 0, SEEK_SET);

    file_content = read_file(f, fsize);
    printf("file content: %s\n", file_content);
    
    free(file_content);
    fclose(f);
}

此行存在的问题

while(fsize > 0){...}

每次从文件读取块时,都会从要读取的剩余字节中减去块大小,而当没有剩余字节要读取时,while循环会停止读取,但是我得到的输出是

reading chunk..., remaining: 580
reading chunk..., remaining: 324
reading chunk..., remaining: 68
reading chunk..., remaining: -188
reading chunk..., remaining: -444
reading chunk..., remaining: -700
reading chunk..., remaining: -956
reading chunk..., remaining: -1212
reading chunk..., remaining: -1468
etc...

fsize是一个负数,这意味着fsize > 0false,而while循环保持4ever

1 个答案:

答案 0 :(得分:4)

size的类型为size_t,这是一种无符号类型。因此,当您继续从CHUNK_SIZE中减去size时,该值会回绕到非常大的正值。

打印时看到负值的原因是因为printf使用了错误的格式说明符。 %d需要一个int参数。您应该使用%zu代替size_t

您还没有检查fread的返回值。您读取的字节可能少于CHUNK_SIZE个字节,否则可能会出错。您还每次都读入同一缓冲区,覆盖以前的缓冲区。

您需要捕获返回值并进行检查。基于此,您可以从size中减去,还可以向fbuff添加一个偏移量,以附加到已经阅读的内容上。

    char *p = fbuff;
    while(fsize > 0){
        printf("reading chunk..., remaining: %zu\n", fsize);
        size_t len = fread(p, CHUNK_SIZE, 1, f);
        if (len == 0) {
            printf("error reading\n");
            break;
        }
        fsize -= len;
        p += len;
    }
    *p = 0;  // null terminate the string for printing