Key C++ Practice Problems (And Solutions) From Beginner To Senior Level - CodeSignal
Key C++ Practice Problems (And Solutions) From Beginner To Senior Level - CodeSignal
INTERVIEW PREP
BACK TO BLOG
Jump to a section
What you will need to get started
How to solve our C++ practice problems for maximum benefit
Essential C++ practice problems (and solutions) for beginners
Language fundamentals and syntax
C++ control structures
Basic I/O operations with C++
Object-oriented programming
Basic data structures
Advanced C++ practice problems (and solutions)
Advanced data structures and algorithms
Memory management
Concurrency and multithreading
Advanced features of C++
Next steps & resources
IDEs
Using fully-featured IDEs for C++ interview preparation provides a comprehensive
environment, integrating editing, building, and debugging seamlessly. The GUI-
based project configuration simplifies the setup, making it easier to manage larger
codebases efficiently. IDEs come with advanced features like code refactoring,
enhancing productivity during interview simulations. However, be mindful of the
potentially steep learning curve associated with complex UIs, and the resource-
intensive nature of IDEs if you haven’t used one before.
Conversely, for more senior engineers and those very comfortable with their IDE,
pay attention to your debugging methods. Many interview platforms don’t have rich
environments for watching variables, compilation warnings, and code completion,
so consider practicing interview questions in a different environment than what
you’re used to so that you’re able to adapt to a few methods of debugging.
Online IDEs
For quick, instant coding practice, online IDEs offer immediate accessibility
without the need for setup. They are suitable for short, focused tests and
demonstrations, making them convenient for interview preparation. This helps
emulate many interview situations where you’re coding online with a less-
customized environment. However, be aware of the limitations, such as restricted
features compared to desktop IDEs. The inability to save work locally might be a
drawback if you want to review your code later in another IDE for practice, and
requiring internet access might limit when you can practice.
Fortunately, most standard facilities needed for interview practice come built-in:
While the STL suffices for most fundamental coding challenges, some additional
libraries useful to have handy include:
Ideally, have these pre-installed and integrated into the dev environment instead
of figuring out during interviews. This removes distractions to stay focused. Most
build systems or Linux package managers make acquiring these straightforward.
With any language, you’ll need to build a solid foundation in implementing basic
data structures, such as dynamic arrays and stacks, as well as common algorithm
patterns and object-oriented programming principles. This set of beginner-level
and essential questions aims to evaluate your grasp on foundational concepts,
setting the stage for more advanced assessments.
What skills this question evaluates: This question tests basic input/output
operations and string manipulation in C++. It evaluates the ability to use cin for
input and cout for output.
Solution:
cpp
Copy code
#include <iostream>
#include <string>
using namespace std;
int main() {
string name;
cout << "Enter your name: ";
cin >> name;
cout << "Hello, " << name << "!" << endl;
return 0;
}
Explanation of the solution: This solution involves using the iostream library for
input and output operations. The program first declares a string variable name,
then uses cin to read the user’s name and cout to print the greeting. The usage of
<< operator for output and >> for input is fundamental in C++.
What skills this question evaluates: This question builds on the first by adding
arithmetic operations and basic data type handling. It assesses the candidate’s
ability to perform calculations and handle user input.
Solution:
cpp
Copy code
#include <iostream>
using namespace std;
int main() {
int num1, num2;
cout << "Enter two numbers: ";
cin >> num1 >> num2;
cout << "The sum is: " << num1 + num2 << endl;
return 0;
}
Explanation of the solution: This solution introduces integer variables num1 and
num2. The program uses cin to read two integers inputted by the user and
calculates their sum using the + operator. This introduces the concept of
arithmetic operations and multiple data input in C++. The use of cin >> num1 >>
num2 demonstrates how to read multiple inputs in a single line.
What skills this question evaluates: This question tests the understanding of
conditional statements (if-else). It evaluates the ability to use logical expressions
to make decisions in C++.
Solution:
cpp
Copy code
#include <iostream>
using namespace std;
int main() {
int number;
cout << "Enter an integer: ";
cin >> number;
if (number % 2 == 0) {
cout << number << " is even." << endl;
} else {
cout << number << " is odd." << endl;
}
return 0;
}
What skills this question evaluates: This question builds on the previous one by
adding a while loop for repeated input. It assesses the understanding of loops and
conditional statements combined.
Solution:
cpp
Copy code
#include <iostream>
using namespace std;
int main() {
int number, positiveCount = 0, negativeCount = 0;
cout << "Enter numbers (0 to stop): ";
while (cin >> number && number != 0) {
if (number > 0) {
positiveCount++;
} else {
negativeCount++;
}
}
cout << "Positive numbers: " << positiveCount << endl;
cout << "Negative numbers: " << negativeCount << endl;
return 0;
}
What skills this question evaluates: This question tests the candidate’s ability to
handle input/output operations and basic string manipulation. It assesses how to
use standard input to receive a string and then process it to produce the reversed
version.
Solution:
cpp
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string input;
cout << "Enter a string: ";
getline(cin, input);
reverse(input.begin(), input.end());
cout << "Reversed string: " << input << endl;
return 0;
}
Explanation of the solution: The program reads a string from the user using
`getline` to handle potentially spaced input. It then utilizes the `reverse` function
from the standard `<algorithm>` library to reverse the string in-place. This
solution demonstrates basic string handling and the use of the standard library for
string manipulation.
What skills this question evaluates: This question adds basic file handling to the
previous skills of string manipulation and I/O operations. It evaluates the ability to
write to and read from a file in C++.
Solution:
cpp
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string input;
cout << "Enter a string: ";
getline(cin, input);
reverse(input.begin(), input.end());
// Write to file
ofstream outFile("output.txt");
outFile << input;
outFile.close();
// Read from file and print
string fileContent;
ifstream inFile("output.txt");
getline(inFile, fileContent);
cout << "String from file: " << fileContent << endl;
inFile.close();
return 0;
}
Explanation of the solution: This solution extends the previous string reversal
program to include file I/O operations. The reversed string is written to
“output.txt” using an `ofstream` object. The program then creates an `ifstream`
object to read the content back from the file and prints it to the console. This
demonstrates how to handle basic file operations in C++, including writing to and
reading from files.
Object-oriented programming
Question 1: Creating a basic class
Prompt: Define a C++ class named `Car` with private member variables for
`brand` (string), `model` (string), and `year` (integer). Include public member
functions to set and get the values of these variables.
What skills this question evaluates: This question assesses understanding of basic
class creation, encapsulation, and the use of public member functions for
accessing private data. It focuses on the fundamental principles of object-oriented
programming in C++.
Solution:
cpp
#include <iostream>
#include <string>
using namespace std;
class Car {
private:
string brand;
string model;
int year;
public:
void setBrand(const string &b) {
brand = b;
}
void setModel(const string &m) {
model = m;
}
void setYear(int y) {
year = y;
}
string getBrand() const {
return brand;
}
string getModel() const {
return model;
}
int getYear() const {
return year;
}
};
int main() {
Car myCar;
myCar.setBrand("Toyota");
myCar.setModel("Corolla");
myCar.setYear(2020);
cout << "Car Details: " << myCar.getBrand() << " " <<
myCar.getModel() << " " << myCar.getYear() << endl;
return 0;
}
Explanation of the solution: The `Car` class is defined with private member
variables (`brand`, `model`, `year`) and public methods (`setBrand`, `setModel`,
`setYear`, `getBrand`, `getModel`, `getYear`) for setting and getting these
variables. This encapsulates the data and provides controlled access to it. The
`main` function demonstrates creating an instance of `Car` and using its
methods.
Solution:
cpp
#include <iostream>
#include <string>
using namespace std;
class Car {
// ... (same as above)
};
class ElectricCar : public Car {
private:
int batteryRange;
public:
void setBatteryRange(int range) {
batteryRange = range;
}
int getBatteryRange() const {
return batteryRange;
}
};
void printCarDetails(const Car &car) {
cout << "Car Details: " << car.getBrand() << " " <<
car.getModel() << " " << car.getYear() << endl;
}
int main() {
ElectricCar myElectricCar;
myElectricCar.setBrand("Tesla");
myElectricCar.setModel("Model S");
myElectricCar.setYear(2022);
myElectricCar.setBatteryRange(400);
printCarDetails(myElectricCar);
return 0;
}
Solution:
cpp
#include <iostream>
#include <cassert>
using namespace std;
class DynamicArray {
private:
int* data;
int size;
int capacity;
void resize() {
capacity *= 2;
int* newData = new int[capacity];
for (int i = 0; i < size; i++) {
newData[i] = data[i];
}
delete[] data;
data = newData;
}
public:
DynamicArray() : size(0), capacity(1), data(new
int[capacity]) {}
~DynamicArray() {
delete[] data;
}
void add(int item) {
if (size == capacity) {
resize();
}
data[size++] = item;
}
int get(int index) {
assert(index >= 0 && index < size);
return data[index];
}
};
int main() {
DynamicArray arr;
arr.add(5);
arr.add(10);
cout << "Element at index 0: " << arr.get(0) << endl;
cout << "Element at index 1: " << arr.get(1) << endl;
return 0;
}
What skills this question evaluates: This question tests the ability to use existing
data structures (like the dynamic array) to implement another data structure
(stack). It evaluates understanding of stack operations and error handling in C++.
Solution:
cpp
#include <iostream>
#include <cassert>
using namespace std;
class Stack {
private:
DynamicArray arr;
public:
void push(int item) {
arr.add(item);
}
int pop() {
assert(!isEmpty());
return arr.get(--arr.size);
}
int top() {
assert(!isEmpty());
return arr.get(arr.size - 1);
}
bool isEmpty() {
return arr.size == 0;
}
};
int main() {
Stack stack;
stack.push(10);
stack.push(20);
cout << "Top element: " << stack.top() << endl;
cout << "Popped element: " << stack.pop() << endl;
cout << "New top element: " << stack.top() << endl;
return 0;
}
Solution:
cpp
#include <iostream>
using namespace std;
class Node {
public:
int key;
Node *left, *right;
Node(int item) : key(item), left(nullptr), right(nullptr) {}
};
class BinarySearchTree {
private:
Node* root;
Node* insertRec(Node* root, int key) {
if (root == nullptr) {
return new Node(key);
}
if (key < root->key) {
root->left = insertRec(root->left, key);
} else {
root->right = insertRec(root->right, key);
}
return root;
}
bool searchRec(Node* root, int key) {
if (root == nullptr) {
return false;
}
if (root->key == key) {
return true;
}
return key < root->key ? searchRec(root->left, key) :
searchRec(root->right, key);
}
public:
BinarySearchTree() : root(nullptr) {}
void insert(int key) {
root = insertRec(root, key);
}
bool search(int key) {
return searchRec(root, key);
}
};
int main() {
BinarySearchTree bst;
bst.insert(10);
bst.insert(5);
bst.insert(15);
cout << "Is 10 in BST? " << (bst.search(10) ? "Yes" : "No")
<< endl;
cout << "Is 20 in BST? " << (bst.search(20) ? "Yes" : "No")
<< endl;
return 0;
}
What skills this question evaluates: This question tests understanding of graph
data structures and depth-first search, an important algorithm in graph theory. It
assesses the ability to implement graphs and traverse them using recursive or
stack-based approaches.
Solution:
cpp
#include <iostream>
#include <list>
#include <vector>
using namespace std;
class Graph {
private:
int numVertices;
list<int> *adjLists;
vector<bool> visited;
void DFSUtil(int vertex) {
visited[vertex] = true;
cout << vertex << " ";
for (int adj : adjLists[vertex]) {
if (!visited[adj]) {
DFSUtil(adj);
}
}
}
public:
Graph(int vertices) : numVertices(vertices), adjLists(new
list<int>[vertices]), visited(vertices, false) {}
void addEdge(int src, int dest) {
adjLists[src].push_back(dest);
}
void DFS(int startNode) {
fill(visited.begin(), visited.end(), false);
DFSUtil(startNode);
}
};
int main() {
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
cout << "Depth First Traversal starting from vertex 2:" <<
endl;
g.DFS(2);
return 0;
}
Explanation of the solution: The `Graph` class uses an adjacency list for
representing the graph and a `visited` vector to track visited nodes. The
`addEdge` method adds edges to the graph. The `DFS` method initializes the
`visited` vector and calls `DFSUtil`, a private method that performs recursive
depth-first traversal from the specified node, printing each visited node. This
solution demonstrates the implementation of a graph and a fundamental graph
traversal algorithm.
Memory management
Question 1: Implementing a smart pointer
Prompt: Write a template class `SmartPointer` that mimics the behavior of a
smart pointer. The class should be able to hold a pointer of any type and should
release the memory when it is no longer in use (i.e., implement basic reference
counting).
What skills this question evaluates: This question assesses the understanding of
dynamic memory management and the concept of smart pointers in C++,
particularly the implementation of reference counting to manage memory
automatically.
Solution:
cpp
#include <iostream>
using namespace std;
template <typename T>
class SmartPointer {
private:
T* ptr;
unsigned* count;
public:
SmartPointer(T* p = nullptr) : ptr(p), count(new
unsigned(1)) {}
SmartPointer(const SmartPointer<T>& sp) : ptr(sp.ptr),
count(sp.count) {
(*count)++;
}
SmartPointer<T>& operator=(const SmartPointer<T>& sp) {
if (this != &sp) {
if (--(*count) == 0) {
delete ptr;
delete count;
}
ptr = sp.ptr;
count = sp.count;
(*count)++;
}
return *this;
}
~SmartPointer() {
if (--(*count) == 0) {
delete ptr;
delete count;
}
}
T& operator*() {
return *ptr;
}
};
int main() {
SmartPointer<int> sp1(new int(10));
SmartPointer<int> sp2 = sp1;
cout << "Value: " << *sp2 << endl;
return 0;
}
What skills this question evaluates: This question tests the candidate’s
understanding of lower-level memory management in C++, particularly the
concepts of memory allocation and deallocation without object construction and
destruction.
Solution:
cpp
#include <iostream>
using namespace std;
template <typename T>
class CustomAllocator {
private:
T* array;
public:
CustomAllocator() : array(nullptr) {}
T* allocate(size_t n) {
array = static_cast<T*>(operator new[](n * sizeof(T)));
return array;
}
void deallocate() {
operator delete[](array);
}
};
int main() {
CustomAllocator<int> allocator;
int* arr = allocator.allocate(5);
// Use the allocated array (construct objects if necessary)
for (int i = 0; i < 5; ++i) {
new (&arr[i]) int(i); // Placement new
}
// Manually call destructor for constructed objects
for (int i = 0; i < 5; ++i) {
arr[i].~int();
}
allocator.deallocate();
return 0;
}
What skills this question evaluates: This question tests the candidate’s
understanding of thread synchronization in C++ using mutexes. It evaluates the
ability to implement basic thread-safe data structures, crucial in multithreaded
applications.
Solution:
cpp
#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>
using namespace std;
template <typename T>
class ThreadSafeQueue {
private:
queue<T> queue;
mutex mtx;
condition_variable cv;
public:
void enqueue(T item) {
lock_guard<mutex> lock(mtx);
queue.push(item);
cv.notify_one();
}
T dequeue() {
unique_lock<mutex> lock(mtx);
cv.wait(lock, [this] { return !queue.empty(); });
T item = queue.front();
queue.pop();
return item;
}
};
int main() {
ThreadSafeQueue<int> tsQueue;
// Example usage: tsQueue.enqueue(10);
// Example usage: int item = tsQueue.dequeue();
return 0;
}
Solution:
cpp
#include <iostream>
#include <vector>
#include <thread>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <queue>
using namespace std;
class ThreadPool {
private:
vector<thread> workers;
queue<function<void()>> tasks;
mutex mtx;
condition_variable cv;
bool stop;
public:
ThreadPool(size_t threads) : stop(false) {
for (size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
while (true) {
function<void()> task;
{
unique_lock<mutex> lock(this->mtx);
this->cv.wait(lock, [this] { return
this->stop || !this->tasks.empty(); });
if (this->stop && this->tasks.empty())
return;
task = this->tasks.front();
this->tasks.pop();
}
task();
}
});
}
}
void enqueue(function<void()> task) {
{
lock_guard<mutex> lock(mtx);
tasks.push(task);
}
cv.notify_one();
}
void shutdown() {
{
lock_guard<mutex> lock(mtx);
stop = true;
}
cv.notify_all();
for (thread &worker : workers) {
worker.join();
}
}
~ThreadPool() {
if (!stop) {
shutdown();
}
}
};
int main() {
ThreadPool pool(4);
// Example usage: pool.enqueue([]{ cout << "Task executed."
<< endl; });
return 0;
}
What skills this question evaluates: : This question assesses advanced knowledge
of C++ template metaprogramming, an area that involves using templates to
perform computations at compile time. It evaluates the ability to use recursive
template instantiations and template specialization.
Solution:
cpp
#include <iostream>
template <unsigned int N>
struct Factorial {
static const unsigned int value = N * Factorial<N -
1>::value;
};
template <>
struct Factorial<0> {
static const unsigned int value = 1;
};
int main() {
std::cout << "Factorial of 5: " << Factorial<5>::value <<
std::endl;
return 0;
}
Explanation of the solution: The `Factorial` template struct calculates the
factorial of a number at compile time. It uses recursive template instantiation,
with each instance calculating part of the factorial. The specialized version of the
template for the base case `Factorial<0>` provides the stopping condition for the
recursion. This is a classic example of template metaprogramming, leveraging C++
templates’ powerful ability for compile-time computation.
What skills this question evaluates: This question tests understanding of newer
C++17 features, particularly `std::variant` and `std::visit`. It assesses the ability to
work with type-safe unions and visitation patterns, showcasing proficiency in
modern C++ idioms.
Solution:
cpp
#include <iostream>
#include <variant>
#include <string>
using VariantType = std::variant<int, double, std::string>;
void processVariants(const VariantType& var) {
std::visit([](const auto& value) {
std::cout << value << std::endl;
}, var);
}
int main() {
VariantType var1 = 10;
VariantType var2 = 3.14;
VariantType var3 = "Hello C++17";
processVariants(var1);
processVariants(var2);
processVariants(var3);
return 0;
}
By taking these steps with the practice questions above (and with more
specialized applications of C++ for game development, machine learning, and
others) you’ll set yourself up to cultivate a robust understanding of the
fundamentals through consistent practice, rather than trying to “cram” concepts
shortly before an interview. Practicing interview scenarios, either solo or with a
peer, can also help you build confidence and improve ability to problem-solve on
the spot.
Keep reading
ENGINEERING
Read More
ENGINEERING
Read More
CODESIGNAL UPDATES
Read More
REQUEST A CALL
GET STARTED
Need product support?
CONTACT US
Products Solutions
IDE
Evaluations
Pricing
Resources Company
Blog Newsroom
Knowledge Base
Integrations
API Docs
Copyright © 2023 CodeSignal, Inc. All rights reserved
Privacy Terms Master Subscription Agreement Security & Compliance Cookie Policy
Sitemap