While 循环不能不以 eof 终止

While loop cannot be not terminated with eof

提问人:ECH 提问时间:12/5/2022 更新时间:12/5/2022 访问量:89

问:

char buf_in()
{
    if(read_pos==16)
    {
        read_pos=0;
        read(fd_in,buffer_in,16);
    }
    return buffer_in[read_pos++];
}

void buf_out(char data)
{
    if(write_pos==16)
    {
        write_pos=0;
        write(fd_out,buffer_out,16);
    }
    buffer_out[write_pos++]=data;
}
int main()
{
    fd_in=open("input.txt",O_RDONLY);
    fd_out=open("result.txt",O_WRONLY|O_CREAT,0666);
    char ch;
    while((ch=buf_in())!= EOF)
    {
        buf_out(ch);
    }
    close(fd_in);
    close(fd_out);
    return 0;
}

这些是我的代码,当我查看结果 .txt 时,它看起来像输入文件的内容和一堆空值,输入文件的内容再次出现。所以它永远不会结束。我的代码有什么问题?谢谢。

C Linux 文件 缓冲区 EOF

评论

3赞 Andreas Wenzel 12/5/2022
如果要工作,则必须对函数进行编程,使其在由于到达文件末尾而导致读取失败时返回。但是,您没有这样做。相反,您忽略了 的返回值,因此您不会注意到何时到达文件末尾。此外,a 不保证能够表示值 。如果要确保数据类型可以表示值,请改用。while((ch=buf_in())!= EOF)buf_inEOFreadcharEOFintEOF
1赞 Craig Estey 12/5/2022
除了 Andreas 提到的之外,除非输入文件是 16 的倍数,否则必须记住返回的长度,并在最后一次调用时超过该长度时返回。也就是说,在某些时候,我们将读取更少的字节(例如 7),而不是读取 16 个字节。因此,在最后一次读取时,在填充缓冲区后,必须返回 [仅] 7 个有效字符和第 8 个 EOF。buf_inreadEOFbuf_in
0赞 Andreas Wenzel 12/5/2022
请向我们展示变量的定义和 。read_poswrite_pos

答:

1赞 Andreas Wenzel 12/5/2022 #1

如果要工作,则必须对函数进行编程,使其在由于到达文件末尾而导致读取失败时返回。但是,您没有这样做。相反,您忽略了 的返回值,因此您不会注意到何时到达文件末尾。while((ch=buf_in())!= EOF)buf_inEOFread

此外,a 不保证能够表示值 。如果要确保数据类型可以表示值,请改用。charEOFintEOF

您似乎认为这是出现在文件末尾的字符的字符代码。然而,事实并非如此。该值不是字符代码。它是由 getchar 等函数返回的特殊值,用于指示未检索到任何字符。该函数不一定返回值以指示 end-or-file 或错误。它使用不同的机制来报告此问题。它将返回成功读取或出错的字节数。该值可能等于某些平台上的值,但您不能依赖此值。EOFEOFreadEOF-1EOF-1

为了解决上述问题,您可以像这样重写函数:buf_in

int buf_in( void )
{
    if ( read_pos == 16 )
    {
        read_pos = 0;
        if ( read( fd_in, buffer_in, 16 ) == -1 )
            return EOF;
    }
    return (unsigned char)buffer_in[read_pos++];
}

强制转换为是必需的,以便保证所有字符代码都可与值区分开来。unsigned charEOF

但是,这不能正确处理仅在 和 字节之间读取而不是字节的情况。read11516

因此,最好添加一个附加变量并将此变量初始化为 。之后,您可以使用以下代码:ssize_t bytes_read0

int buf_in( void )
{
    if ( read_pos == bytes_read )
    {
        read_pos = 0;
        bytes_read = read( fd_in, buffer_in, 16 );
        if ( bytes_read == -1 )
            return EOF;
    }
    return (unsigned char)buffer_in[read_pos++];
}

请注意,您还必须更改变量声明

char ch;

在函数中main

int ch;

因为我们已将函数的返回值更改为 .buf_inint

评论

0赞 ECH 12/5/2022
多谢!但是,有没有什么可以保持炭buf_in呢?
0赞 Andreas Wenzel 12/5/2022
@ECH:在未签名的平台上,您将无法用 表示值,因此您必须改用。在已签名的平台(大多数平台)上,如果使用 .因此,如果您希望程序可靠地工作,则必须使用 而不是 。charEOFcharintcharEOFcharintchar