File Operations Functions Manipulating Files Review The fstream library defines two classes: • ifstream, for creating connections between programs and input files; and • ofstream, for creating connections between programs and output files. Each can be operated on in much the same way as a normal istream or ostream. Problem 1 Using OCD, design and implement a function that reads the name of an input file from the user, tries to open it, and returns to the caller an ifstream guaranteed to be open, and guaranteed to be connected to a file specified by the user. Preliminary Analysis One way to guarantee both conditions: • the ifstream is open • the file was specified by the user is to use a loop that gives the user another chance if they enter an invalid file name... Behavior Our function should display a prompt for the name of the input file. It should read the name of the input file. It should try to open an ifstream to that file. If the ifstream opens successfully, our function should return that ifstream; otherwise, it should display an error message, “loop back” and give the user another chance. Objects Description Type Movement Name prompt file name connection string string ifstream local in (kbd) out -fileName fin error msg string local -- Operations Description Predefined? Library? display a string read a string open connection to a file verify connection repeat on failure return an ifstream Name yes yes yes string string fstream << >> -- yes yes yes fstream built-in built-in is_open loop return Algorithm 1. Loop: a. Display prompt for input file name. b. Read fileName. c. Open ifstream connection named fin to fileName. d. If fin opened successfully, return fin. e. Display error message End loop. Discussion We have seen how to open an ifstream to a file, verify that the open succeeded, etc. We can have a function return an ifstream by making its return-type ifstream. For functions that need to receive an ifstream or ofstream, these types can be used to define function parameters. Discussion (Ct’d) If we wish to avoid declaring fin within the loop, we need a way to open fin at a point different from its declaration. The ifstream (and ofstream) classes provide the function member open() to open a stream at a point other than its declaration. Coding /* GetIFStream() * ... */ ifstream GetIFStream() { ifstream fin; string fileName; // declare fin here for (;;) { cout << “\nEnter the name of the input file: “; cin >> fileName; fin.open(fileName.data()); // open fin here if (fin.is_open()) return fin; // verify it opened cout << “\n*** Unable to open file \’” << fileName << “\’ for input!\n” << endl; } } Discussion In addition to the file operations we have seen, the iostream (and fstream) libraries provide a variety of additional operations for manipulating streams. Status Operations To determine the status of a stream, the libraries provide these function members: – good() // returns true iff stream is ok – bad() // returns true iff stream is not ok – fail() // returns true iff last operation failed – eof() // returns true iff last file-read failed Change-State Operations To change the state of a stream, the libraries provide these function members: – clear() // reset status to good – setstate(b) // set state bit b (one of ios_base::goodbit, ios_base::badbit, ios_base::failbit, or ios_base::eofbit). Read-Position Operations To manipulate the read-position within an ifstream, the libraries provide these: – tellg() // returns offset of current read-position from beginning of file – seekg(offset, base) // move read-position offset bytes from base (one of ios_base::beg, ios_base::cur, or ios_base::end) Write-Position Operations To manipulate the write-position within an ofstream, the libraries provide these: – tellp() // returns offset of current write-position from beginning of file – seekp(offset, base) // move write-position offset bytes from base (one of ios_base::beg, ios_base::cur, or ios_base::end) Other Operations To look at the next character in an ifstream without advancing the read-position (i.e., without reading it), the libraries provide: – peek() // returns next char in the stream without reading it To “unread” the last char that was read, the libraries provide: – unget() // unread char most recently read Another Operation To skip a given number of chars in the stream (or until a particular char is encountered), the libraries provide: – ignore(n, stopChar) // skip past n chars, or until stopChar is encountered Discussion This is by no means an exhaustive list, but it does give some of the most commonly-used stream function members. See Chapter 21 of “The C++ Programming Language” by Bjarne Stroustrup (AddisonWesley) for a complete list. Summary The C++ iostream library provides a rich set of I/O functions that let a programmer: – open and close streams. – read-from/write-to streams. – get/set the state of a stream. – get the read/write position of a stream. – move the read/write position of a stream. – peek at, or unget chars from a stream. – skip over chars in a stream.