2.4. The string class¶
Like a byte string, a std::string
is storage for a character sequence:
#include <string> // access std::string functions
using std::string; // alias type std::string to 'string'
int main() {
string x; // empty string
string greet = "Hello, World!"; // create from C string
string hello ("Hello, World!"); // as above, constructor style syntax
string howdy = {"Hello, World!"}; // C++11 only
string howdy {"Hello, World!"}; // as above, = is optional
return 0;
}
What is different is that a std::string
is a full-fledged object.
It knows it’s own size, and comes with many convenience functions.
Notice that unlike a built-in variable declaration such as int x;
,
the declaration string x
is not incomplete.
The variable x
is a complete and valid string
object
that stores no characters.
This tab shows alternate functions for accessing the first and last characters in a string.
The append
function allows you to append N copies of a character or
an array of characters to the end of a string.
The insert
function allows you to insert 1 character or
an array of characters at a position in a string.
Using the operator[] to access select characters in a string is,
like an array,
not range checked.
This means that if you use an index referring to an invalid position,
then your program might have undefined behavior, or fail unexpectedly.
You can use the function at anywhere operator[]
is allowed.
The at
function is range checked.
While there is a cost associated with this check,
if the index provided is out of range,
then an std::out_of_range exception is thrown,
which must be caught,
otherwise the program will terminate.
if (a == b)
{
b.at(0) = 'H'; // might be OK
b.at(-1) = 'W'; // never OK. throws exception
}
Remember that a std::string
is not a byte string.
std::string
is a class.
A decision was made long ago that in order to remain more compatible with
C, double quited strings should evaluate to byte strings.
Declarations like this are a common source of confusion for new programmers:
auto my_string = "Howdy!";
What type is my_string
?
my_string
is not a std::string.
The default type for characters enclosed in double quotes is const char*
.
This is one of those situations where auto may not be deducing the type
you actually want.
There are several simple ways to use auto and get the type
deduced to be a std::string
.
In C++14, you can simply append an s
to the end of the string literal.
This identifies the literal as type std::string.
auto my_string = "Howdy!"s; // preferred
Alternatively, you can call the string constructor explicitly, which works for C++ versions older than C++14.
auto my_string = string("Howdy!");
auto your_str = string{"Howdy!"}; // C++11 initialization syntax
Note
Look carefully at the size values printed for s1
and s2
.
Are those sizes expected? Why or why not?
2.4.1. Getting information out of a string¶
A string
knows its own size and can provide other useful information.
#include <cassert>
#include <string>
using std::string;
int main() {
string my_string = "Hello";
assert( my_string.size() == 5 ); // .length() is available also
if (!my_string.empty()) {
my_string += ", there."; // my_string == "Hello, there."
}
return 0;
}
And the string class provides many functions dedicated to finding substrings within a string.
The simplest example is the find function.
Given any string object, for example, this string:
auto us = "team"s;
defined using the C++14 string literal syntax,
creates a new object us
.
Once we have a string
, calling the string member function
find always returns a position:
Either a position within the string, or
The special value std::string::npos which means the value was not found in the string.
We can use this to check if we found what we were looking for:
size_t pos = us.find('i');
if(pos == std::string::npos) {
std::cout << "There is no 'i' in 'team'\n";
}
The position returned by find is a zero-based index into the string.
Find can also take a sequence of characters.
In that case, it returns the position to the first char
where the entire sequence is matched.
Reverse find
Similar to find
, rfind performs the same
task as find, but iterates through the string in reverse order:
starting at the end and moving towards the first character.
Keep in mind that the position returned is still based
on the same index positions as regular find
.
Find first of
The find_first_of function takes a char
sequence,
but unlike find where the entire sequence is used to find a match,
find_first_of
examines each character in the sequence,
on at a time, and returns the minimum position of any
of the characters listed as function arguments in the string.
For example:
auto hi = "Hello world"s;
pos = hi.find_first_of("aeiou"); // pos == 1 (e)
The function returns the position of ‘e’ in ‘Hello world’, even though ‘e’ and ‘o’ are both present, because ‘e’ is first.
The order of the character arguments do not matter. The results would be exactly the same if the arguments were ‘uoiea’. Don’t take my word for it, try it yourself.
The special value std::string::npos is used both as an end of string indicator by functions that expect a string and as an indicator of not found by functions that return an index (like find).
2.4.2. Convert a byte string to a number¶
Another common string task is parse a C string and extract a numeric value.
The number conversion functions are part of the string
header.
There are number conversion functions that C++ inherits from C.
They are all in the cstdlib
header.
Of these C functions, the atoi
and atof
functions should not be used.
They fail silently.
That is if something bad happens, there is no way to check and even detect
whether the function completed its task.
stoi extracts an integer value from a string.
stoi
discards any whitespace characters until the first non-whitespace
character is found,
then takes as many characters as possible to form a valid integer
number representation and converts them to an integer value.
The valid integer value consists of the following parts:
an optional plus or minus sign
the digits 0-9
stod extracts an floating point value from a byte string.
Other than return value, it functions similarly to stoi
.
All of these functions allow for error handling, which we will cover in a future chapter. For now, know that these function will generate errors if given bad or unexpected input.
2.4.3. Converting a std::string to a C string¶
You cannot use std::string
in a function
that expects const char*
- you must convert it
to a null terminated character array.
auto my_name = "Alice"s;
printf ("Hello again, %s\n", my_name); // compile error!
// the c_str() function converts a string into a c string
printf ("Hello again, %s\n", my_name.c_str());
Self Check
sc-1-10: Given the following:
std::string x = "The rain in Spain. . . ";
size_t pos = x.find("in");
What is the value of pos
?
sc-1-12: Given the following:
#include <string>
int main (){
std::string s = "Donald Duck";
int value = 0;
if (s.find_first_of(' ') == s.find_last_of(' ')) {
value = 3;
} else {
value = 5;
}
return value;
}
What value is returned from main?
More to Explore
cppreference.com Strings library overview
YoLinux String class tutorial
Bjarne Stroustrup’s C++11 FAQ: Raw String literals