Lesson 1

Understanding C++ Vectors, and Strings


Welcome to this course!

Before we dive into the essentials of C++ for interview preparation, let's begin with a review of some fundamental concepts within C++. In particular, we'll discuss C++ containers, vectors and strings. These tools are important for grouping multiple elements such as numbers or letters under a single entity.

Understanding C++'s Containers

A fundamental distinction of C++ containers is that they are mutable, meaning we can change their contents after their creation. Let's review how to create and modify vectors:

1#include <vector> 2 3int main() { 4 // Defining a vector 5 std::vector<int> my_vector = {1, 2, 3, 4}; 6 7 // Now let's try to change the first element of the container 8 my_vector[0] = 100; 9 10 // Now, my_vector equals {100, 2, 3, 4} 11 12 return 0; 13}
Diving Into Vectors

Vectors are dynamic arrays provided by the C++ Standard Template Library. They not only help us organize data such that each element holds a specific position, or index, but also provide several built-in functions for managing the stored data effectively. These functions include push_back(), insert(), erase(), and find(), and they allow us much flexibility when handling vectors.

push_back() is a function that allows you to add a new element to the end of the vector. This increases the size of the vector by one.

insert() provides a way to add an element at a specific position in a vector. The position is indicated by an iterator. This function shifts the position of all elements after the specified position by one.

The find() function comes from the <algorithm> library of STL and is used to find the position of a specific element within a vector. It takes a range provided by begin() and end() to look for the element.

erase() is a function that removes a specific element or a range of elements from the vector. This is done by specifying the position or range using iterators.

The begin() function returns an iterator pointing to the first element of the vector while end() returns an iterator pointing to the position past the last element of the vector.

The example below illustrates the use of these functions.

1#include <vector> 2#include <algorithm> //Needed for find 3 4int main() { 5 // Creating a vector 6 std::vector<std::string> fruits = {"apple", "banana", "cherry"}; 7 8 // Adding a new element at the end using push_back 9 fruits.push_back("date"); 10 11 // Inserting an element at a specific position using insert 12 fruits.insert(fruits.begin() + 1, "bilberry"); 13 14 // Finding position of 'banana' and removing it using erase 15 auto pos = std::find(fruits.begin(), fruits.end(), "banana"); 16 if (pos != fruits.end()) 17 { 18 fruits.erase(pos); 19 } 20 21 // Accessing elements using indexing 22 std::string first_fruit = fruits[0]; // "apple" 23 std::string last_fruit = fruits[fruits.size() - 1]; // "date" 24 25 // Now, fruits equals {"apple", "bilberry", "cherry", "date"} 26 return 0; 27}

In this code, the push_back() function adds "date" to the end of the fruits vector. The insert() function adds "bilberry" at the second position of the vector. The find() and erase() functions remove "banana" from the vector. We also use the indexing approach to access the first and last elements of the vector.

Understanding Strings

In C++, strings are a sequence of characters. This format offers a powerful set of abilities to store and manipulate text. We can directly access and modify individual characters using an index and convert the entire string to lowercase or uppercase.

To convert to lowercase, we can use the ::tolower function while to convert to uppercase, we have the ::toupper function.

Like vectors, strings also support the begin() and end() functions. These return iterators pointing to the beginning and position-past-the-end character of the string, which are very handy in many operations including transformations.

1#include <algorithm> 2#include <string> 3 4int main() { 5 // Creating a string 6 std::string greeting = "HeLLo, WoRlD!"; 7 8 // Accessing characters using indexing 9 char first_char = greeting[0]; // 'H' 10 char last_char = greeting[greeting.length() - 1]; // '!' 11 12 // Lowercasing the entire string 13 std::transform(greeting.begin(), greeting.end(), greeting.begin(), ::tolower); 14 // greeting becomes "hello, world!" 15 16 // Covert the string back to uppercase 17 std::transform(greeting.begin(), greeting.end(), greeting.begin(), ::toupper); 18 // greeting becomes "HELLO, WORLD!" 19 20 return 0; 21}

Here, the ::tolower and ::toupper functions convert the string into lowercase and uppercase respectively.

Remember that it is possible to modify the case of individual characters within the string by using the ::tolower and ::toupper functions along with the square bracket ([]) notation to specify the index of the character to be modified as follows: char lower_letter = ::tolower(greeting[index]).

Indexing and Common Operations

In C++, both vectors and strings can be accessed and manipulated using indices. This forms the basis for many useful operations, such as slicing, concatenating, and counting occurrences of a particular element, among others. Let's explore some of these operations:

  1. Slicing: This operation enables you to extract a portion of a vector or a string. For vectors, you can create a new vector using the range of iterators from begin() to end(). For strings, the substr() function can be used by specifying the starting index and the length of the substring.

  2. Concatenation: This involves joining two vectors or strings together. In vectors, you can add elements to the end of a vector using the insert() function, while for strings, you can simply use the + operator.

  3. Counting occurrences: You can count the number of occurrences of a specific element in a vector or string using the std::count() function.

Consider the following example using these operations:

1#include <algorithm> 2#include <string> 3#include <vector> 4 5int main() { 6 // Define a vector and a string 7 std::vector<int> my_vector = {1, 2, 3, 4, 5}; 8 std::string greeting = "Hello"; 9 10 // Slicing: get elements within a range 11 std::vector<int> slice_vector(my_vector.begin() + 2, my_vector.begin() + 4); // Extracts elements from positions 2 to 3 12 std::string slice_string = greeting.substr(1, 2); // Retrieves 'el' 13 14 // Concatenation: join two vectors/strings 15 std::vector<int> concatenate_vector(my_vector); 16 concatenate_vector.insert(concatenate_vector.end(), {6, 7, 8}); // appends {6, 7, 8} to my_vector 17 std::string concatenate_string = greeting + ", world!"; // concatenates ", world!" to "Hello" 18 19 // Counting occurrences of an element in a vector/string 20 int count_vector = std::count(my_vector.begin(), my_vector.end(), 2); // counts the number of occurrences of 2 in my_vector 21 int count_string = std::count(greeting.begin(), greeting.end(), 'l'); // counts the number of occurrences of 'l' in "Hello" 22 23 // Sorting items in a vector 24 std::sort(my_vector.begin(), my_vector.end(), std::greater<int>()); // Sorts in descending order 25 // my_vector becomes {5, 4, 3, 2, 1} 26 return 0; 27}

At the end of this code, we use the sort() function to sort the my_vector vector in descending order using the std::greater<int>() argument. By default, without this argument, the sort() function sorts in ascending order.

Lesson Summary and Practice

Great work! You've just reviewed the basics of C++ containers, with a focus on Vectors and Strings. You've learned how to create, access, and manipulate these data structures using various operations.

Up next, reinforce your understanding with plenty of hands-on practice. Understanding these concepts and practicing frequently will empower you to tackle more complex problem-solving tasks with ease. Happy coding!

Enjoy this lesson? Now it's time to practice with Cosmo!

Practice is how you turn knowledge into actual skills.