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
.