1 of 26

Week 2: File I/O, Exceptions, Two-Dim Arrays

Victor Norman

2 of 26

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) {

}

  1. 0
  2. 1
  3. 2
  4. 3
  5. Other/unknown

3 of 26

Vote (show me 1, 2, 3, 4, 5 fingers)

How many values flow OUT of the function to its caller?

double aFunc() {

}

  • 0
  • 1
  • 2
  • 3
  • Other/unknown

4 of 26

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;

}

  • 0
  • 1
  • 2
  • 3
  • Other/unknown

5 of 26

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;

}

  • 0
  • 1
  • 2
  • 3
  • Other/unknown

6 of 26

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;

}

  • 0
  • 1
  • 2
  • 3
  • Other/unknown

7 of 26

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?

  • Pass-by-const-ref is actually easier to write.
  • Pass-by-value can't be used to flow values into a function.
  • Pass-by-const-ref is more efficient for large data values.
  • Pass-by-value is a defensive strategy, ensuring the function cannot change the parameter value by mistake.
  • Other/unknown

8 of 26

How can I "return" two values from a function?

Or, "how can I make two (or more) values flow out of a function?"

9 of 26

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.

10 of 26

File I/O

Two kinds of files: input and output. ifstream and ofstream

  • Have to open a file first. Should close it when done.

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

11 of 26

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.

12 of 26

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

}

13 of 26

Peer Instruction Question

What is the name of the class used for reading in from a file?

  1. fstream
  2. ifstream
  3. instream
  4. fin

14 of 26

Peer Instruction Question

One way to open a file for reading is

ifstream fin("filename");

What is another way?

  1. ifstream fin.open("filename");
  2. ifstream open("filename") as fin;
  3. ifstream fin;�fin.open("filename");
  4. ifstream fin().open("filename");

15 of 26

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

16 of 26

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;

17 of 26

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;

}

}

  1. No lines of input will ever be processed.
  2. An infinite loop will occur.
  3. The first line of the file will not be processed.
  4. The last line of the file will not be processed.
  5. The last line of the file will be processed twice.

18 of 26

Writing to file: use <<

Remember to output \n to make new lines.

19 of 26

Exceptions

Why?

  • A mechanism for a function to communicate an error back to the caller
  • And handle that error in a "graceful" fashion (i.e., stop the program from crashing).

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

20 of 26

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

}

}

21 of 26

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";�}

  1. dbe
  2. dbc
  3. dbace
  4. dbae
  5. None of the others.

22 of 26

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.

23 of 26

Two-dimensional arrays

Useful in many situations

int board[5][8];

5 rows, 8 columns.

24 of 26

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

25 of 26

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;

26 of 26

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…

}