Home > Software design >  While loop cannot be not terminated with eof
While loop cannot be not terminated with eof

Time:12-05

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;
}

These are my codes, and when I look at the result.txt, it looks like the content of the input file and bunch of nulls and the content of input file appears again. So it never ends. What is the problem of my code? Thanks.

CodePudding user response:

If you want while((ch=buf_in())!= EOF) to work, you must program the function buf_in to return EOF when a read fails due to reaching end-of-file. However, you did not do this. You are instead ignoring the return value of read, so you will not notice when end-of-file is reached.

Also, a char is not guaranteed to be able to represent the value EOF. Use int instead, if you want to be sure that the data type can represent the value EOF.

You appear to be under the impression that EOF is the character code of a character that appears at the end of the file. However, that is not the case. The value EOF is not a character code. It is a special value that is returned by functions such as getchar, to indicate that no character was retrieved. The function read will not necessarily return the value EOF to indicate end-or-file or an error. It uses a different mechanism to report this. It will return the number of bytes successfully read, or -1 on error. The value EOF may be equal to the value -1 on some platforms, but you cannot rely on this.

In order to solve the problems mentioned above, you could rewrite the function buf_in like this:

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  ];
}

The cast to unsigned char is necessary so that it is guaranteed that all character codes are distinguishable from the value EOF.

However, this would not properly handle the case of read only reading between 1 and 15 bytes, instead of 16 bytes.

Therefore, it would probably be best to add an additional variable ssize_t bytes_read and to initialize this variable to 0. Afterwards, you can use the following code:

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  ];
}

Note that you must also change the variable declaration

char ch;

in the function main to

int ch;

because we have changed the return value of the function buf_in to int.

  • Related