08: Strings
UC Irvine - Fall ‘22 - ICS 45C
Quick list of things I want to talk about:
- Mutable
- c_str
- Quotes
- Size
Expanded notes:
Basics
A string is a type we use to store a bunch of text (a sequence of char
s).
However, strings are not a base type and not included by default in C++, so you should add a new include at the top of your file:
#include <string>
Similarly to cout
and cin
, strings are also a part of the std
namespace, which we’ll learn more about it next week.
For now, if you are using the using namespace std
directive, it should all work out.
Declaring a string
We can create a string just like any other variable:
string test; // empty string
string other_test = "this one is initialized!";
One thing to note here is the double quotes! String require you to use those, if you use single quotes the compiler will want a single character inside of it.
A string has a some similarities to arrays:
- no bound checks;
- index access with
[]
;
However, when you create a string without initialization like the example above, we can assume that it’s empty.
Mutability
Another similarity to arrays, and unlike in other languages, strings in C++ are mutable! So you could modify an existing index like this:
string msg = "hello";
msg[0] = 'H';
Unlike other arrays, you can append to a string like this:
string msg = "Hello";
msg += " world!";
If you do that, you modified the original string, and did not create a new one.
Size
As you saw above, a string is similar to a char
array, but we can actually change its size.
That works because string objects are not fully stored in the stack.
They actually are split between the stack and the heap, where we have more space and flexibility how to use it.
Again, we’ll get more into this when we cover pointers!
Comparisons
In C++11, we can compare strings using ==
, !=
, <
, <=
, >
, and >=
.
All these comparisons compare the two strings alphabetically, not based on the actual objects.
Taking strings as input
So far we have been using cin >> x
to take input.
And if we try it out with strings, at first it seems to work fine:
string name;
int age;
cout << "Please enter your name and age: ";
cin >> name >> age;
cout << "Name: " << name << "\nAge: " << age << '\n';
If you run this code with this output:
Alice 20
You should see this output:
Name: Alice
Age: 20
Similarly, if you have that same input broken into lines you should see the same output. Using
Alice
20
as input would give us the same result.
However, what if Alice wants to type her last name too? What happens?
By using cin >> name >> age
, cin
is trying to be smart and break things apart.
In that case, it would use the space as a delimiter, and only the first string would work as a name.
So if you had this input:
Alice Zane 20
Or this:
Alice
Zane
20
Or this:
Alice Zane
20
cin
would assign Alice
to our variable name
, but then try to convert the string Zane
into an integer… which doesn’t work!
So we would end up with this output:
Name: Alice
Age: 0
To go around that, we can ask our code to read an entire line into a variable. So instead of trying to break values by space, you can store everything until the user presses enter/return.
To do that, we can use the getline
function.
getline
takes two arguments, where it’s reading from and where to store it.
In the previous example, it would work like this:
string name;
int age;
cout << "Please enter your name and age: ";
getline(cin, name);
cin >> age;
cout << "Name: " << name << "\nAge: " << age << '\n';
Here, we’re trying to read from cin
and store it in name
.
By doing it like this, we can store the entire first line in our variable.
So if the input is:
Alice Zane
20
You should see this output:
Name: Alice Zane
Age: 20
Methods
String objects have a bunch of methods that you can use. A few that I think might be useful:
empty
returns a bool indicating if the string is empty;size
andlength
return the size of characters in the string;max_size
returns the maximum number of characters that you can store in the string;find
finds a sequence of characters starting from the beginning;rfind
finds a sequence of characters starting from the end.
There are also some functions that might be useful:
stoi
to convert a string to anint
;stof
to convert a string to afloat
.
You can see all the methods and functions available here: https://en.cppreference.com/w/cpp/string/basic_string
Note that there isn’t a split
method, which lets you tokenize a string.
However, you can combine existing methods and string-functions to achieve the same goal, e.g., https://stackoverflow.com/a/14266139
C-strings
Whenever you’re looking for resources online, you might see strings defined as char str[]
or char *str
.
That means it is an array of char
s.
This happens because on C, an array of char
s is how you define strings, and they should always be terminated with a value of 0
.
So, for example, if you want to store the word hi
in a char []
, you will need 3 positions.
One for 'h'
, one for 'i'
, and one for 0
, which is a null character that indicates the string terminated.
The reason you might see this in C++ is because some libraries that were originally written in C are still used.
To make it easy for you, if you ever need to use a “c-style string”, the C++ string has a c_str
method that you can use.
References
- Comic reference: https://twitter.com/system32comics/status/1221891795157581824
- Comic context: https://knowyourmeme.com/memes/press-f-to-pay-respects