An exception is an unexpected incident that stops the normal program execution. Ex: Accessing an out of range element in vector results in an exception. A program that does not handle an exception ends execution.
Here is an example program:#include <iostream> #include <vector> #include <iomanip> using namespace std; int main() { int packageWeight; double shippingCost; vector<double> shippingCostPerLb = {5.00, 6.00, 7.00, 8.50, 10.00, 11.50, 13.00, 15.00, 17.00, 20.00}; cout << "Enter package weight: "; cin >> packageWeight; shippingCost = shippingCostPerLb.at(packageWeight - 1); cout << "Shipping cost: $" << fixed << setprecision(2); cout << shippingCost << endl; return 0; }
shippingCost = shippingCostPerLb.at(packageWeight - 1);
.
An exception can occur on this line, as the value of packageWeight determines the index in shippingCostPerLb that is accessed. As shippingCostPerLb has 10 elements, any value of packageWeight less than 1 or greater than 10 will exceed shippingCostPerLb's range, causing an out_of_range exception.
To avoid having a program end when an exception occurs, a program can use try and catch blocks to handle the exception during program execution.
try
block surrounds normal code, which is exited immediately if a statement within the try block throws an exception.
catch
block catches an exception thrown in a preceding try block. If the thrown exception's type matches the catch block's parameter type, the code within the catch block executes. A catch block is called an exception handler.
#include <iostream> #include <vector> #include <iomanip> using namespace std; int main() { int packageWeight; double shippingCost; vector<double> shippingCostPerLb = {5.00, 6.00, 7.00, 8.50, 10.00, 11.50, 13.00, 15.00, 17.00, 20.00}; cout << "Enter package weight: "; try { cin >> packageWeight; shippingCost = shippingCostPerLb.at(packageWeight - 1); } catch (out_of_range& excpt) { cout << "Error: Invalid weight" << end; } cout << "Shipping cost: $" << fixed << setprecision(2); cout << shippingCost << endl; return 0; }
out_of_range
.
As the catch block has a parameter of type out_of_range, the catch block will catch any out_of_range exception thrown by the code within the try block.
#include <iostream> #include <vector> #include <iomanip> using namespace std; int main() { int packageWeight; double shippingCost; vector<double> shippingCostPerLb = {5.00, 6.00, 7.00, 8.50, 10.00, 11.50, 13.00, 15.00, 17.50, 20.00}; bool needInput = true; cout << "Enter package weight: "; while(needInput) { try { cin >> packageWeight; shippingCost = shippingCostPerLb.at(packageWeight - 1); needInput = false; } catch (out_of_range& excpt) { cout << "Error: Invalid weight" << endl; } } cout << "Shipping cost: $" << fixed << setprecision(2); cout << shippingCost << endl; return 0; }
Exception Type | Cause of exception |
---|---|
runtime_error | Errors that occur and are detected at runtime. runtime_error is a base class for other exceptions. |
system_error | Errors originating from the underlying operating system or other low-level system components. system_error's typically have an associated error code. |
invalid_argument | Errors due to invalid user inputs or invalid inputs to program components (e.g., function arguments). |
out_of_range | Errors due to accessing elements outside of a supported range (e.g., vector indices). |
ios_base::failure | Errors due to failures in reading or writing input/output streams. |
A program can throw user-defined exceptions by using a throw statement. A throw
statement can throw an exception, like runtime_error, which causes execution to jump immediately to the end of a try block. Ex: The statement throw runtime_error("Invalid date");
creates and throws an exception with the message "Invalid date".
#include <iostream> #include <cmath> using namespace std; int main() { double gasVolume; double oilVolume; double mixRatio = 0.0; try { cin >> gasVolume; cin >> oilVolume; mixRatio = gasVolume / oilVolume; if (isnan(mixRatio)) { throw runtime_error("mixRatio is NaN!") } } catch (runtime_error& excpt) { cout << excpt.what() << end; } return 0; }
throw invalid_argument("Value not greater than 0");
?
catch (invalid_argument& excpt) {
// ...
}
.
The thrown exception's type is invalid_argument, which matches the catch block's parameter type. So, the catch block can catch and handle the exception.
#include <iostream> #include <cmath> using namespace std; int main() { double massVal = 0; // Object mass (kg) double volumeVal = 0; // Object volume (m^3) double densityCalc; // Resulting density try { cin >> massVal; // Error checking, greater than zero mass if (massVal <= 0.0) { throw runtime_error("Invalid mass"); } cin >> volumeVal; // Error checking, greater than zero volume if (volumeVal <= 0.0) { throw runtime_error("Invalid volume"); } densityCalc = massVal / volumeVal; cout << "Density: " << densityCalc; } catch (runtime_error& excpt) { // Prints the error message passed by the throw statement cout << excpt.what() << endl; } return 0; }
#include <iostream> #include <cmath> using namespace std; int main() { double inputTempValue; char inputTempUnit; double convertedTempK; try { cin >> inputTempValue; cin >> inputTempUnit; // check for valid input temperature unit if (inputTempUnit != 'C' && inputTempUnit != 'F') { throw invalid_argument("Temperature unit not C or F"); } if (inputTempUnit == 'C') { convertedTempK = inputTempValue + 273.15; } else { convertedTempK = (inputTempValue + 459.67) / 1.8; } if (convertedTempK < 0.0) { throw runtime_error("Temperature less than 0 K"); } cout << inputTempValue << " " << inputTempUnit; cout << " = " << convertedTempK << " K" << endl; } catch (invalid_argument& excpt) { cout << "Error: " << excpt.what(); } catch (runtime_error& excpt) { cout << "Error: " << excpt.what(); } return 0; }
#include <iostream> #include <cmath> using namespace std; double convertTemp(char inputTempUnit, double inputTempValue) { double convertedTempK; if (inputTempUnit != 'C' && inputTempUnit != 'F') { throw invalid_argument("Temperature unit not C or F"); } if (inputTempUnit == 'C') { convertedTempK = inputTempValue + 273.15; } else { convertedTempK = (inputTempValue + 459.67) / 1.8; } return convertedTempK; } int main() { double inputTempValue; char inputTempUnit; double convertedTempK; try { cin >> inputTempValue; cin >> inputTempUnit; convertedTempK = convertTemp(inputTempUnit, inputTempValue); if (convertedTempK < 0.0) { throw runtime_error("Temperature less than 0 K"); } cout << inputTempValue << " " << inputTempUnit; cout << " = " << convertedTempK << " K" << endl; } catch (invalid_argument& excpt) { cout << "Error: " << excpt.what(); } catch (runtime_error& excpt) { cout << "Error: " << excpt.what(); } return 0; }
#include <iostream>
#include <cmath>
using namespace std;
int main() {
char row;
int column;
bool askForInput = true;
while (askForInput) {
try {
cin >> row;
cin >> column;
if (row != 'A' && row != 'B' && row != 'C') {
// TODO
}
if (column < 1 || column > 8) {
// TODO
}
cout << "Dispensing item: " << row << column << endl;
askForInput = false;
}
// TODO
}
return 0;
}
#include <iostream>
#include <cmath>
using namespace std;
int main() {
char row;
int column;
bool askForInput = true;
while (askForInput) {
try {
cin >> row;
cin >> column;
if (row != 'A' && row != 'B' && row != 'C') {
throw invalid_argument("Row must be A, B, or C");
}
if (column < 1 || column > 8) {
throw runtime_error("Column must be 1-8");
}
cout << "Dispensing item: " << row << column << endl;
askForInput = false;
}
catch (invalid_argument& excpt) {
cout << "Exiting program: " << excpt.what() << endl;
askForInput = false;
}
catch (runtime_error& excpt) {
cout << "Error: " << excpt.what() << endl;
}
}
return 0;
}
Given a program that searches for a student's ID or name in a text file, complete the FindID() and FindName() functions. Then, insert a try/catch statement in main() to catch any exceptions thrown by FindID() or FindName(), and output the exception message. Each line in the text file contains a name and ID separated by a space.
Function FindID() has two parameters: a student's name (string) and the text file's contents (ifstream). The function FindID() returns the ID associated with the student's name if the name is in the file, otherwise the function throws a runtime_error with the message "Student ID not found for studentName", where studentName is the name of the student.
Function FindName() has two parameters: a student's ID (string) and the text file's contents (ifstream). The function FindName() returns the name associated with the student's ID if the ID is in the file, otherwise the function throws a runtime_error with the message "Student name not found for studentID", where studentID is the ID of the student.
The main program takes three inputs from a user: the name of a text file (string), the search option for finding the ID or name of a student (int), and the ID or name of a student (string). If the search option is 0, FindID() is invoked with the student's name as an argument. If the search option is 1, FindName() is invoked with the student's ID as an argument. The main program outputs the search result or the caught exception message.
Ex: If the input of the program is:
roster.txt 0 Reagan
and the contents of roster.txt are:
Reagan rebradshaw835
Ryley rbarber894
Peyton pstott885
Tyrese tmayo945
Caius ccharlton329
the output of the program is:
rebradshaw835
Ex: If the input of the program is:
roster.txt 0 Mcauley
the program outputs an exception message:
Student ID not found for Mcauley
Ex: If the input of the program is:
roster.txt 1 rebradshaw835
the output of the program is:
Reagan
Ex: If the input of the program is:
roster.txt 1 mpreston272
the program outputs an exception message:
Student name not found for mpreston272
#include <iostream>
#include <string>
#include <stdexcept>
#include <fstream>
using namespace std;
string FindID(string name, ifstream &infoFS) {
string nextName;
string nextID;
infoFS >> nextName;
infoFS >> nextID;
while (!infoFS.fail()) {
if (nextName == name) {
return nextID;
}
else {
infoFS >> nextName >> nextID;
}
}
throw runtime_error("Student ID not found for " + name);
}
string FindName(string ID, ifstream &infoFS) {
string nextName;
string nextID;
infoFS >> nextName;
infoFS >> nextID;
while (!infoFS.fail()) {
if (nextID == ID) {
return nextName;
}
else {
infoFS >> nextName >> nextID;
}
}
throw runtime_error("Student name not found for " + ID);
}
int main() {
int userChoice;
string studentName;
string studentID;
string studentInfoFileName;
ifstream studentInfoFS;
// Read the text file name from user
cin >> studentInfoFileName;
// Open the text file
studentInfoFS.open(studentInfoFileName);
// Read search option from user. 0: FindID(), 1: FindName()
cin >> userChoice;
try {
if (userChoice == 0) {
cin >> studentName;
studentID = FindID(studentName, studentInfoFS);
cout << studentID << endl;
}
else {
cin >> studentID;
studentName = FindName(studentID, studentInfoFS);
cout << studentName << endl;
}
}
catch (runtime_error &excpt) {
cout << excpt.what() << endl;
}
studentInfoFS.close();
return 0;
}