Home > 书山有路 > APUE2e Exercise3.6

APUE2e Exercise3.6

September 11th, 2011 Leave a comment Go to comments

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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
/*
 * 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 end
	char buffer2[20];
	char buffer3[] = "The second sentence of file3-6 (Using the write function to write).n";  //an '' in the end
	char 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);
}
  1. No comments yet.
  1. No trackbacks yet.