Week 2: File I/O, Exceptions, Two-Dim Arrays
Victor Norman
Vote (show me 1, 2, 3, 4, 5 fingers)
How many values flow IN to the function from its caller?
double aFunc(double value, double root) {
…
}
Vote (show me 1, 2, 3, 4, 5 fingers)
How many values flow OUT of the function to its caller?
double aFunc() {
…
}
Vote (show me 1, 2, 3, 4, 5 fingers)
How many values flow IN to the function from its caller?
double aFunc(int p1) {
p1 = 7;
…
}
Vote (show me 1, 2, 3, 4, 5 fingers)
How many values flow OUT of the function to its caller?
double aFunc(int &p1) {
p1 = 7;
…
}
Vote (show me 1, 2, 3, 4, 5 fingers)
How many values flow OUT of the function to its caller?
double aFunc(const int &p1) {
p1 = 7;
…
}
Vote (show me 1, 2, 3, 4, 5 fingers)
If pass-by-value and pass-by-const-ref both can be used only to pass values in to a function, and pass-by-value is easier to write, why would you use pass-by-const-ref?
How can I "return" two values from a function?
Or, "how can I make two (or more) values flow out of a function?"
Reading from input
cin is stream from keyboard
>> "Extraction" operator: it extracts a value from an input stream
#include <iostream>
using namespace std;
...
int num;
cin >> num;
You can do a similar thing, but reading from a file instead of the keyboard.
File I/O
Two kinds of files: input and output. ifstream and ofstream
Two ways to open:
ifstream fin("the_file.txt"); // or
ifstream fin;�fin.open("the_file.txt");
Best to check if the file is successfully opened: assert(fin.is_open());
To close: fin.close();
Reading from a file
Use >>, like reading from console:
fin >> aVariable;
This operation returns false if the operation fails -- perhaps because file has been read to the end.
So, to read repeatedly to end of file:
while (fin >> aVariable) {
// do something with aVariable
}
Can read multiple things with multiple >>. Each >> reads a word.
Code
#include <fstream>
#include <cmath> // for sqrt().
using namespace std;
int main() {
ifstream fin("numbers.txt");
assert(fin.is_open());
double number = 0.0;
while (fin >> number) {
cout << "The square root of " << number << " is " << sqrt(number)� << endl;
}
fin.close();
}
Peer Instruction Question
What is the name of the class used for reading in from a file?
Peer Instruction Question
One way to open a file for reading is
ifstream fin("filename");
What is another way?
Reading entire line
Using fin >> aString reads just the next word.
To read an entire line of a file:
string line;�getline(fin, line);
If getline() fails, then the input stream (fin) will have a false status. I.e., fin == false
ifstream fin("text.txt");
assert(fin.is_open());
string str;
while (true) {
getline(fin, str);
if (! fin) {
break;
}
cout << "-->" << str << "<--" << endl;
}
fin.close();
return 0;
Peer Instruction Question
There is a problem with this code. What is it? (Assume the file is opened, etc.)
string s;
while (true) {
getline(fin, s);
cout << s << endl;
if (! fin) {
break;
}
}
Writing to file: use <<
Remember to output \n to make new lines.
Exceptions
Why?
In C++, there are fewer exceptions (than python) because syntax errors, etc., are caught during compilation.
See https://www.cplusplus.com/reference/exception/exception/
throw
try / catch
Examples
Most common cases of use of exceptions is when reading from user or input file, or depending on an external library that throws exceptions.
Example program that checks if an index is legal: invalid_argument.
#include <stdexcept>
#include <iostream>
using namespace std;
int getVal(int *a, int size, int index) {
if (index < 0 || index >= size) {
throw invalid_argument("bad index, silly goose");
}
return a[index];
}
int main() {
int arr[8] = {3, 4, 5, 6, 7, 8, 9, 10};
cout << "Enter an index between 0 and 7: ";
int idx;
cin >> idx;
try {
cout << getVal(arr, 8, idx) << endl;
} catch (const invalid_argument &e) {
cout << "Error.\n";
cout << e.what();
}
}
Peer Instruction Question
Given this code, what output is produced?
f() {
throw invalid_argument("yuck");
cout << "a";
}
g() {
cout << "b";
f();
cout << "c";
}
main() {� cout << "d";� g();� f();� cout << "e";�}
Stack unwinding
When throw executes, it is like return -- control goes immediately back to the caller.
What if the caller does not handle a thrown exception?
void f() { … }
void g() { … f(); … }
int main() { … g(); … }
f throws an exception… g() does not handle it, but main() does.
Two-dimensional arrays
Useful in many situations
int board[5][8];
5 rows, 8 columns.
const unsigned ROWS = 5;
const unsigned COLUMNS = 5;
int main() {
ifstream fin("board.txt");
assert(fin.is_open());
char board[ROWS][COLUMNS];
string dummy;
for (unsigned i = 0; i < ROWS; ++i) {
for (unsigned j = 0; j < COLUMNS; ++j) {
fin >> dummy;
board[i][j] = dummy[0]; // convert to char
}
}
fin.close();
cout << board[0][0] << " " << board[0][1] << endl;
assert(board[3][3] == 'a');
assert(board[1][0] == 'd');
cout << "All tests passed" << endl;
}
board.txt
a b a b c
d e f b c
a a a b c
b a a a c
c c c c c
Pointers into 2-dim array can move between rows
char *cellp = &board[0][4];
cout << "at 0, 4 is " << *cellp << endl;
cellp++;
cout << "next cell is " << *cellp << endl;
cellp++;
cout << "next cell is " << *cellp << endl;
Passing two-dim array as parameter
Can specify number of cols. Have to specify the number of rows:
void aFunc(int arr[NUM_ROWS][NUM_COLS]) {
code here…
}