Part 2
Part 2
What Is an Array?
Before we discuss vectors, we will first learn about arrays, a simpler form
of a vector. An array is a data structure that stores a collection of data such
as ints, doubles, strings, etc. This data is often referred to as the array’s
elements. Being able to store elements into an array helps reduce the
amount of time needed to declare and initialize variables. For example, if
you wanted to store the ages of all family members in your household, you
would typically have to declare and initialize integer variables and values
for each family member. Copy the code below into the text editor on the
left and then click the TRY IT button to see the output. You can also click on
the ++Code Visualizer++ link underneath to see how the program runs
behind the scenes.
Code Visualizer
challenge
Code Visualizer
Array Creation
To avoid the repetitive task of declaring and initializing multiple variables,
you can declare an array and directly assign values or elements into that
array like below.
Code Visualizer
Specify the data type that the array will store (i.e. int).
Declare the variable name for the array (i.e. ages) followed by empty
brackets [] followed by the assignment symbol =.
Elements assigned to the array are separated by commas , and enclosed
within curly braces {}.
Additional information
If you used the Code Visualizer, you’ll notice that the array variable ages
refers to all of the elements as a collection. An array is considered to be a
collection that bundles all of the data that it holds.
Alternatively, you can create an array without any elements in which you
will need to declare and specify the array variable name and size before
you can assign elements to the array.
int ages[5];
Specify the data type that the array will store (i.e. int).
Declare the variable name for the array (i.e. ages) followed by the
number of elements you want the array to hold within brackets (i.e.
[5]).
Additional information
Note that when you declare an array without initializing any elements, the
system will still reserve enough memory for the array to hold the specified
number of elements. This means that you can initialize elements within the
array later on.
Array Details
If an element within an array has not been initialized yet, printing it will
cause the system to output random memory data. Random memory data
is often generated when array elements are not initialized.
int ages[5];
cout << ages[0] << endl;
Note that ages[0] in the example above refers the element at index 0, also
known as the first position within the array. Currently, the element at the
first position is not initialized so printing the first element will only output
random memory data. In fact, the same will happen if you try to print any
other elements within the array. Additionally, all elements within the array
must be of the same type. If you try to store a string within an integer array,
or a double within a boolean array, you will get an error message.
challenge
IMPORTANT
When you create an array in C++, you must specify the number of
elements that you expect the array to hold. Otherwise, you will get an
error.
P.O. Boxes at the postal office are symbolically similar to arrays. Each row
of P.O. Boxes is like an array, except each box can only store one item
(element) and each item within that row must be of the same type
(i.e. integers).
.guides/img/ArrayElementsIndices
Accessing an Array
Array Access
To access and print array elements, you need to know their position. The
position at which an element is stored is called its index. For example,
names[0] refers to the first element in the array called names. Array indices
always start at 0 and increment by 1 with each element that comes next.
Due to this, numbers[4] refers to the fifth element in the array, not the
fourth.
challenge
important
IMPORTANT
You may have noticed that printing the names array without specifying
an index resulted in an output that included a mixture of numbers and
letters. This occurs because printing an array actually prints its
memory location, not its elements. You’ll learn how to print all
elements in an array without having to specify all of their indices on a
later page.
challenge
IMPORTANT
Here are some key points to keep in mind when working with arrays:
If you do not initialize any elements, printing the elements will only
result in random memory data.
If you try to access an element position that is not valid (i.e. the
second element in the integers array), the system will also output
random memory data.
Elements must be of the same type as the array. The only exception
is that integers can be expressed as doubles and can therefore be
put into a double array.
.guides/img/ArrayExceptions
Modifying an Array
Array Modification
To modify an element within an array, simply find the index at which that
element is stored and assign a new value to it.
Code Visualizer
challenge
Code Visualizer
cout << family[0] << " " << age[0] << endl;
cout << family[1] << " " << age[1] << endl;
cout << family[2] << " " << age[2] << endl;
cout << family[3] << " " << age[3] << endl;
Code Visualizer
challenge
Code Visualizer
important
IMPORTANT
Since the integer array above was created without any initialization,
random memory data were populated as elements within the array at
first. Then by setting the array indices to specific values, you were able
to modify the array to include the appropriate age for each family
member.
Iterating an Array
Array Iteration
Though we can add many elements to our array, printing each of them can
get quite tedious. For example, if we have 10 names of friends in our array,
we would need to specify each of their array index to print them.
Luckily, we can use loops which we had learned previously to help us with
this process. To print out all of our friends’ names without repeating the
print statement ten times, we can use a for loop to iterate 10 times.
important
IMPORTANT
Did you notice that the print statement above includes i as the index
for friends? We do this because i will take on the values specified by
the for loop. The loop starts at 0 and increments by 1 until it reaches 9
(not including 10). Thus, friends[0] will print, then friends[1], so on
and so forth until friends[9] is printed. Then the loop ends.
Array Size
To make the iteration process easier, we can use the sizeof() operator to
determine how many elements are in our array. To use sizeof(), just call it
by using the keyword sizeof followed by the array name within
parentheses ().
Unfortunately, the sizeof() operator does not determine the number of the
elements within an array. Instead, sizeof() calculates the size of the array
in bytes. In C++, a string takes up 32 bytes and since there are 10 string
elements in the array, the size of the array in bytes is 320.
challenge
challenge
IMPORTANT
One of the main differences between a regular for loop and an
enhanced for loop is that an enhanced for loop does not refer to any
index or position of the elements in the array. Thus, if you need to
access or modify array elements, you cannot use an enhanced for
loop. In addition, you cannot use an enhanced for loop to iterate
through a part of the array. Think of an enhanced for loop as an all-or-
nothing loop that just prints all of the array elements or nothing at all.
Also note that the iterating variable type must match the array type.
For example, you cannot use for (int i : friends) since friends is a
string array and i is an integer variable. Use for (string i : friends)
instead.
Helpful Array Algorithms
Array Algorithms
In addition to being used with loops, arrays can also be used with
conditionals to help with tasks such as searching for a particular element,
finding a minimum or maximum element, or printing elements in reverse
order.
cout << Camry << endl; //print whether Camry exists or not
challenge
Sample Solution
string cars[] = {"Corolla", "Camry", "Prius", "RAV4",
"Highlander"};
string Prius = "A Prius is not available.";
cout << "The lowest grade is " << min << endl; //print lowest
element
challenge
Sample Solution
int grades[] = {72, 84, 63, 55, 98};
int max = grades[0];
cout << "The highest grade is " << max << endl;
What Is a Vector?
Although arrays are very useful for data collection, they are considered
static, meaning once they are created, you cannot add or remove elements
from them without changing the way they are initialized. Vectors, on the
other hand, are dynamic, meaning you can make changes to them while
the program is running. Vectors are particularly helpful when you don’t
know how large your collection of elements will become. Since vectors are
dynamic, you can add and remove elements later on if needed. In order to
use vectors, you must include #include <vector> in the header of your
program. For convenience, the program file to your left already contains
the included statement.
Vector Creation
To create a vector, you need to include the following:
* The keyword vector followed by the data type in angle brackets <>.
* A variable name that refers to the vector.
* The number of elements the vector can hold within parentheses ().
vector<int> numbers(3);
important
IMPORTANT
When you try to print an array reference variable, you will get the
array’s memory address. However, this is not the case for vectors.
To print an element within the vector, use the at() function and specify the
index of the position of the element you wish to print within the
parentheses.
vector<int> numbers(3);
Similar to arrays, the first index or position of the vector also starts at index
0. Thus, numbers.at(0) refers to the element at the first position in the
vector, which currently does not contain any initialized elements. When a
vector is declared without any initialized elements, the system will
populate the vector with 0 as elements by default. This is common across
vectors of many data types except strings. Additionally, if you try to output
an element at an index that does not exist, you will get an out_of_range
error message.
vector<int> numbers(3);
vector<int> numbers(3);
int digits[3];
challenge
IMPORTANT
In both arrays and vectors, you must specify how many elements you
expect them to hold. Otherwise, you will not be able to determine their
size. However, if you initialize the array or vector upon declaration,
then you don’t have to specify the number of elements since the system
can determine that automatically.
Adding and Removing Elements
cout << numbers.at(0) << endl; //50 becomes first and only
element
challenge
IMPORTANT
Arrays are strict when it comes to data type compatibility, however,
vectors are more flexible. Between the four common data types, string
is the only type that cannot be associated with the other three in a
vector. Integers, doubles, and booleans are all compatible with each
other. Remember, in C++, true is 1 and false is 0.
To add an element to a specific index in the vector, you can use the
insert() along with the begin() functions like below.
vector<int> numbers(2);
numbers.insert(numbers.begin()+1, 50); //add 50 to index 1
cout << numbers.at(0) << endl;
cout << numbers.at(1) << endl;
cout << numbers.at(2) << endl;
challenge
IMPORTANT
The begin() function always refer to the first position in the vector,
which is also the 0th index. If you want to refer to the 1st index, use
begin()+1. For the 2nd index, use begin()+2, so on and so forth.
challenge
To remove an element from a specific index in the vector, use the erase()
function and specify the index you want to erase with begin(). When an
element and its index is removed from the vector, all of the elements to its
right will be moved one place to the left.
vector<int> numbers(0); //empty vector
numbers.push_back(50); //add 50 to vector
numbers.push_back(100); //add 100 to vector
cout << numbers.at(0) << endl;
cout << numbers.at(1) << endl << endl;
numbers.erase(numbers.begin()); //removes 50
cout << numbers.at(0) << endl;
cout << numbers.at(1) << endl; //no longer exists
challenge
vector<string> contact(0);
contact.push_back("First name");
contact.push_back("Last name");
contact.push_back("Phone number");
cout << contact.at(0) << " "
<< contact.at(1) << " "
<< contact.at(2) << endl;
challenge
When initializing elements within a vector, you do not specify the number
of elements in parentheses. The system will automatically know how many
elements are being added to the vector. The initialized elements should be
in curly braces {} and separated by commas ,.
Iterating a Vector
IMPORTANT
When using an enhanced for loop for a vector, you must label the
iterating variable accordingly. If your elements are of type int then
your iterating variable must also be int. If the elements are strings
then your variable must be typed as string. However, you can always
use auto to force the variable to match your element type.
Vector vs. Array
Here is a table showing the differences between vectors and arrays. Note
that type stands for data type. Also note that var stands for vector or array
name, num stands for an integer number, index stands for index or position
number, and element stands for a vector or array element.
Find number of
var.size() sizeof(var)/sizeof(var[0])
elements
Access an
var.at(index) var[index]
element
Modify an
var.at(index) = element var[index] = element
element
var.push_back(element) or
Add an element var.insert(var.begin()+index, n/a
element)
Remove an var.pop_back() or
n/a
element var.erase(var.begin()+index)
string top[] = {"First: ", "Second: ", "Third: ", "Fourth: ",
"Fifth: "};
vector<string> names(0);
names.push_back("Alan");
names.push_back("Bob");
names.push_back("Carol");
names.push_back("David");
names.push_back("Ellen");
challenge
Sample Solution
string top[] = {"First: ", "Second: ", "Third: ", "Fourth: ",
"Fifth: "};
vector<string> names(0);
names.push_back("Alan");
names.push_back("Bob");
names.push_back("Carol");
names.push_back("David");
names.push_back("Ellen");
Vector Algorithms
Like arrays, vectors can be used to search for a particular element and to
find a minimum or maximum element. Additionally, vectors can reverse
the order of elements rather than just simply printing the elements in
reverse order.
vector<string> cars(0);
string Camry = "A Camry is not available."; //default string
value
cars.push_back("Corolla");
cars.push_back("Camry");
cars.push_back("Prius");
cars.push_back("RAV4");
cars.push_back("Highlander");
cout << Camry << endl; //print whether Camry exists or not
challenge
vector<string> cars(0);
string Prius = "A Prius is not available.";
cars.push_back("Corolla");
cars.push_back("Camry");
cars.push_back("Prius");
cars.push_back("RAV4");
cars.push_back("Highlander");
vector<int> grades(0);
grades.push_back(72);
grades.push_back(84);
grades.push_back(63);
grades.push_back(55);
grades.push_back(98);
cout << "The lowest grade is " << min << endl; //print lowest
element
challenge
Sample Solution
vector<int> grades(0);
grades.push_back(72);
grades.push_back(84);
grades.push_back(63);
grades.push_back(55);
grades.push_back(98);
cout << "The highest grade is " << max << endl;
important
IMPORTANT
Note that we used letters.erase(letters.begin()) which causes the
system to delete both the element and the index. Thus, the next
element in the vector becomes the new 0th index which we want to
continue to delete.
Learning Objectives: 2D Arrays
.guides/img/2DArray
string names[3][5];
2D Array Syntax
Array type followed by a name for the 2D array followed by two empty
pairs of brackets [][].
The number of rows goes inside the first pair of brackets and the
number of columns goes inside the second pair of brackets.
To determine the number of rows and columns in the 2D array, we can use
the sizeof() operator like we did for arrays.
string names[3][5];
important
IMPORTANT
Note that when determining column length, you must refer to the 2D
array’s 0th row index. For example, names[0] doesn’t just refer to the
first element in the row, it also refers to the entire column of elements.
See image above.
2D Array Access
To access and modify elements inside a 2D array, you need to specify the
row and column indices at which the elements are located. For example
names[1][2] refers to the element that’s at row index 1 and column index 2.
.guides/img/2DArray
Below is a code block showcasing a 2D array that contains fifteen P.O. Box
names from a postal office. Note that you can initialize the elements inside
your 2D array just like how you initialize elements inside a regular array.
Each column array is separated by curly braces {} as well as a comma ,.
important
IMPORTANT
Note that you must declare the number of elements within the column
brackets. You can leave the row brackets empty, but you cannot leave
the column brackets empty. Also, when you try to print an element that
is outside of the row/column range, the system will either print
random memory data or nothing at all.
2D Array Modification
To modify elements within a 2D array, simply access the element and
assign another element to it.
names[1][2] = "Harry";
cout << names[1][2] << endl;
challenge
2D Array Iteration
To iterate through a 2D array, we can use two for loops, one nested inside
another. The outer for loop is for the rows while the inner for is for the
columns.
Code Visualizer
challenge
Code Visualizer
Note that all of the columns’ lengths are the same, there are 3 columns for
each row. Therefore, it doesn’t matter if we use digits[0], digits[1], or
digits[2] when calculating the number of elements in each row and
column. Also note that using << endl prints the elements vertically while
removing it prints the elements horizontally. To print the elements so that
the columns stay together but the rows separate, we can try something like
this:
int digits[3][3] = { {1, 2, 3},
{4, 5, 6},
{7, 8, 9} };
Code Visualizer
Code Visualizer
You may have noticed that the outer loop contains for (auto &i : digits).
Unlike a regular array where we can access the first element by locating
just one index, we need two indices in order to access elements within a 2D
array. The &i creates a reference iterating variable that can refer to the 2D
array. We type it as auto because doing so will cause the system to force the
variable to match the 2D array type. In fact, we can always use auto to type
variables to cause them to match the data that they refer to. For example,
we can use for (auto j : i) for the inner loop instead of using int.
Also note that we cannot use an enhanced for loop to manipulate array
indices. Our iterating variable goes through the 2D array and takes on each
element value rather than each element index. This is why we have the
conditional statement if ((j == 3) | (j == 6) | (j == 9)) rather than
if (j == col - 1).
Lab: Arrays
classes[4] = "French";
Program Summary
vector<string> veggies(0);
veggies.push_back("carrot");
veggies.push_back("tomato");
veggies.push_back("celery");
veggies.push_back("spinach");
veggies.erase(veggies.begin()+1);
veggies.at(1) = "potato";
Program Summary
Code Visualizer
Lab Challenge: 2D Chessboard
2D Chessboard
You are trying to create a chessboard representation using the alphabetical
letters O and X. The O represents the lighter spaces while the X represents
the darker spaces.
OXOXOXOX
XOXOXOXO
OXOXOXOX
XOXOXOXO
OXOXOXOX
XOXOXOXO
OXOXOXOX
XOXOXOXO
So far you have the following code within the text editor to your left:
#include <iostream>
using namespace std;
int main() {
string chessboard[8][8];
return 0;
Chessboard Challenge
challenge
Assignment:
For this challenge, you will use your knowledge of 2D arrays to
produce the chessboard pattern:
OXOXOXOX
XOXOXOXO
OXOXOXOX
XOXOXOXO
OXOXOXOX
XOXOXOXO
OXOXOXOX
XOXOXOXO
Requirement:
Your program cannot make any changes to the existing code in the
program. If you do, you will not earn any credit for this challenge. If
you accidentally delete any existing code, you can copy the original
code shown above back into your program.
Hint: It is probably much easier to use nested for loops in your code to
populate the 2D array with either O or X than to go through each (row,
column) index to modify the elements.
Learning Objectives: Pointer Basics
Declare a pointer
Pointer Introduction
A pointer is a data type that stores a memory address of another piece of
data. Much like how an array points to all of its elements as a collection,
pointers point to the memory address of the data that they are associated
with.
.guides/img/PointerBasics
The picture above shows how pointers work. A pointer is like a key that
stores the address of the locker that it is associated with. This association
also enables the pointer to gain access to the content of what’s inside the
locker.
The advantage of using a pointer is that you do not need to worry about the
value of the data that the pointer is pointing to. Thus, if the data ever
changes its value, the pointer will still be able to access the new data as
long as the pointer still points to the data’s memory address.
Declaring a Pointer
Pointer Declaration
All pointers have a data type and a name that they are referred to. To
declare a pointer, you need to have the following syntax in order:
int* p;
challenge
important
IMPORTANT
The asterisk symbol can be placed anywhere between the end of
the data type (i.e. int) and the variable name (i.e. p). int* p;, int
*p, and int * p all work the same way.
Pointers that are not assigned a memory address will have a default
output of 0, also referred to as null pointers.
Reference Operator
Pointer Reference
A pointer can only be assigned a memory address. They cannot be
assigned values that are int, double, string, etc. A memory address is
denoted with the & symbol, called the reference operator, and they go in
front of the variable that the address is associated with.
int a = 2;
int* p = &a;
Code Visualizer
challenge
Code Visualizer
important
IMPORTANT
Memory is dynamic in C++ so whenever programs are compiled or
executed again, they will often output memory addresses that are
different from before.
Pointer Dereference
Every memory address holds a value and that value can be accessed by
using the dereference operator. The dereference operator is denoted by
the asterisk symbol *.
Code Visualizer
challenge
Code Visualizer
important
IMPORTANT
A pointer can only be assigned a memory address of a variable that
holds a value of the same type as the pointer. For example, if &a is
the memory address of an int variable, then you cannot assign it to
a string pointer (string* p = &a).
int a = 5;
int* p = &a;
int** p2 = &p;
Code Visualizer
challenge
Code Visualizer
important
IMPORTANT
Dereferencing a new pointer to an old pointer will return the memory
address of the old pointer. If that pointer is dereferenced again, then
the value of the variable that the old pointer pointed to will be
returned. For example, **p2 and *p both returned 5 because p2 points
to p which points to a which equals 5.
.guides/img/PointerTable
challenge
Fun Fact:
If you dereference an array, it will return only the first element in the
array.
Code Visualizer
Remember: The row index [3] is optional but the column index [6] is
mandatory.
The code above creates an array of characters where the row index [3]
refers to the three starting characters A for Alan, B for Bob, and C for Carol,
and the column index 6 refers to how many character each of the rows can
hold which also includes the null characters (NUL or \0). Notice how the null
characters also take up memory space.
.guides/img/ArrayNullCharacter
Here, we know how long the names would be, so we were able to budget
the right amount memory for them. However, what if we didn’t? In such a
case, we would have to assign additional space for our characters,
something larger, like 20 for example. That way, if the name Carol was a
mistake and it was actually supposed to be ChristopherJones, we can feel
more confident that the array will still be able to hold all of the characters.
Unfortunately, this causes more memory to be wasted as depicted in the
image below.
.guides/img/ArrayWasteMemory
Pointer Usage
This is where pointers come in handy because they can help the system
save memory. When using pointers for character arrays, the pointers will
only point to the 3 leading characters A, B, and C. You do not need to specify
the column index. Note that C++ requires the keyword const for pointers
that point to characters within an array. This forces the characters to
remain intact and prevents the pointer from potentially pointing
elsewhere.
const char* names[] = { "Alan",
"Bob",
"ChristopherJones" };
Code Visualizer
.guides/img/PointerArray
Notice how we did not have to include any index values, which means the
potential for wasting memory can be avoided. All we needed was to
reserve enough memory for the creation of 3 pointers.
Lab: Pointer Operators
bool b = true;
bool* p = &b;
A pointer can also point to another pointer. When doing so, the new
pointer will be denoted with two asterisk symbols **. ** is also used to
dereference a pointer twice.
bool b = true;
bool* p = &b;
bool** p2 = &p; //p2 points to p
Pointer Keys
You are trying to come up with a set of pointers or keys that, when referred
to, will be able to tell you the age of each of your family members. For
example, the pointer amy should be associated with the variable age1.
#include <iostream>
using namespace std;
int main() {
return 0;
Pointer Challenge
challenge
Assignment:
Your task is to associate the pointers within the code to their respective
variables. The output of your program should produce:
Requirement:
To receive credit for the challenge, you need to do the following:
* Only add to the existing code, do not make any changes, otherwise,
you will not receive credit for your work. If you accidentally delete any
existing code, you can copy the original code shown above back into
your program.
You must use the pointers amy, bob, and carol in your code and
assign the pointers to their appropriate data.
String Length
We have already seen strings in the “Fundamentals”section. We are going
to dig a little deeper with this data type. All strings have the following
characteristics:
To calculate the length of a string, use the length() function. This function
will return an integer that is the sum of all of the characters between the
quotation marks.
challenge
IMPORTANT
Although each character that you see on a typical keyword usually has
a length of 1, there are other foreign characters that do not follow this
convention. For example, Привет, which stands for Hello in Russian,
actually has a length of 12 instead of 6.
String Index
Previously in the vectors module, we learned that vectors and arrays have
elements that reside in certain positions or indices. A string too has indices
that correspond to the position where each of its character resides. Like
vector and array indices, string indices also start at 0.
.guides/img/StringIndex
.guides/img/StringAtIndex
string my_string = "Hello!";
char character = my_string.at(1);
challenge
Mutability
You now know how to reference each character of a string. What do you
think the code below will do?
If you thought the code above would print Mouse, that would be a logical
guess. However, you see an error. Unlike vectors and arrays where the
characters can be manipulated, string literals are immutable. That means
you cannot change the string literal itself. You can, however, manipulate a
particular character within the string.
Can you spot the difference between the two code snippets mentioned
above? The difference lies within the double quotes "" and single quotes ''.
You cannot change the string literal, but you can change a character at a
particular index. Thus, my_string.at(0) = 'M' changes the string to Mouse
but my_string.at(0) = "M" does not.
String Re-Assignment
In addition to character manipulation, you can also change the entire
string itself by overwriting it with a new value(s).
.guides/img/MutabilityAssignment
Find
string my_string = "The brown dog jumps over the lazy fox.";
challenge
string my_string = "The brown dog jumps over the lazy fox.";
.guides/img/StringSubstr
string my_string = "The brown dog jumps over the lazy fox.";
string my_slice = my_string.substr(4, 9);
challenge
Escape Characters
An escape character is a character that has a different interpretation than
what you see in a string. Escape characters always start with a backslash
(\). The most common escape character is the newline character (\n) which
causes C++ to print on the next line.
Escape
Description Example
Character
\\ Prints a backslash cout << "\\" << endl;
Prints a single
\' cout << "\'" << endl;
quote
Prints a double
\" cout << "\"" << endl;
quote
Prints a tab cout << "Hello\tworld" <<
\t
(spacing) endl;
challenge
When you use a " to start a string, C++ looks for the next " to end it. To
avoid syntax errors, you can use a double quote to start your string, single
quotes for the inner quote, and end the string with a double quote.
challenge
.guides/img/FindFirstOf
string string1 = "The brown dog jumps over the lazy fox.";
string string2 = "brown";
challenge
Note that the index specification comes before the string you want the
system to add. For example, my_string.insert(0, "abc") will add the
string abc to the 0th index which is also the beginning of the string. To add
to the end of the string, you can use my_string.length(). Note that you do
not need to subtract 1 from my_string.length() because the system will
add characters starting at the index after the last character of the string.
string my_string = "Today is Satur";
my_string.insert(my_string.length(), "day");
challenge
challenge
my_string.replace(1, 2, "3")
challenge
string a = "High";
string b = " Five";
challenge
important
IMPORTANT
NOTE that the append() function is exclusively for strings. Thus, you
cannot include other data types like ints when using append() unless
they are converted to strings first. Additionally, when using the +
operator to combine two strings together, make sure that at least one
of the strings is a string variable. Otherwise, the system will think you
are trying to manipulate a string literal, which is not allowed.
Uppercase & Lowercase
.guides/img/StringToUpper
challenge
challenge
challenge
Note that you can also use a range-based or enhanced for loop to iterate
over strings. Make sure to cast the iterating variable as char!
While Loop
String iteration is most often done with a for loop. However, a while can be
used as well.
challenge
Above are two ways of iterating through a string. The first way uses the for
loop and the second uses a while loop. Both produces the same result.
However, the for loop is usually preferred because it requires less code to
accomplish the same task. You can also use an enhanced for loop, which
requires the least account of code, but an enhanced while loop does not
exist.
Learning Objectives: String
Comparison
Compare strings with == and !=
Comparing with ==
The == operator can be used with strings just like it is with numbers or
boolean values. Note that without the boolalpha flag, the system will return
1 if true and 0 if false. 1 represents string equality and 0 represents
inequality.
challenge
Comparing with !=
You can also test for string inequality with the != operator.
Lexicographical Order
In C++, strings can be compared lexicographically, meaning they can be
compared according to how they will appear in the dictionary. You can use
the compare() method to determine which of two strings comes first. A
return value of a negative integer means the first string comes first, a
return value of a positive integer means the second string comes first, and
a return value of 0 means the strings are equal and neither comes first.
if (string1.compare(string2) < 0) {
cout << "string1 comes first" << endl;
}
else if (string1.compare(string2) > 0) {
cout << "string2 comes first" << endl;
}
else {
cout << "the strings are equal" << endl;
}
challenge
if (string1.compare(string2) < 0) {
cout << "string1 comes first" << endl;
}
else if (string1.compare(string2) > 0) {
cout << "string2 comes first" << endl;
}
else {
cout << "the strings are equal" << endl;
}
challenge
String Functions
You will need two string functions that were not covered earlier to help
with this project:
* isupper() - Returns an integer greater than 0 if the character is
uppercase, 0 if the character is not.
* islower() - Returns an integer greater than 0 if the character is
lowercase, 0 if the character is not.
Variables
You will need three variables for this project. One variable will count all of
the lowercase characters, another to count the uppercase characters, and
one for the string itself.
int lower_count = 0;
int upper_count = 0;
string my_string = "Roses are Red, Violets are Blue";
The next thing to do is iterate over the string and to check each character of
the string. A enhanced for loop works best.
if (islower(ch)) {
lower_count += 1;
}
What you do not want to do is use an else statement. This will not give you
an accurate count. For example, asking if a special character is lowercase
will return 0. However, that does not mean that it is an uppercase character
either. Special characters are neither uppercase nor lowercase. So use an
else if statement and ask if the character is uppercase. If so, increment
the uppercase counting variable.
else if (isupper(ch)) {
upper_count += 1;
}
The final step is to print the messages with the count values.
cout << "There are " << lower_count << " lowercase characters."
<< endl;
cout << "There are " << upper_count << " uppercase characters."
<< endl;
Code
int lower_count = 0;
int upper_count = 0;
string my_string = "Roses are Red, Violets are Blue";
cout << "There are " << lower_count << " lowercase
characters." << endl;
cout << "There are " << upper_count << " uppercase
characters." << endl;
Lab 2
Reverse a String
You are going to write a program that takes a string and prints it in reverse
order.
Variables
All you need for this program is the string variable and a loop to iterate
through the string.
string my_string = "The brown dog jumps over the lazy fox";
String Iteration
Since we are going to reverse the order of the string, we will need to start at
the end of the string and iterate back to the front. Unfortunately, an
enhanced for loop will not help us in this case because it only iterates from
left to right. However, we can still use a regular for loop.
The for loop should start at the back my_string,length()-1 and run as long
as index is greater than or equal to 0. After each iteration, the iterating
variable should also decrement by 1 to allow the loop to reverse.
Reversing a string comes down to taking the character from the end
printing that first, then go backwards. This will be done by accessing the
indices with at().
my_string.at(i);
All that’s left to do is print. Remember not to include endl or the system
will print a newline after each character.
Code
string my_string = "The brown dog jumps over the lazy fox";
Variables
You are going to need two string variables. The first string variable
represents the original string and the second represents the modified
string. For now, the modified string can be empty.
String Iteration
It does not matter if you start at the beginning of the string or the end for
iteration. An enhanced for loop is the easiest way to iterate through the
original_string. Set the iterating variable as ch.
String Functions
You are going to use the isupper() and islower() functions to test if a
character is uppercase or lowercase. In addition, you will be using the
toupper() and tolower() functions to convert characters to their new cases.
Conditional
if (islower(ch))
If this is true, then append the uppercase version of the character to the
variable modified_string.
modified_string += toupper(ch);
else {
modified_string += tolower(ch);
}
Once the loop has finished, print both the original string and the modified
string.
cout << "The original string is: " + original_string << endl;
cout << "The modified string is: " + modified_string << endl;
The original string is: THE BROWN DOG JUMPS over the lazy fox!
The modified string is: the brown dog jumps OVER THE LAZY FOX!
Code
string original_string = "THE BROWN DOG JUMPS over the lazy
fox!";
string modified_string;
cout << "The original string is: " + original_string << endl;
cout << "The modified string is: " + modified_string << endl;
Lab 4
Variables
For this project, you will need three variables. One will be the string.
Another will be a char to represent each character of the string. The final
variable will be a count of all the vowels.
string my_string = "The Brown Dog Jumps Over The Lazy Fox";
char ch;
int count = 0;
String Iteration
Use a for loop to iterate through the string. Then set ch to check every
character in the string.
Use a conditional to see if the characters in the string are equal to any
vowels. Make sure to account for both uppercase and lowercase vowels.
Note that characters are wrapped in single quotes ' ', not double quotes in
C++.
Incrementing the Counter
count += 1;
The string may contain no vowels, one vowel, or more than one vowels.
Thus, you’ll need conditionals to output the appropriate responses.
if (count == 0) {
cout << "There are no vowels in the string." << endl;
}
else if (count == 1) {
cout << "There is 1 vowel in the string." << endl;
}
else {
cout << "There are " << count << " vowels in the string." <<
endl;
}
Code
string my_string = "The Brown Dog Jumps Over The Lazy Fox";
char ch;
int count = 0;
if (count == 0) {
cout << "There are no vowels in the string." << endl;
}
else if (count == 1) {
cout << "There is 1 vowel in the string." << endl;
}
else {
cout << "There are " << count << " vowels in the string." <<
endl;
}
Lab Challenge: Vowel Replacement
Some of the code has already been filled out for you. Your task is to
complete the program so that it produces some of the sample output below.
If you accidentally change anything from the original code, you can copy
and paste the code back into the text editor.
#include <iostream>
using namespace std;
return 0;
Expected Output
Hll
Expected Output
ppl
Expected Output
Wtrmln!
Requirements
You should not make any changes to the code that already exists. If you
accidentally delete any existing code, you can copy and paste the entire
program from above.
You can use any number of string functions and conditionals to
produce the desired output.
Learning Objectives: Reading
Demonstrate how to open a file using ifstream
File Basics
This module is all about working with files on a computer. The first step is
to locate the desired file. That means being able to navigate the file system.
The file we are going to use is called practice1.txt. It is located in the text
folder, which is inside the folder called student. So the path to the file is:
student/text/practice1.txt.
File Path
Use a string to represent the file path. This string will be passed to direct
the system to open a file.
ifstream file;
file.open(path);
You’ll see that Command was successfully executed. is returned, which isn’t
very helpful. To know if the file was opened successfully, you can set up
conditions like so:
ifstream file;
file.open(path);
if (file.is_open()) {
cout << "File successfully opened." << endl;
}
else if (!file.is_open()) {
cout << "File failed to open." << endl;
}
challenge
Before your program terminates, it is a best practice to close the file. When
a file is opened, it takes up memory that will not free up until the file is
properly closed.
string path = "student/text/practice1.txt"; // setting file path
challenge
What is cerr?
When printing error messages, cerr is preferred over cout. cerr is not
bufferred, which means it is not stored in memory to be printed later
on. It just gets printed immediately. Therefore, as a rule of thumb,
important data and variables should be printed with cout while error
messages should be printed with cerr.
Reading a File
Reading a File
Let’s start reading from a file that contains some text. First set the string
path to student/text/readpractice.txt. Then open the file and handle any
opening errors. To read from a file, use the getline() function. The
getline() has at least two parameters; the first is the input stream to read
from and the second is a string to store what is read.
try {
ifstream file;
string read; //create string to store what is read into
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
getline(file, read);
cout << read;
file.close();
cerr << "File successfully opened and closed." << endl;
}
catch (exception& e) {
cerr << e.what() << endl;
}
important
IMPORTANT
You’ll notice from above that the system printed File successfully
opened and closed. first and then C++ was created by Bjarne
Stroustrup. was printed. This is due to cerr being unbuffered, which
means it gets printed immediately. cout is buffered, so it will store its
content into memory before printing, which explains the delay. This
doesn’t mean that cerr always gets printed first, it just depends on
what on quickly cout stores its content.
To see the content of the file readpractice.txt, click this link here:
readpractice.txt
If you take a look at the content of the file, you’ll see that it has more text
than just C++ was created by Bjarne Stroustrup.. The reason why only
one line of text was printed is because getline() only reads up until a
newline character is reached. To continue to read more lines of text, wrap
getline() inside a while loop.
try {
ifstream file;
string read; //create string to store what is read into
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) {
cout << read;
}
file.close();
cerr << "File successfully opened and closed." << endl;
}
catch (exception& e) {
cerr << e.what() << endl;
}
challenge
try {
ifstream file;
char ch; //create string to store what is read into
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (file.get(ch)) {
cout << ch;
}
file.close();
cerr << "File successfully opened and closed." << endl;
}
catch (exception& e) {
cerr << e.what() << endl;
}
Change cout << ch; in the new code to cout << ch << endl;?
The get() function in the new code works similarly to the getline()
function. However, get() reads character by character instead of by
strings.
Additionally, did you notice that File successfully opened and closed.
was printed at two different locations before and after << endl was added?
This all depends on how quickly cerr and cout work behind the scenes. To
avoid inconsistencies in printing, we’ll avoid printing the success message
moving forward.
Reading a Buffer
try {
ifstream file;
file.open(path); //content of file goes into memory buffer
if (!file) {
throw runtime_error("File failed to open.");
}
cout << file.rdbuf(); //read the buffered content
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
challenge
If the file is closed, the buffer gets flushed to clear the memory that was
used. So after a file is closed, you will not be able to read the buffered
content anymore.
Delimiters
Delimiters
Delimiters are a predefined character that separates one piece of
information from another. Some common delimiters involve white spaces
(' ') and commas (','). When using getline() previously, we only made
use of two of its parameters. It actually has a third parameter which is
reserved for a delimiter. By default, this delimiter is the newline character
('\n'). Thus the parameters for getline(x, y, z) are:
* The stream source (x).
* The string variable to store what is read (y).
* The delimiter to separate the content of the stream source (z).
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
getline(file, read, ','); //specify comma as delimiter
cout << read;
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
When a delimiter is applied, the system will read only up to that delimiter.
This is why you only see content up through the first comma occurrence. If
you want to continue reading further and get to the other comma
occurrences, you can put the command inside a while loop.
string path = "student/text/readpractice.txt";
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, ',')) { //specify comma as
delimiter
cout << read;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
The code above continues to read the stream and separates the content via
the delimiter, ,. This is why there are no commas present in the output.
However, it doesn’t look very clear that the stream has been separated
since the system continues to print the remainder of the stream. You can
add << endl to the output so that the system will print a newline after each
delimiter is reached so that you can see clearer where the content is
separated.
string path = "student/text/readpractice.txt";
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, ',')) { //specify comma as
delimiter
cout << read << endl;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
challenge
Tokens
When we apply a delimiter to break up a stream or string, the resulting
separated strings are sometimes referred to as tokens. Tokens are useful if
you want to use their data for further analysis later on. For example, you
can store each token as an element in a vector in which you can extract
further information from later on. What do you think the code below does?
The following file contains the first and last names of 5 individuals:
names.txt
string path = "student/text/names.txt";
vector<string> names;
string last_name = "Smith";
int count = 0;
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, ' ')) {
names.push_back(read);
}
file.close();
for (int i = 0; i < names.size(); i++) {
if (i % 2 == 1) {
if (names.at(i) == last_name) {
count++;
}
}
}
cout << "There are " << count << " people whose last name is
Smith." << endl;
}
catch (exception& e) {
cerr << e.what() << endl;
}
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, ' ')) {
names.push_back(read);
}
file.close();
for (int i = 0; i < names.size(); i++) {
if (i % 2 == 0) { //start checking index 0 and then
every other index
if (names.at(i) == first_name) { //first name found
count++;
}
}
}
cout << "There are " << count << " people whose first
name is Jackie." << endl;
} //change the print statement as needed
catch (exception& e) {
cerr << e.what() << endl;
}
Jason Seymore
Jackie Simmons
Jennifer Small
Jane Smith
John Smith
Then using the code above will cause issues since it only takes a white
space as a delimiter, not a newline. To include both the newline and white
space as delimiters, you can use a stringstream data type (#include
<sstream>) to create another string stream off of the string variable read.
The first getline() function will separate the stream using a newline as the
delimiter and the second getline() will use a white space as a delimiter.
string path = "student/text/names2.txt";
vector<string> names;
string last_name = "Smith";
int count = 0;
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) { //newline delimiter
stringstream ss(read); //create a string stream of read
while (getline(ss, read, ' ')) { //white space delimiter
names.push_back(read);
}
}
file.close();
for (int i = 0; i < names.size(); i++) {
if (i % 2 == 1) {
if (names.at(i) == last_name) {
count++;
}
}
}
cout << "There are " << count << " people whose last name is
Smith." << endl;
}
catch (exception& e) {
cerr << e.what() << endl;
}
challenge
Notice how you get the same result regardless of how your names are
organized in the text file.
Ignore Function
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) {
cout << read << endl;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
Now compare the output above with the output from the code below. C++
will ignore the first 29 characters and start reading only from the character
at position 30.
string path = "student/text/readpractice.txt";
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
file.ignore(30); //ignore all chars before index 30
while (getline(file, read)) {
cout << read << endl;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
challenge
Writing to a File
When writing to a file, you’ll want to use ofstream instead of ifstream. Like
before, create your string path, open the file, and check for whether it can
be opened successfully.
try {
ofstream file;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
}
If the file is successfully opened, you can start writing to the file using the
insertion operator << followed by what you want to write in double quotes
"". Remember to close the file, and if you want, you can print a message at
the end telling the user that that the file was successfully written to.
string path = "student/text/practice1.txt";
try {
ofstream file;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
file << "Hello there";
file.close();
cerr << "Finished writing to file.";
}
Click on the link to open the file and see what was wrttien: Open
practice1.txt
challenge
Open practice1.txt
try {
ofstream file;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
file << "Hello there";
file.close();
ifstream stream;
string read;
stream.open(path);
while (getline(stream, read)) {
cout << read << endl;
}
stream.close();
}
challenge
Multiline Strings
In addition to being able to write and output string literals (e.g. file <<
"Hi!";), we can also write and output the content of variables (e.g. file <<
var;). Let’s tweak the code from the previous page to write multiple
messages to a text file called practice2.txt. We’ll create three string
variables, text1, text2, and text3. The first message will go into a string
variable text1, the second will go into text2, and the third will go into
text3.
try {
ofstream file;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
string text1 = "Hello, ";
string text2 = "your balance is: ";
string text3 = "12.34";
file << text1 + text2 + text3;
file.close();
ifstream stream;
string read;
stream.open(path);
while (getline(stream, read)) {
cout << read << endl;
}
stream.close();
}
Open practice2.txt
challenge
Change file << text1 + text2 << endl; to file << text1 + text2
<< '\n';?
Change file << text1 + text2 << '\n'; to file << "Hello, your
balance is:\n12.34"; and remove file << text3;?
Open practice2.txt
Notice how you can also write the content of other types of data (double,
int, etc.) to a file. You are not restricted to just strings. Also, there are
multiple ways to write the same kind of content to a file.
Appending to a File
Appending to a File
You may have noticed that every time a file is opened using an ofstream
object, a new file is always created, even if one already exists (the system
just overwrites the existing file). If you want to add to an existing file, you
have to tell C++ to open the file in append mode. Let’s look at the code
below and TRY IT.
try {
ofstream file;
file.open(path, ios::app); //open file in append mode
if (!file) {
throw runtime_error("File failed to open.");
}
string text = "Adding to the file.";
file << text;
file.close();
ifstream stream;
string read;
stream.open(path);
while (getline(stream, read)) {
cout << read << endl;
}
stream.close();
}
Open practice3.txt
Since there is no practice3.txt file at the start of the program, C++ will
create one. However, try running the code again and see what happens.
Open practice3.txt
You’ll notice that the output Adding to the file. shows up twice in the file.
This happens because we have included the tag ios::app as a second
parameter when we opened up the file practice3.txt. By default, an
ofstream object has the flag ios::out as a second parameter, which causes
the file to always get overwritten. By changing the parameter to ios::app,
we’re telling the system to add to the file instead of overwriting it.
challenge
Open practice3.txt
If you follow through the challenges above, you’ll notice that when the flag
is set to input mode ios::in, the system will overwrite the content without
creating a new file or overwriting the old one. On the other hand, ios::app
will add to the end of the existing content. Lastly, ios::out creates a
completely new file and writes to it.
Learning Objectives: CSV
Define CSV
CSV Files
C++ can work with files besides just text files. Comma Separated Value (CSV)
files are an example of a commonly used file format for storing data. CSV
files are similar to a spreadsheet in that data is stored in rows and columns.
Each row of data is on its own line in the file, and commas are used to
indicate a new column. Here is an example of a CSV file.
You can read a CSV file in the same way you read a text file. First create an
ifstream object and then open the CSV file using it.
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, ',')) {
cout << read + ' ';
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
To iterate through the CSV file, we use while (getline(file, read, ',')).
Since CSV files contain commas that separate information, we set the
delimiter to ','. Then we print the content by using cout << read + ' '.
We add a space to separate the tokens from each other since it is not
apparent that the information is tokenized from using just cout << read;.
challenge
By using cout << read << endl; you can clearly see each token line by line.
Depending on your preference, you can choose to arrange the tokens in a
variety of different formats.
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
file.ignore(19); //Ignore the first 19 characters from index
0-18
while (getline(file, read, ',')) {
cout << read << endl;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
challenge
The file.ignore(500, '\n'); command tells the system to skip the first
500 characters or up through the newline character \n. Since there are
fewer than 500 characters, the system will skip everything up through the
first occurrence of the newline. You can add additional ignore commands
to ignore more lines of data if needed.
Printing CSV Data
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, ',')) {
cout << read + " ";
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
To better organize our CSV data, we can store the data into a vector and
then format and print elements in a way that looks more organized.
string path = "student/csv/homeruns.csv";
vector<string> data;
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) {
stringstream ss(read);
while (getline(ss, read, ',')) {
data.push_back(read);
}
}
file.close();
for (int i = 0; i < data.size(); i++) {
if (i % 3 == 0) {
cout << setw(20) << left << data.at(i);
}
else if (i % 3 == 1) {
cout << setw(15) << left << data.at(i);
}
else {
cout << data.at(i) << endl;
}
}
}
catch (exception& e) {
cerr << e.what() << endl;
}
To organize our data, we use conditionals to split our elements into three
columns. if (i % 3 == 0) refers to the elements in the first column, else
if (i % 3 == 1) refers to the second column, and else refers to the third.
We use the setw() function to provide padding for our elements. For
example, setw(20) means that the system will reserve 20 characters for the
elements. If the element does not take up 20 characters, then white spaces
will occupy those spaces. To use setw(), you’ll need #include <iomanip> in
the header of your file. The left tag forces the element to be aligned to the
left side.
challenge
Notice how the last column Active Player is not formatted and is therefore
unaffected by the changes.
important
IMPORTANT
The order or placement of where you use left and setw() can affect all
streams that follow. So it’s important to keep track of the changes that
take place as you print. For example outputting
Writing to CSV Files
try {
ofstream file;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
file << "Greeting,Language" << endl;
file << "Hello,English" << endl;
file << "Bonjour,French" << endl;
file << "Hola,Spanish";
file.close();
ifstream file2;
string read;
file2.open(path);
while (getline(file2, read, ',')) {
cout << read + ' ';
}
file2.close();
}
To organize the CSV data, you can add each token into a vector and then
use conditionals to format and print the data like before.
string path = "student/csv/writepractice.csv";
vector<string> data;
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) {
stringstream ss(read);
while (getline(ss, read, ',')) {
data.push_back(read);
}
}
file.close();
for (int i = 0; i < data.size(); i++) {
if (i % 2 == 0) {
cout << setw(15) << left << data.at(i);
}
else {
cout << data.at(i) << endl;
}
}
}
catch (exception& e) {
cerr << e.what() << endl;
}
Lab 1
Lab 1
As you read a text file, you go line by line until you reach the end of the file.
What happens if you want to go back to a specific line of text? A common
practice that comes with reading text from a file is to store that information
into something like a vector. This way you can easily reference any data
obtained from the file.
Before reading the file, create the path variable with the file path, and
instantiate the string vector text.
Use try, throw and catch blocks to handle input/output exceptions. In the
try portion, create an ifstream object to read through the file and store its
content into a string variable. While reading, add each line to the vector
text. Print any errors in the catch portion. You can optionally print a
message that the file has successfully been read, but that is not required.
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) {
text.push_back(read);
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
The content of the text file now resides in the vector variable text.
However, the code above only adds text from the file into the vector. To
print what was stored in the vector, use a loop to iterate the vector’s
elements first followed by the cout command.
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) {
text.push_back(read);
}
for (int i = 0; i < text.size(); i++) {
cout << text.at(i) << endl;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
You should see a passage from Bram Stoker’s Dracula. You’ll notice,
however, that the output is just a collection of text grouped together. In
fact, if you were to print the first element in the vector, you will get the
same result. The entire file was read and stored as the first element in the
vector. This occurs because the default delimiter is a newline and there is
only 1 occurrence of a newline at the end of the file.
Let’s change the delimiter into a period . so that the text will be tokenized
into sentences. Each token will represent one sentence from the passage.
string path = "student/labs/fileslab1.txt";
vector<string> text;
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, '.')) { //set delimiter as a period
text.push_back(read);
}
for (int i = 0; i < text.size(); i++) {
cout << text.at(i) << endl;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, '.')) {
text.push_back(read + '.'); //add period to end
}
for (int i = 0; i < text.size(); i++) {
cout << text.at(i) << endl;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, '.')) {
text.push_back(read + '.');
}
cout << text.at(1); //print the second element/sentence
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
To erase the first leading white space, you can use text.at(1).erase(0, 1).
This will take the system to the first position, index 0, and erase just 1
character in that string.
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read, '.')) {
text.push_back(read + '.');
}
cout << text.at(1).erase(0, 1) << endl; //erase the first
string char
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
Lab 2
Lab 2
This lab uses a comma delimited CSV file fileslab2.csv, which contains
integers. There are three columns and four rows. The program below will
print the sum for each row in the CSV. This is what the file currently looks
like:
1,4,5
18,34,99
0,12,51
37,29,61
We’ll start with directing the path to the file, creating a vector nums to store
the data for later, creating an ifstream and string to read and hold the
content of the file temporarily, and using try, throw and catch blocks to
handle any issues when opening the file.
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
After, use the getline() function to iterate through the file and store its
content as tokens in the vector. Note that you will need to go through the
file twice and include a stringstream object to further help tokenize the
data. Try running the code below to see what’s currently stored.
string path = "student/labs/fileslab2.csv";
vector<string> nums;
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) {
stringstream ss(read);
while (getline(ss, read, ',')) {
nums.push_back(read);
}
}
for (int i = 0; i < nums.size(); i++) {
cout << nums.at(i) << endl;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
You should see a list of numbers after the code runs. Though what you see
are numbers, they are currently strings which means we cannot do
calculations on them directly. We must convert them into integers first
using stoi(). Additionally, the data is stored in a vector which is one
dimensional but we want to calculate totals for multiple rows. To achieve,
we’ll use a double nested for loop to iterate through the vector in chunks of
three elements which will allow us to calculate the totals of each row.
string path = "student/labs/fileslab2.csv";
vector<string> nums;
try {
ifstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (getline(file, read)) {
stringstream ss(read);
while (getline(ss, read, ',')) {
nums.push_back(read);
}
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
Total: 10
Total: 151
Total: 63
Total: 127
Lab 3
Lab 3
The goal of this lab is to rely on user input for data. We are going to
continuously ask the user to enter the name of a superhero followed the
name of their power. If the user enters lowercase q, the system will stop
collecting data and write all of the data collected to the CSV file
superheroes.csv.
First let’s create our string path, ofstream object, read string, and exception
blocks like usual.
try {
ofstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
Next, we need to create variables for our user input. Additionally, we also
need to continuously ask the user for output until they enter q. After q is
detected, the information entered will be written to our CSV file.
string path = "student/labs/superheroes.csv";
string name;
string power;
try {
ofstream file;
string read;
file.open(path);
if (!file) {
throw runtime_error("File failed to open.");
}
while (true) {
cout << "Please enter a superhero name (or enter q to quit):
";
cin >> name;
if (name == "q") {
break;
}
cout << "Please enter a superhero power (or enter q to
quit): ";
cin >> power;
if (power == "q") {
break;
}
file << name << ',' << power;
}
file.close();
}
catch (exception& e) {
cerr << e.what() << endl;
}
Click the TRY IT button to enter information into the terminal. Enter q to
stop the data collection and write to to the CSV file. Click on the CSV file link
below to see everything that was entered.
Open superheroes.csv
Lab Challenge
Lab Challenge
Write a program that reads a text file . This file is stored in the variable
path.
The file contains several instances of the word Burma. Replace each instance
of Burma with Myanmar, and print the results of this transformation. The final
output of your program should be:
Hint
You can use the FindAndReplace() function to replace all instances of Burma
with Myanmar. Note that you will need to store the content of the file into a
string in order to use this function.