Strings

Strings

Earlier we mentioned strings, and how they are the technical term for text in C++. This chapter is all about strings and how they work. And the tools C++ offers to work with them.

Our current primary input and output system is all string-based. Mastering strings lets us master this medium. This will unlock a whole new world of possibilities for programs.

Due to this, a lot of practice tasks and projects will be unlocked during this chapter. Many great tasks will unlock almost every single lesson, so make sure to check into the practice area.

std::string and the char datatype

char our_char = 'V';

This is a char. char is short for character and holds a single character.

The single quotation marks indicate the value of a char. A char can only hold 1 character or escape sequence.

It cannot be empty, meaning it has to have a char inside it, even if that character is the space character.

When we stack a bunch of these chars after each other in an array, we get a string.

Many IDEs will show you the datatype of a hovered value. Here you can see that this string is a character array in disguise.


When we work with text, we want to be able to change the length of the text, and because of this we often need to resize the char array.

std::string is an STL container that works like std::vector and std::deque. It's a dynamic array that handles resizing and memory allocation for us. It is optimized for storing and working with strings. Every element is by default a char.

std::string will handle any resizing of the text for us, and give us a library of useful functions.

std::string is declared in the <string> header. You can declare it and use it like a variable.

#include <iostream>
#include <string>

int main()
{
    std::string some_text = "Hello World!\n";

    std::cout << some_text;
}
Hello World!

Using std::string like a variable

You can get user input and store it as a string in the exact same way as you would with other variables using std::cin.

std::string input;
std::cin >> input;

One problem that you might run into is that std::cin likes to separate inputs through spaces. This is done so that you can store multiple inputs from the same std::cin call.

std::cin >> input1 >> input2 >> input3;

Because of this, a string input will be separated after a space. To get around this we can use the getline function.

getline captures the entire line.

std::string input;
getline(std::cin, input);

This allows us to capture sentences instead of the first word.


You can use the addition operator to glue 2 pieces of text together.

std::string text1 = "Entry";
std::string text2 = "Point";
std::string output = text1 + text2;
std::cout << output;
EntryPoint

The assignment version += also works to append text to another string. The rest of the math operators don't do anything.

We can compare strings using equals to == and not equals to !=.

int main() 
{
    std::cout << "What is the secret code?\n";
    std::string input;
    getline(std::cin, input);

    if (input == "Cowboys rule!")
    {
        std::cout << "Welcome in cowboy!\n";
    }
    else
    { 
        std::cout << "We don't allow strangers. Please leave. \n"; 
    }
}

If the user inputs Cowboys rule! they get a different prompt than if they don't.

Using std::string as an array

You can use the subscript operator ([x]) on a std::string object to access a single character.

You can use this in a loop to access each character.

std::string our_text = "ENTRY";
for (int i = 0; i < our_text.length(); i++)
	std::cout << "- " << our_text[i] << " -\n";

Here each character is accessed and printed individually.

You can also use iteration loops with std::string to cycle the characters in the text.

std::string our_text = "ENTRY";
for (char c : our_text)
	std::cout << "- " << c << " -\n";

Output for both pieces of code:

- E -
- N -
- T - 
- R - 
- Y - 

Characters & ASCII

Chars are quite similar to integers.

In binary, we can see the comparison between integers and characters. The binary data of 'c' and 99 are the exact same.

What separates them, is that we have specified 'c' to be a char, so the program treats the data as a character instead of an integer.

These numbers that represent each letter are known as ascii codes. An ASCII table is used to give us an overview of which characters represent which codes, and vice versa.

This table also gives you an overview of how int and char are cast to each other.

The characters' ASCII codes, or their integer values, are being compared when we use the lesser than or greater than operators on them.


Strings can also be compared with greater than or lesser than operators. When a string is compared to another using a "greater than" operator, the char values are compared from start to finish. The first letter to differ is used to decide which is greater than the other.

For example "ABCD" < "ABDD" is true. 'A'(65) == 'A'(65) 'B'(66) == 'B'(66) 'C'(67) < 'D'(68) At this point, the computer has already decided that "ABDD" is greater than "ABCD". The rest of the string isn't compared.

std::string member functions 1

std::string has a bunch of member functions that help us work with strings, many of which are also in std::vector.

Getting data

std::string::size and std::string::length functions the same as std::vector::size.

