Overview • Character oriented I/O (revision) Files in C • Files and streams • Opening and closing files cp1h James Soutter Idiom for character-oriented I/O int c; Character oriented I/O while ((c = getchar()) != EOF) { /* Code for processing the character c */ } File Length Copying a File int c; int c; int length = 0; while ((c = getchar()) != EOF) { while ((c = getchar()) != EOF) { putchar(c); ++length; } } printf(“File length is %d\n”, length); Note that putchar(c) is the equivalent In TourLength() in Practical 3, several people forgot to printf(“%c”, c) to initialise length , i.e. the “ length = 0 ” part. 1
Exercise : Count the number of uppercase One Solution letters and print the result. Int main(void) { Int main(void) { int c, countu; int c, countu; /* 1 mark */ countu = 0; while ((c = getchar()) != EOF) { while ((c = getchar()) != EOF) { /* 3 marks */ if (isupper(c)) countu += 1; } /* 1 mark */ } printf(“%d uppercase letters\n”, countu); } } Hint, use “isupper()” to test whether a character is upper case. Full Exercise : Count the number of uppercase One Solution letters in countu, and lower case letters in countl. Print the result. int c, countu, countl; Int main(void) { countu = 0; countl = 0; int c, countu, countl; while ((c = getchar()) != EOF) { /* 1 mark */ if (isupper(c)) while ((c = getchar()) != EOF) { countu += 1; /* 3 marks */ if (islower(c)) } countl += 1; /* 1 mark */ } } printf(“%d uppercase and %d lowercase letters\n”, countu, countl); Models of I/O putchar(c) getchar() 2
Redirection Adds Some Output Flexibility • Input from a file : ./ftour < data50 putchar(c) • Output to a file : ./ftour > log getchar() • Both Input and Output Redirection : ./ftour < data50 > log • Input and Output from a program Input : cat data50 | ./ftour | grep length Streams • In C we talk about input and output streams – getchar() reads from the standard input stream Named Streams – putchar(ch) writes to the standard output stream • You might think of a stream as a file – In practice, streams often end at a keyboard, a window or another program. • It is more proper to think of streams as connectors to files etc. Standard Streams Using Named Streams • All C programs begin with three standard • All the standard I/O functions have a variant streams that have a named stream as a parameter � fprintf(stdout, “Hello”) ≡ printf(“Hello”). � stdin is read by getchar() � stdout is written to by putchar(c) � putc(c, stdout) ≡ putchar(c) � getc(stdin) ≡ getchar() � stderr is a second output stream � These streams are defined in stdio.h • Use the manual pages to find the variants 3
Output Remember Practical 2 stdout void SkipWhiteSpace(void) { int ch = ReadChar(); while (ch == ' ' || ch == '\n' || ch == '\t') stdin stderr ch = ReadChar(); Input UnReadChar(ch); Output } Using Standard Calls void SkipWhiteSpace(void) Exercise { int ch = getc(stdin); /* or getchar() */ while (ch == ' ' || ch == '\n' || ch == '\t') ch = getc(stdin); /* or getchar() */ ungetc(ch, stdin); /* There is no ungetchar(ch) */ } Exercise : Replace “ez” by “es” One Solution (lowercase only) int main(void) { int main(void) { int c, prev = 0; int c, prev = 0; while ((c = getchar()) != EOF) { while ((c = getchar()) != EOF) { /* 5 marks */ if (prev == ‘e’ && c == ‘z’) putchar(‘s’); } else } putchar(c); prev = c; } } 4
Using Named Streams int main(void) { Opening New Streams int c, prev = 0; while ((c = getc(stdin)) != EOF) { if (prev == ‘e’ && c == ‘z’) putc(‘s’, stdout); else putc(c, stdout); prev = c; } } FILE * Practical 4 • Streams have the type FILE * FILE *wordlist; FILE *stdin, *stdout, *stderr; wordlist = fopen(“wordlist.txt”, “r”); FILE *wordlist; if (wordlist == NULL) { printf(“Can’t find the word list\nBye!\n”); • Streams do not always end in a file despite return EXIT_FAILURE; the name. } /* To be completed */ fclose(wordlist); fopen() fopen modes Mode Meaning FILE * fopen(const char *path, const char *mode) “r” Open text file for reading • Opens a stream for the file named path “w” Open text file for writing – E.g. fopen(“output.txt”, “w”); “a” Open text file for appending – E.g. fopen(“/usr/include/stdio.h”, “r”); “rb” Open binary file for reading • The mode selects read or write access “wb” Open binary file for writing – This prevents some misuse – E.g. you can’t write to a CD-Rom “ab” Open binary file for appending • fopen() returns NULL on failure What happens if the file exists already? 5
Copying a File fclose() • fclose() discards a stream FILE *in, *out; • It is good practice to close streams when in = fopen(“wordlist.txt”, “r”); out = fopen(“copy.txt”, “w”); they are no-longer needed while ((c = getc (in)) != EOF) { – To avoid operating system limits putc(c, out); • Exiting a program closes all streams } fclose(in); fclose(out); Copying a File perror(): Reporting Errors • fopen may return NULL for many reasons FILE *in, *out; – File not found in = fopen(“wordlist.txt”, “r”); – Invalid path out = fopen(“copy.txt”, “w”); – Permission denied while ((c = getc (in)) != EOF) { putc(c, out); – Out of disk space } – Etc. fclose(in); • perror() prints an error related to the last fclose(out); failed system call fclose(stdin); fclose(stdout); fclose(stderr); Using perror() Buffering • Streams are buffered FILE *wordlist; – Text written to a stream may not appear immediately. wordlist = fopen(“silly.txt”, “r”); • fflush(FILE *stream) if (wordlist == NULL) { – Forces the pending text on a stream to be written perror(“Can’t open word list”); – As does fclose( stream ) return EXIT_FAILURE; } • fprintf( stream , “\n”) – Text streams usually flush themselves after each newline character. : ./prac4 Can’t open word list: No such file or directory 6
Streams • Have the type FILE * Summary • Programs start with three streams � stdin � stdout � stderr New Operators • fopen - open a stream for a file • getc - similar to getchar() • putc - similar to putchar() • fprintf - similar to printf() • fclose - closes a stream • fflush - flushes a buffer • perror - reports an error in a system call 7
Recommend
More recommend