read() 系统调用读入一个额外的 0

Ans*_*dai 1 c system-calls

我编写了一个函数,它使用 read() 系统调用从文件中读取数字并将它们放入数组中。但是,我注意到最后总是包含一个额外的 0。

       int numberRead = 0;
       int fp;
       char buf[512];
       size_t nbytes = sizeof(buf);
       int n;
       int counter = 0;
       char* ptr;
       size_t curSize = 16;
       int radix = hexFlag ? 16 : 10;


        *array = malloc(curSize * sizeof(*array));

        fp = open(fname, O_RDONLY);      

            if (fp == -1) {
                    return -1;
            }

        while ((n = read(fp, buf, nbytes)) != 0) {
            ptr = strtok(buf, " \n");
            while(ptr) {
                if (counter >= curSize) {
                    curSize += 16;
                    *array = realloc(*array, curSize * sizeof(**array));
                }
                (*array)[counter++] = strtol(ptr, NULL, radix);
                ++numberRead;
                ptr = strtok(NULL , " \n");
            }
        }
Run Code Online (Sandbox Code Playgroud)

原因是由于strtok吗?

Chr*_*odd 5

read不会 NULL 终止它读入的缓冲区,因此此代码可能会在上次读取结束后获得一个额外的数字,该数字在上次读取的缓冲区中徘徊。添加行:

buf[n] = 0;
Run Code Online (Sandbox Code Playgroud)

紧接在while调用 read的第一行之后。

此外,读取的块read不一定对应于行或其他任何特定内容。如果您正在读取文件,则 read 调用可能会返回以多位数字中间结尾的字符块,在这种情况下,您的代码会将其拆分为两个数字。为了避免这种情况,您不需要尝试对读取的最后几个字符(最后一个空格读取之后的所有字符)进行标记/解码,而是将它们添加到下一次读取之前。

你最终需要这样的代码:

char buf[1024], *end;
size_t n;
size_t leftover = 0;
while ((n = read(fp, buf+leftover, sizeof(buf)-leftover-1)) > 0 || leftover > 0) {
    buf[leftover+n] = 0;
    ptr = strtok(buf, " \n");
    while(ptr) {
        if (counter >= curSize) {
            curSize += 16;
            *array = realloc(*array, curSize * sizeof(**array));
        }
        (*array)[counter] = strtol(ptr, &end, radix);
        if (end == buf+leftover+n && n > 0) {
            leftover = ptr-end;
            memmove(buf, ptr, leftover);
            break; }
        ++counter;
        ++numberRead;
        ptr = strtok(NULL , " \n");
    }
    if (!ptr) leftover = 0;
}
Run Code Online (Sandbox Code Playgroud)