They return the number of elements (characters) in the string. Both exist because we talk about length in relation to strings, whereas most other STL containers use .size()

std::string::empty tells you if a string is empty.

It returns true if the string is empty, and false if it is not. Using this instead of str == "" makes the intent clear, and gives more consistency with other STL containers. Performance is the same though, so it's mostly preference.

std::string::find finds the first position of a string or character inside a string.

It takes 2 arguments:

  1. What std::string, or char to search for
  2. The position of the string search to start from. This argument is by default 0, which means the start of the string.

If the string or character isn't found, the string will return the constant std::string::npos. You can use this to check if the string wasn't found.

if (str.find('c') == std::string::npos) 
    std::cout << "'c' was not found in str";

If str doesn't have any c's in it 'c' was not found in str will print.


str.find("hi", 5); will return the starting position of the first "hi" that occurs inside str after index 5. In the case of str being "hi friend, high five!" this function will return 11. It's returning the index of the "hi" in "high".

std::string::substring returns a string based on the content inside a range of another.

It takes 2 parameters, the index of the start and the length of the substring.

std::string("Hello World!").substr(6, 5) will return "World".

The second parameter defaults to std::string::npos. if the second parameter is std::string::npos it will get the rest of the string until its end.

std::string::begin, std::string::end, std::string::rbegin, std::string::rend do the exact same thing as in std::vector

Click here for a refresher

std::string member functions 2

Altering data

std::string::clear removes all characters in a string, rendering it empty.

Using str.clear() can be slighly easier to read than str = "";, and shows that the intent of the statement is to empty the string.

std::string::append adds to the content of a string.

It's similar to the += operator. It takes a string argument and adds that to the end of the current string.

std::string str = "Hello ";
str.append(" World!");

str now contains "Hello World!".

You can also append a single character. str.append('!');.

std::string::erase and std::string::insert work the same as std::vector::erase and std::vector::insert.

You can use std::string::erase in the same way for strings as you do for vectors. With one iterator input to delete a single element. str.erase(str.begin() + idx) or with 2 to delete a range: str.erase(str.begin() + idx, str.begin() + idx2).

You can also pass a normal index value and how many letters you want to delete. This is a version that doesn't use iterators. std::string("Hello World!").erase(3, 3) turns into "He World!"

std::string::insert works the same way as std::vector::insert. It inserts a string or character at the specified position. str.insert(str.begin() + idx, "inserted text");

std::string::insert also has iterator-less variations. str.insert(idx, "inserted text"); does the same thing as the previous insert code.

std::string::push_back & std::string::pop_back are the same as std::vector::push_back & std::vector::push_back

.push_back() takes a single char and adds it to the end of the string. .pop_back() removes the last char of the string.

std::string::replace replaces a part of the string with another string.

It takes 3 arguments:

  1. The starting position of the replacement
  2. The length of the text to be replaced.
  3. The text that will replace it.
    std::string str1 = "Hello, world!";
    str1.replace(7, 5, "Earth");
Hello Earth!

You can use indexes or iterators for the first and second arguments.

    std::string str1 = "Hello, world!";
    str2.replace(str2.begin() + 7, str2.begin() + 12, "Earth");
Hello Earth!

Null-terminated Strings

std::string is a modern implementation of strings, that came along with C++. C-style strings can be used to hold text without std::string.

std::string should be your go-to whenever you're working with strings. However, knowing about null-terminated strings lets you navigate older libraries that rely on them.

C-style strings are null-terminated. This means that it's an array of char elements terminated by a null character (\0). The null character signifies the end of the string to any function that processes it.

char null_terminated_string[] = "Hello";
// Array content: {'H', 'e', 'l', 'l', 'o', '\0'}

The null character is crucial. Functions that operate on C-style strings use this character as an endpoint marker. The function wouldn't know when to stop without it.

Conversion to std::string

You can convert between std::string and C-style strings. std::string has a member function .c_str() that returns a C-style version of the string.

std::string str = "Hello";
const char* cstyle_str = str.c_str();

You can use this to use std::string when working with code that requires C-style strings.

You can get a std::string object from a C-style string by assigning it to the object.

const char* cstyle_str = "Hello World!\n";
std::string str = cstyle_str;

C-style strings are useful for low-level or performance-critical code. However, I would recommend using std::string whenever possible because of the safety and ease of use.

Questions

Questions

Questions

Questions

Questions

Questions

Questions

Questions