Intermediate Programming / C... 1/16 Intermediate Programming / C and C++ CSCI 6610 Streams and Files February 22, 2016
Intermediate Programming / C... 2/16 Lecture 4: Using Streams and Files in C and in C++ Streams Opening Files File I/O
Intermediate Programming / C... 3/16 Files We will use input text files and output text files. A file is data that is stored on your hard disk or some other device. Files have many properties that the programmer would rather not deal with: Its physical location. Its actual size Decoding the access permissions. How much has been processed so far, and how much remains? Streams were invented to take care of all those troublesome properties of a file.
Intermediate Programming / C... 4/16 Streams A stream is an abstraction that makes files easy to use. An input stream is a data structure that permits you to bring data from a file into your program. An output stream is a data structure that permits you to write your data out to permanent storage. It is implemented as a structure that contains buffers, error flags, pointers, and other parts. In standard C, a stream has type FILE* The tools library uses typedef to define the type name stream as a synonym for FILE* typedef FILE* cstream; In C++, there are istreams and ostreams.
Intermediate Programming / C... 5/16 Opening a File in C: Chapter 14.2 To read from or write to a file, you must first open the file and check to be sure the file was properly opened. Here are two correct approaches. The second one is better. FILE* datafile = fopen("mydata.txt", "r"); // input. if (! datafile) { puts ("Cannot open myfile.txt for input."); exit(1); } #define OUTF "myout.txt" stream outfile = fopen( OUTF, "w"); // output. if (! outfile) fatal ("Cannot open %s for output.", OUTF);
Intermediate Programming / C... 6/16 Opening a File in C++ # include "tools.hpp" # define INF "mydata.txt" # define OUTF "myout.txt" ifstream datafile ("mydata.txt"); // input. if (!datafile) fatal("can t open %s for input", INF); ofstream outfile( OUTF ); if (!outfile.is open()) fatal ("Cannot open %s for output.", OUTF);
Intermediate Programming / C... 7/16 File and eof I/O in C: Chapter 14.4.3 The file-input and file-output functions are like scanf and printf. Here, we read a series of pairs of numbers from one file and write them in reverse order on the other. double x, y; int status; // To store the result of fscanf. for(;;) { status = fscanf( datafile, "%lg %lg", &x, &y ); if( feof( datafile ) ) break; if( status == 0 ) fatal( "File format error" ); // Otherwise, process the data you just read. fprintf( outfile, "%g %g", y, x ); } The program will terminate with a File format error comment if alphabetic data is read when numeric data was expected.
Intermediate Programming / C... 8/16 File I/O and eof in C++ Everything stays the same or becomes easier. double x, y; for(;;) { datafile >>x >>y; if (datafile.eof( )) break; if (!datafile.good()) fatal("file format error"); // Otherwise, process the data you just read. outfile <<y, <<x; } The program will terminate with a File format error comment if alphabetic data is read when numeric data was expected.
Intermediate Programming / C... 9/16 Reading Numbers in C++ Simply use the >> operator. C++ numeric input and output is generic: you write it the same way no matter what the type of the number happens to be. double x; int k float f; for(;;) { datafile >> x >> k >> f; if (datafile.eof( )) break; if (!datafile.good()) fatal("file format error"); // Otherwise, process the data you just read. }
Intermediate Programming / C... 10/16 Reading a Character in C To read the next character, even if it is invisible: char ch; fscanf( datafile, "%c" ); ch = fgetc( datafile ); ch = getc( datafile ); To skip whitespace, then read the next visible character, Put a space before the %: fscanf( datafile, " %c" );
Intermediate Programming / C... 11/16 Reading a Character in C++ To skip whitespace, then read the next visible character: char ch; datafile >> ch; To read the next character, even if it is invisible, set a flag in the stream, thus: datafile >> noskipws >> ch The noskipws flag remains set until the program resets it: datafile >> skipws;
Intermediate Programming / C... 12/16 Reading a String in C Reading a string is more complex than reading a number because a string can be any length. One of the main security vulnerabilities in old C code is that string reads were allowed to store data past the end of the array that was supposed to hold the letters. This is called the buffer overflow problem. It is irresponsible and unprofessional to read a string without limiting the number of chars that can be read. For this reason, you must never use gets(). It provides no way to read a string safely.
Intermediate Programming / C... 13/16 Using fgets() in C char ary [16]; fgets( ary, 16, datafile ); fprintf( outfile, "%s", ary ); fgets() lets you limit the length of an input string to the length of the array that stores it. fgets( char * ary, int n, FILE* strm ); Read characters from strm into the ary until n-1 chars have been read. Store a null terminator after the last input character. fgets() also stops reading if a newline character is found, or end-of-file occurs before reading n-1 chars.
Intermediate Programming / C... 14/16 Using fscanf() to read a string in C fscanf( FILE* strm, char* format, char* ary ); fscanf() lets you limit the length of an input string to the length of the array that stores it. char ary [16]; fscanf( datafile, "%15[^\n]", char* ary ); fprintf( outfile, "%s", ary ); The format must specify a maximum string length that is 1 shorter than ary.
Intermediate Programming / C... 15/16 Reading a String in C++ Reading a string is much simpler in C++ than in C because of the C++ type string. A string has a default length (number of characters), but if you try to store more than that into it, it will grow itself by reallocating the character array to double the current length. So although it is possible to read a char* in C++, it is normally not the right thing to do. A C++ string is the ideal type variable to contain input. You can read the input safely, and later decide how it should be handled. There are two basic ways to read a string.
Intermediate Programming / C... 16/16 >> and getline() datafile >> name; The input operator skips leading whitespace and reads one word into name. It stops when the next whitespace character is found in the datafile. getline (istream& is, string& str); This function reads chars from the stream into the string until the newline is found, or eof happens. The newline is removed from the stream and discarded. It is not stored as part of the string. getline (istream& is, string& str, char delim); This function reads chars from the stream into the string until the specified delimiter is found, or eof happens. The delimiter is removed from the stream and discarded. It is not stored as part of the string.