APUE2e之Exercise 3.6

来源:互联网 发布:mac文件夹消失 编辑:程序博客网 时间:2024/06/01 09:09

I was working exercise3.6 of APUE2e and the code was simple. But when I tried to use fgets and fputs to print out the file content, I got problems. Then I tried to figure out the reason. It turned out to be the null or ‘’ byte of C string, which prevent fgets and fputs from behaving as I expected (fgets appends null byte to the end of input buffer, while fputs prints null-terminated string). I solved the problem by preventing write function to write the null or ‘‘ byte for a C string to the file. This was done by restricting the number of bytes to be writen (using sizeof(buffer)-1, rather than sizeof(buffer)). These findings reminded me of my careless reading, because the problem was caused by a really small mistake. Now I learned the lesson. I prefer reading to writing codes. But through writing and testing, I learn more than just reading. I think I must do more coding and don’t get satisfied just by reading the books and codes.

Attaching is the code I wrote for exercise3.6.


/* * exercise3-6.c * *  Created on: Sep 10, 2011 *      Author: zhuhuang */ #include <apueerr.h>#include <fcntl.h> int main(void){int filedes;FILE *fileptr;int writenum;int readnum;off_t seekpos;int character; char buffer0[] = "test";    printf("Size of buffer0: %dn", sizeof(buffer0)); //sizeof includes the '' char buffer1[] = "The first sentence of file3-6 (Using the write function to write).n"; //an '' in the endchar buffer2[20];char buffer3[] = "The second sentence of file3-6 (Using the write function to write).n";  //an '' in the endchar buffer4[69]; if((filedes = open("file3-6", O_CREAT | O_RDWR | O_APPEND | O_TRUNC, S_IRWXU | S_IRGRP | S_IROTH)) == -1)err_sys("open error"); if((writenum = write(filedes, buffer1, sizeof(buffer1)-1)) == -1)  //Not "sizeof(buffer1)", otherwise it will cause fputs to behave weirdly.err_sys("write error 1");printf("Number of characters of first write: %dn", writenum); if((seekpos = lseek(filedes, 0, SEEK_CUR)) == -1)err_sys("lseek error 1");printf("Current file offset after the first write: %dn", (int)seekpos); if((seekpos = lseek(filedes, 10, SEEK_SET)) == -1)err_sys("lseek error 2");printf("lseek the current file offset to: %dn", (int)seekpos); if((readnum = read(filedes, buffer2, 20)) == -1)err_sys("read error");printf("The string that has been read: %sn", buffer2); if((seekpos = lseek(filedes, 0, SEEK_CUR)) == -1)err_sys("lseek error 3");printf("Current file offset after the first read: %dn", (int)seekpos); if((writenum = write(filedes, buffer3, sizeof(buffer3)-1)) == -1)err_sys("write error 2");printf("Number of characters of second write: %dn", writenum); if((seekpos = lseek(filedes, 0, SEEK_CUR)) == -1)err_sys("lseek error 4");printf("Current file offset after the second write: %dn", (int)seekpos); if((seekpos = lseek(filedes, 68, SEEK_SET)) == -1)err_sys("lseek error 2");printf("lseek the current file offset to: %dn", (int)seekpos); if((readnum = read(filedes, buffer2, 20)) == -1)err_sys("read error");printf("The string that has been read: %sn", buffer2); if((seekpos = lseek(filedes, 0, SEEK_CUR)) == -1)err_sys("lseek error 3");printf("Current file offset after the second read: %dn", (int)seekpos); //Problem: fail to give the complete content of the file.//Depending on the size of buffer4, the output can be only contents of buffer1, or contents of buffer1 and part of buffer3. //No matter how big we have set the size of buffer4 to and whether we use the fflush and fsync function, the problem remains.//The problem is caused by null or '' byte. printf("The contents of the file file3-6:n");if((fileptr = fopen("file3-6", "r")) == NULL)err_sys("fopen error"); //fgets read at most 40-1 characters, a null or '' byte is inserted to the end.while(fgets(buffer4, 40, fileptr) != NULL){//fputs writes the null-terminated string.//The null or '' causes fputs to behave unexpectedly.if(fputs(buffer4, stdout) == EOF)err_sys("fputs error");//fputs(buffer4, stdout); //Not the flushing problem.//fflush(stdout);//fsync(STDOUT_FILENO);} if(ferror(fileptr))err_sys("fgets error"); exit(0);}