CSCE 121 Chapter 10

From Notes
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:

DeviceDriversInput Library[istreamPROGRAMostream]Output LibraryDriversDevice

Working with Files

Sequence of bytes numbered from 0 upward

Format determines how bytes are interpreted: text files use bytes as characters.

Reading Process:
  1. Get file path and name
  2. Open file for reading
  3. Read characters
  4. Close file (typically done implicitly)
Writing Process:
  1. Set file path and name
  2. Open or create file (if it doesn't exist) for writing
  3. Write objects
  4. Close file (also typically done implicitly)

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");