CSCE 121 Chapter 10
Jump to navigation
Jump to search
« previous | Monday, October 4, 2010 | next »
Input and Output
There are innumerable different types of input and output devices (printers, console, GUI, LCD, Network, etc.). Drivers make input/output streams for each item as similar as possible:
- Device ⇒ Drivers ⇒ Input Library ⇒ [istream → PROGRAM → ostream] ⇒ Output Library ⇒ Drivers ⇒ Device
Working with Files
Sequence of bytes numbered from 0 upward
Format determines how bytes are interpreted: text files use bytes as characters.
Reading Process:
|
Writing Process:
|
ifstream and ofstream can be used to create stream variables:
void read_file() {
cout << "Please enter input file name: ";
string name;
cin >> name;
ifstream ist(name.c_str()); // 'c_str' produces low-level C-style string (null character at the end)
if (!ist) error("can't open input file");
string contents;
ist >> contents;
// do something here...
}
void write_file() {
cout << "Please enter name of output file: ";
string oname;
cin >> oname;
ofstream ost(oname.c_str());
if (!ost) error("can't open output file");
ost << "file contents";
// do something here...
}
open() and close() can also be used:
void read_file() {
ifstream ifs;
// ...
ifs >> foo; // error: ifs is not open
// ...
ifs.open(name, ios_base::in); // open file for input
// ...
ifs >> bar; // OK
// ...
ifs.open(name, ios_base::out); // error: ifs is already open
// ...
ifs.close(); // close file
// ...
ifs >> baz; // error: ifs has already been closed
Stream States
good() | Operations succeeded |
eof() | Hit end of input ("end of file") |
fail() | Something unexpected happened: can be reset with clear() |
bad() | Something unexpected and serious happened: get out of program! |
void fill_vector(istream& ist, vector<int>& v, char terminator) { // Read integers from ist into v until we reach eof() or terminator
int i = 0;
while (ist >> i) v.push_back(i);
if (ist.eof()) return; // fine: we've found the end of the file
if (ist.bad()) error("ist is bad"); // stream corrupted; let's get out of here!
if (ist.fail()) { // we can clean up from this
ist.clear(); // clear stream so we can look for terminator
char c;
ist >> c;
if (c != terminator) { // unexpected character
ist.unget(); // put character back (shorter version of putback()); caller of fill_vector() might need it
ist.clear(ios_base::failbit); // set state back to fail()
}
}
}
Note: iostream contains built-in exceptions such as ist.exceptions(ist.exceptions() | ios_base::badbit), which throws ios_base::failure exception.
Reading in a loop
void skip_to_int() {
if (cin.fail()) { // we found something that wasn't an integer
cin.clear(); // allow program to look for characters
char ch;
while (cin >> ch) { // throw away all non-digit characters
if (isdigit(ch)) {
cin.unget();
return;
}
}
}
error("no input");
}
int get_int() {
int n = 0;
while (true) {
if (cin >> n) return n;
cout << "Sorry that wasn't a number; please try again";
}
}
int get_int(int low, int high, const string& greeting, const string& sorry) {
cout << greeting << " [" << low << " to " << high "]:\n";
while (true) {
int n = get_int();
if (low <= n && n <= high) return n;
cout << sorry;
}
}
// in main()
int n = get_int(1,10, "Howdy, please enter a number", "Sorry, that wasn't in range");