Error handling
- C++ course
- Beginner
- Lesson 115/116
- 6 min
Add input validation and error handling with try/catch.
Validation with a custom exception
In this lesson we will add validation to the addTask function. If the title is empty, an InvalidTaskException will be thrown; the caller catches it with try/catch and shows a message to the user.
InvalidTaskException is a class derived from std::exception; it overrides the what() method to return a custom message. This way the program can respond appropriately to invalid inputs without crashing.
Catching with try/catch
You wrap the addTask call in a try block; when an exception is thrown, the catch block runs. With catch (const InvalidTaskException& e), the message is accessed via e.what().
try {
addTask(tasks, "", "pending");
} catch (const InvalidTaskException& e) {
cout << e.what();
}Here an empty title throws InvalidTaskException; catch catches it and prints the message. The program continues without crashing. This pattern is the standard way to validate user input.
Practice Add the InvalidTaskException class
Define class InvalidTaskException : public std::exception; in a public: block write const char* what() const noexcept override { return "invalid task"; }. At the start of addTask, add if (title.empty()) throw InvalidTaskException();. In main, after printMenu();, add try { addTask(tasks, "Homework", "pending"); addTask(tasks, "", "pending"); } catch (const InvalidTaskException& e) { cout << e.what() << endl; } and a final listTasks(tasks); call.
Starter code
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
using namespace std;
struct Task {
string title;
string status;
};
// Define the InvalidTaskException class
void printMenu() {
cout << "1 - Add" << endl;
cout << "2 - List" << endl;
cout << "3 - Exit" << endl;
}
void addTask(vector<Task>& tasks, string title, string status) {
// add a throw for empty title
Task t;
t.title = title;
t.status = status;
tasks.push_back(t);
}
void listTasks(const vector<Task>& tasks) {
for (Task t : tasks) {
cout << t.title << " - " << t.status << endl;
}
}
int main() {
printMenu();
vector<Task> tasks;
// add a try/catch addTask call and listTasks
return 0;
}Sample solution
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
using namespace std;
struct Task {
string title;
string status;
};
class InvalidTaskException : public std::exception {
public:
const char* what() const noexcept override {
return "invalid task";
}
};
void printMenu() {
cout << "1 - Add" << endl;
cout << "2 - List" << endl;
cout << "3 - Exit" << endl;
}
void addTask(vector<Task>& tasks, string title, string status) {
if (title.empty()) throw InvalidTaskException();
Task t;
t.title = title;
t.status = status;
tasks.push_back(t);
}
void listTasks(const vector<Task>& tasks) {
for (Task t : tasks) {
cout << t.title << " - " << t.status << endl;
}
}
int main() {
printMenu();
vector<Task> tasks;
try {
addTask(tasks, "Homework", "pending");
addTask(tasks, "", "pending");
} catch (const InvalidTaskException& e) {
cout << e.what() << endl;
}
listTasks(tasks);
return 0;
}Expected output
1 - Add 2 - List 3 - Exit invalid task Homework - pending
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 Fill in the blank: throw call
if (title.empty()) {
____ InvalidTaskException();
}
if (title.empty()) {
throw InvalidTaskException();
}
Explanation: throw throws the exception.
2 How is an empty title reported in addTask?
- The program crashes
- Returns 0
- Ignores
- Throws InvalidTaskException Correct answer
Explanation: On empty title, InvalidTaskException is thrown.
3 Match each block with its job
| Term | Meaning |
|---|---|
try |
addTask call |
throw |
throws the exception |
catch |
prints the message |