1 / 45

The Standard C I/O Library

The Standard C I/O Library. As in C++, the fundamental notion used in doing I/O is the stream (but a stream is not an object as it is in C++ ... it is a struct) When a file is created or opened in C, the system associates a stream with the file. When a stream is opened, the fopen( ) call

duena
Download Presentation

The Standard C I/O Library

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. The Standard C I/O Library

  2. As in C++, the fundamental notion used in doing I/O is the stream (but a stream is not an object as it is in C++ ... it is a struct) When a file is created or opened in C, the system associates a stream with the file. When a stream is opened, the fopen( ) call returns a pointer to a FILE data structure. The FILE data structure contains all of the information necessary for the I/O library to manage the stream: * a file descriptor * a pointer to the I/O buffer * error flags * etc The original C I/O library was written around 1975 by Dennis Ritchie. Little has changed since then.

  3. Standard Streams Three streams are predefined and available to a process. These standard streams are referenced through the pre-defined FILE pointers stdin, stdout, and stderr. These pointers are defined in <stdio.h>

  4. Formatted Console I/O

  5. writes to stdout intprintf (const char *format-spec, print-data … ); printf • a format-specification has the following format: • %[flags] [width] [.precision] type % -this is format-spec digits after decimal point. This can truncate data Minimum field width. If width is prefixed with 0, add zeros until minimum width is reached. d signed decimal integer i signed decimal integer u unsigned decimal integer o unsigned octal integer x unsigned hex integer f double in fixed point notation e double in exponent notation c single character, an int s a string • left align, default is to right align • + prefix value with a sign • 0 pad output with zeros • prefix positive values with a blank

  6. Example Format Specification “%-10.8f” print 8 digits after the decimal point left justify the output % - introduces the format specification output field is 10 chars wide as a minimum. Padded if fewer characters in the output. Data is never truncated.

  7. int n = 3; double cost-per-item = 3.25; printf(“Cost of %3d items at $%4.2f each = $%6.2f\n”, n, cost-per-item, n*cost-per-item); Example Cost of 3 items at $ 3 . 2 5 = $ 9 . 7 5 second field is 4 characters wide with two characters after decimal point third field is 6 characters wide with 2 characters after decimal point right justified first field is 3 characters wide data is right justified

  8. scanf #include <stdio.h> intscanf (const char* format-spec, data fields);

  9. scanf reads formatted data from stdin into the data fields given in the argument string. Each argument must be a pointer to a variable that corresponds to a type specifier in the format specification. The format specification can contain: * white space characters. A white space character causes scanf to read in, but not store all consecutive white space characters in the input stream, up to the next non-white space character. * non-white space characters, except % sign. Causes scanf to read but not store a matching non-white space character. If the character does not match, scanf terminates. * format specification, introduced by %. Causes scanf to read in and convert characters in the input into values of the specified type. The resulting value is assigned to the next data field in the arg list.

  10. Sample Program

  11. One of the keys of the C I/O library is that I/O is normally buffered to minimize context switches. Buffering I/O Fully Buffered: I/O takes place when a buffer is full. Disk files are normally fully buffered. The buffer is allocated by the I/O library itself by doing a malloc. Line Buffered: I/O takes place when a new line character is encountered. Line buffering is used for terminal I/O. Note that I/O may take place before a new line character is encountered because of the size of the buffer.

  12. Most Unix systems default to the following: Standard Error is always un-buffered. All streams referring to a terminal device are line buffered (stdin and stdout). All other streams are fully buffered.

  13. Flushing a Stream You can force a stream to be flushed, (all unwritten bytes are passed to the kernel) #include <stdio.h> int fflush (FILE *fp); I’ve not seen an issue in Windows, but in Unix, you may not see output when you expect to if you don’t flush the buffers.

  14. #include <stdio.h> FILE *fopen (const char *filename, const char *mode); Opening a Stream full path to the file to be opened Mode bits “r” open text file for reading “rb” open binary file for reading “w” open text file for writing - truncate “wb” open binary file for writing - truncate “a” open text file for writing-append “ab” open binary file for writing-append “r+” open text file to read & write (file must exist) “rb+” open binary file to read & write - ditto “w+” open text file to read & write – truncate “wb+” open binary file to read & write – truncate “a+” open text file to read & write – append “ab+” open binary file to read & write - append pointer to the FILE structholding the internal state information about the connection to the associated file. Returns a NULL pointer if open fails. when opened for reading and writing * input cannot immediately follow output without an intervening fflush, fseek, fsetpos, or rewind. * output cannot immediately follow input without an intervening fseek, fsetpos, or rewind.

  15. Restriction r w a r+ w+ a+ file must already exist * * previous contents are discarded * * stream can be read * * * * stream can be written * * * * * stream can only be written at end * * Opening a Stream You cannot set permission when a file is opened with w or a

  16. Example of using fopen FILE *in; if ((in = fopen(“file1.txt”, “r”)) == NULL) perror(“could not open file1.txt”);

  17. FILE *freopen (const char *pathname, const char *mode, FILE *fp); Related Calls Opens a specified file on a specified stream. Closes the file first, if it is already open. Most typically used with stdin, stdout, and stderr to open a file as one of these streams. FILE *fdopen (int filedes, const char *mode); takes a file descriptor as a parameter. Used with pipes and network connections, because these use file descriptors. Associates an I/O stream with the descriptor.

  18. #include <stdio.h> int fclose (FILE *stream); Closing a Stream returns a zero if the close is successful Otherwise it returns -1 All files are closed when the program terminates normally, but this allows no opportunity to do error recovery if termination is not normal. Therefore, it is recommended that all files be closed explicitly.

  19. Binary I/O is commonly used to read or write arrays or to read and write structures, because both deal with fixed size blocks of information. Binary I/O Note: Binary files are not necessarily interchangeable across systems! * compilers change how data is packed * binary formats are different on different cpu architectures.

  20. Unformatted I/O There are three types of unformatted I/O: * Character at a time * Line at a time * Direct I/O (fread and fwrite for binary data)

  21. for binary files and text files on GNU systems returns the current byte offset or -1L Stream Positioning #include <stdio.h> long ftell (FILE *fp); int fseek (FILE *fp, long offset, int whence); void rewind (FILE *fp); SEEK_SET – from beginning of file SEEK_CUR – from the current position SEEK_END – from the end of the file returns 0 if successful nonzero on error

  22. For portability across POSIX systems use: int fgetpos (FILE *fp, fpos_t *pos); int fsetpos (FILE *fp, const fpos_t *pos); returns 0 if successful the position is passed in this parameter, a new data type defined by the POSIX standard. The position value in an fsetpos must have been obtained in a previous fgetpos call.

  23. fread is used to read binary data and text in fixed sized blocks operating systems address of where first byte is to be stored fread #include <stdio.h> size_t fread (void *ptr, size_t size, size_t nblocks, FILE *stream); The number of blocks to read The size of each block or record The stream to read from The number of items read. It could be less than nblocks if there is an error or eof is reached.

  24. If the data that you are reading has some record structure … Interpreting Binary Data struct record_fmt data_buf; . . . fread(&data_buf, sizeof(char), sizeof(data_buf), file_handle);

  25. from the file operating systems databuf struct record_fmt { int a; float b; char id[8]; char pw[8]; }; 01000101000110100011101000111001 011110100111001010001101000111101 001101110100001101110101000011110 011101000101011010100011101010011 cout << data_buf.id;

  26. address of the first byte to write #include <stdio.h> size_t fwrite (void *ptr, size_t size, size_t nblocks, FILE *stream); fwrite The number of blocks to write The number of blocks written. If not the same as nblocks, some error has occurred. The stream to write to The size of each block or record

  27. Character at a time Input The return value is an unsigned char that has been converted to an int. The constant EOF (usually -1) is returned if there is an error or if the end of the file is encountered. #include <stdio.h> int fgetc (FILE *stream); fgetc gets the next character in the stream as an unsigned char and returns it as an int. If an eof or an error is encountered, EOF is returned instead. This call is guaranteed to be written as a function.

  28. Character at a time Input intgetc (FILE *stream); intgetchar ( void ); highly optimized –best function for reading a single character. Usually implemented as a macro. Equivalent to getc(stdin)

  29. In most implementations, each stream maintains * an error flag * an end-of-file flag To distinguish between EOF and an error call one of the following functions: #include <stdio.h> int ferror (FILE *fp); int feof (FILE *fp); returns nonzero (true) if error flag is set, otherwise returns 0 returns nonzero (true) if eof flag is set, otherwise returns 0 Clear the flags by calling void clearerr (FILE *fp);

  30. After reading a character from a stream, it can be pushed back into the stream. #include <stdio.h> int ungetc (int c, FILE *fp); the character to push back. Note that it is not required that you push back the same character that you read. You cannot pushback EOF. Implementations are not required to support more than a single character of pushback, so don’t count on it.

  31. int fputc (int c, FILE *stream); Character Output fputc converts c to an unsigned char and writes it to the stream. EOF is returned if there is an error. int putc (int c, FILE *stream); int putchar( int c ); optimized for single character input assumes stdout is the output stream

  32. Line at a Time Input returns buf if successful and NULL on end of file or error. #include <stdio.h> char *fgets (char *buf, intn, FILE *fp); char *gets (char *fp); reads up through and including the next newline character, but no more than n-1characters. The buffer is terminated with a null byte. If the line is longer than n-1, a partial line is returned. The buffer is still null terminated. If the input contains a null, you can’t tell. gets has been deprecated because it does not allow the size of the buffer to be specified. This allows buffer overflow! Warning

  33. #include <stdio.h> intfputs (const char *str, FILE *fp); int puts (const char *str); String Output writes a null-terminated string to the stream. It does not write the null terminating character. It does not write a newline character. Returns EOF if the function fails. writes the null terminated string to standard-out, replacing the zero terminating character with a new-line character. If successful, the function returns a non-negative value. If the function fails, it returns EOF.

  34. I/O Efficiency #include <stdio.h> int main (void) { int c; while ( (c =getc(stdin)) != EOF) if (putc(c, stdout) == EOF) perror("Error writing output"); if(ferror(stdin)) perror("Error reading input"); exit(0); } char at a time EOF is ctrl-D

  35. #include <stdio.h> #define MAXLINE 4096 int main (void) { char buf[MAXLINE]; while (fgets(buf, MAXLINE, stdin) != NULL) if (fputs(buf, stdout) == EOF) perror("Output Error"); if (ferror(stdin)) perror("Input Error"); exit(0); } line at a time

  36. for copying a file of 1.5M bytes in 30,000 lines Function user CPU fgets, fputs 2.2 seconds getc, putc 4.3 seconds fgetc, fputc 4.6 seconds loop is executed 30,000 times loop is executed 1.5M times

  37. Temporary Files #include <stdio.h> FILE *tmpfile (void); creates a temporary file (type wb+) that is automatically deleted when the file is closed or the program terminates.

  38. Sample Program Write a simple version of the cat command. It takes an optional parameter, a file name. It copies the file to stdout. - if no file name is given, it copies stdin to stdout

  39. Preliminaries header files for I/O #include <stdio.h> #include <stdlib.h> #define LINELEN 256 void send_to_stdout( FILE*); required to define NULL C programmers use #define to define constants. It works like a macro … the value 256 gets inserted wherever the name LINELEN appears in the code. There is no type checking! function prototype

  40. Array contains the command line arguments The number of arguments on the command line Main declaration int main (intargc, char* argv[ ]) { . . . }

  41. Body of main int main (intargc, char* argv[ ]) { FILE *fp; if (argc == 1) send_to_stdout ( stdin); Declare a FILE* to hold the file handle If there is just one command line argument it is the command. Copy from stdin.

  42. int main (intargc, char* argv[ ]) { FILE *fp; if (argc == 1) send_to_stdout ( stdin); else if (argc == 2) { if ( (fp = fopen(*++argv, “r”) ) != NULL) { send_to_stdout ( fp ); fclose ( fp ); } If there are two command line arguments, the second one is the file name.

  43. int main (intargc, char* argv[ ]) { FILE *fp; if (argc == 1) send_to_stdout ( stdin); else if (argc == 2) { if (fp = fopen(*++argv, “r”) ) != NULL) { send_to_stdout ( fp ); fclose ( fp ); } else { perror(“could not open the file.”); exit(1); } handle file won’t open error

  44. else { perror(“could not open the file.”); exit(1); } } else { perror(“Invalid command – too many arguments”); exit(1); } return 0; } Handle the case where there are too many arguments on the command line.

  45. void send_to_stdout(FILE *fp) { char line[LINELEN]; while ( fgets (line, LINELEN, fp) ) { if (fputs ( line, stdout ) == EOF ) { perror(“Write to stdout failed”); exit(1); } } } send_to_stdout function

More Related