Saturday, August 30, 2014

Unix Prog: Character at-a-time I/O(1)

1. Read Character from stream

getc, fgetc, getchar system calls are used to read one character at-a-time.

Definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/stdio.h  
 ......  
 /* Read a character from STREAM.  
   
   These functions are possible cancellation points and therefore not  
   marked with __THROW. */  
 extern int fgetc (FILE *__stream);  
 extern int getc (FILE *__stream);  
   
 /* Read a character from stdin.  
   
   This function is a possible cancellation point and therefore not  
   marked with __THROW. */  
 extern int getchar (void);  
 ......  

The difference between getc and fgetc: getc can be implemented as one macro, fgetc is guaranteed to be a function, calls to fgetc probably takes longer time.
getchar is equal to getc(stdin)

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
   
 int main(int argc, char* argv[])  
 {  
  FILE *fp;  
   
  if((fp = fopen("test.txt", "r+")) == NULL) {  
   printf("fopen error!\n");  
   exit(1);  
  }  
   
  char c1, c2;  
  c1 = getc(fp);  
  c2 = fgetc(fp);  
  printf("c1: %c, c2: %c\n", c1, c2);  
  printf("input one char: \n");  
  printf("%c\n", getchar());  
   
  fclose(fp);  
   
  exit(0);  
 }  

shell:
Run the program, it will read two characters and then instruct the user to input one character, user input 'k', getchar() will catch this char from stdin and output to stdout.
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 c1: a, c2: b  
 input one char:  
 k  
 k  

2. Read error
When reading from the stream, both error and encountering the end will return the same negative value. So we need: ferror, feof and clearerr to differentiate the returning information.

definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/stdio.h  
 ......  
 /* Clear the error and EOF indicators for STREAM. */  
 extern void clearerr (FILE *__stream) __THROW;  
 /* Return the EOF indicator for STREAM. */  
 extern int feof (FILE *__stream) __THROW __wur;  
 /* Return the error indicator for STREAM. */  
 extern int ferror (FILE *__stream) __THROW __wur;  
 ......  

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
   
 int main(int argc, char* argv[])  
 {  
  FILE *fp;  
   
  // Open the file "test.txt" containing only one character 'a'  
  if((fp = fopen("test.txt", "r+")) == NULL) {  
   printf("fopen error!\n");  
   exit(1);  
  }  
   
  // Read 2 characters, 2nd one is EOF  
  printf("%c ", getc(fp));  
  printf("%d\n", fgetc(fp));  
   
  // run ferror, feof to detect if it is one error or EOF  
  printf("ferror: %d feof: %d\n", ferror(fp), feof(fp));  
   
  if(ferror(fp) > 0) {  
   printf("error on stream!\n");  
  } else {  
   printf("no error!\n");  
  }  
   
  if(feof(fp) > 0) {  
   printf("reached the end of file\n");  
  } else {  
   printf("not reaching the end\n");  
  }  
   
  // Clear up the error flag at FILE struct  
  clearerr(fp);  
  printf("After clearerr, ferror: %d, feof: %d\n", ferror(fp), feof(fp));  
   
  fclose(fp);  
   
  exit(0);  
 }  

shell:
Run the program it will open the "test.txt" containing only one character. It tries to get 2 characters from "test.txt", the first character is "a", the second one is -1, which is EOF, meaning end of file. At this time, FILE's feof flag is turned on. After calling clearerr, all error flags are turned off.
 ubuntu@ip-172-31-23-227:~$ ./a.out  
 a -1  
 ferror: 0 feof: 1  
 no error!  
 reached the end of file  
 After clearerr, ferror: 0, feof: 0  

No comments:

Post a Comment