Summary
Text is the most frequent datum of a program: names, messages, lines of a file, a user’s commands. This lesson treats it as what it is for C++, a sequence of characters with operations of its own. It presents std::string, which is created, concatenated, compared and traversed like a vector of char with the job of a text; its search and extraction operations (find, substr, starts_with, contains) and the value std::string::npos, with which find says that it found nothing; std::string_view, the view that observes a text without copying it, and the condition on which it depends: that the observed text still exists. The lesson closes with C strings, for reading other people’s code, and with the order in which C++ compares and sorts words.
Learning objectives
- Use the operations of
std::string(size,+,find,substr,starts_with,contains) to solve text problems. - Interpret the result of
findand check it againststd::string::npos, and predict what happens if it is treated as an ordinary number. - Receive text in a function as
std::string_viewand explain with an example why a view must not outlive the string it observes. - Read code with C strings and explain how they differ from
std::string: the null terminator, the fixed size and the sum of two literals, which does not compile.
The string std::string
Create, concatenate, traverse
The lesson Characters, Booleans, conversions and constants presented the character, char, as a small number that a table turns into a letter. A text is a succession of characters; if this is so, it can be stored in a std::vector<char>, and what the lesson Vectors taught about sequences would hold for it. Now, a text is asked for operations that an arbitrary sequence is not: to append another text to it, to search it for a word, to extract a piece of it, to write it all at once. From this follows a type of its own, the string, std::string, from the header <string>: a vector of char with the job of a text.
#include <format>#include <print>#include <string>int main(){ const std::string first{"Ada"}; std::string greeting{"Hello, " + first}; greeting += '.'; std::println("{} ({} characters)", greeting, greeting.size()); std::println("First “{}”, last “{}”", greeting[0], greeting.back()); int spaces{0}; for (const char c : greeting) { if (c == ' ') { ++spaces; } } std::println("Spaces: {}", spaces); const std::string code{std::format("{}-{:03}", "MAT", 7)}; std::println("{} {}", code, code == "MAT-007");}Hello, Ada. (11 characters)First “H”, last “.”Spaces: 1MAT-007 trueLine 7 creates a string from a literal. Line 8 concatenates it: the operator + between a string and a literal produces a new string with the characters of both, one after the other. Line 9 appends a character at the end with +=, which also accepts a string or a literal. The rest is what was already known about vectors: size() counts the characters (11, because the comma, the space and the period are characters too), greeting[0] is the first and back() the last, and the loop on lines 13 to 17 traverses the string character by character with the range form of the lesson Loops. Like the vector, a string also admits push_back, pop_back and empty, and the GCC 15 library, when it does not optimize, checks its indices with operator[] (with optimization, that check disappears).
The last two lines fulfill what the lesson Designing with functions announced. std::format, from <format>, takes the same placeholders as std::println, with the same format specifications ({:03} pads with zeros up to three digits), but instead of writing the result it returns it as a string: it is the way to build a text that is later stored, compared or passed to a function. And == compares two strings by their content: they are equal if they have the same size and the same characters in the same order. Therefore code == "MAT-007" is true, even though the text on the left was built piece by piece and the one on the right is a literal.
Comparing
Besides == and !=, strings admit <, <=, > and >=, which compare them in lexicographic order, the order of the dictionary: the two are traversed side by side, and at the first position where they differ the smaller character decides; if one runs out first without any difference, the shorter one is the smaller. Thus the string “cast” is less than “cost”, because 'a' < 'o' in the second position, and “sea” is less than “seal”, because the first is a prefix of the second. The operators compare strings: between two literals written in quotation marks they compare something else, because a literal is not a std::string but an array, as the section on C strings will show. Which character is “less” is decided by its code, not by the alphabet; the last section of the lesson shows what follows from this.
Loading the content…
Completed
Sign in to save your progress