Search

S.4.4b — An introduction to std::string

What is a string?

The very first C++ program you wrote probably looked something like this:

So what is “Hello, world!” exactly? “Hello, world!” is a collection of sequential characters called a string. In C++, we use strings to represent text such as names, addresses, words, and sentences. String literals (such as “Hello, world!”) are placed between double quotes to identify them as a string.

Because strings are commonly used in programs, most modern languages include a built-in string data type. C++ includes one, not as part of the core language, but as part of the standard library.

std::string

To use strings in C++, we first need to #include the <string> header to bring in the declarations for std::string. Once that is done, we can define variables of type std::string.

Just like normal variables, you can initialize or assign values to strings as you would expect:

Note that strings can hold numbers as well:

In string form, numbers are treated as text, not numbers, and thus they can not be manipulated as numbers (e.g. you can’t multiply them). C++ will not automatically convert string numbers to integer or floating point values.

String input and output

Strings can be output as expected using std::cout:

This prints:

My name is: Alex

However, using strings with std::cin may yield some surprises! Consider the following example:

Here’s the results from a sample run of this program:

Enter your full name: John Doe
Enter your age: Your name is John and your age is Doe

Hmmm, that isn’t right! What happened? It turns out that when using operator>> to extract a string from cin, operator>> only returns characters up to the first whitespace it encounters. Any other characters are left inside cin, waiting for the next extraction.

So when we used operator>> to extract a string into variable name, only “John” was extracted, leaving “Doe” inside std::cin, waiting for the next extraction. When we then used operator>> to get variable age, it extracted “Doe” instead of waiting for us to input an age. We are never given a chance to enter an age.

Use std::getline() to input text

To read a full line of input into a string, you’re better off using the std::getline() function instead. std::getline() takes two parameters: the first is std::cin, and the second is your string variable.

Here’s the same program as above using std::getline():

Now our program works as expected:

Enter your full name: John Doe
Enter your age: 23
Your name is John Doe and your age is 23

Mixing std::cin and std::getline()

Reading inputs with both std::cin and std::getline may cause some unexpected behavior. Consider the following:

This program first asks you to enter 1 or 2, and waits for you to do so. All good so far. Then it will ask you to enter your name. However, it won’t actually wait for you to enter your name! Instead, it prints the “Hello” line, and then exits. What happened?

It turns out, when you enter a value using cin, cin not only captures the value, it also captures the newline. So when we enter 2, cin actually gets the string “2\n”. It then extracts the 2 to variable choice, leaving the newline stuck in the input stream. Then, when std::getline() goes to read the name, it sees “\n” is already in the stream, and figures we must have entered an empty string! Definitely not what was intended.

A good rule of thumb is that after reading a value with std::cin, remove the newline from the stream. This can be done using the following:

If we insert this line directly after reading variable choice, the extraneous newline will be removed from the stream, and the program will work as expected!

Rule: If reading values with std::cin, it’s a good idea to remove the extraneous newline using std::cin.ignore().

What’s that 32767 magic number in your code?

That tells std::cin.ignore() how many characters to ignore up to. We picked that number because it’s the largest signed value guaranteed to fit in a (2-byte) integer on all platforms.

Technically, the correct way to ignore an unlimited amount of input is as follows:

But this requires remembering (or looking up) that horrendous line of code, as well as remembering what header to include. Most of the time you won’t need to ignore more than a line or two of buffered input, so for practical purposes, 32767 works about as well, and has the benefit of being something you can actually remember in your head.

Throughout these tutorials, we use 32767 for this reason. However, it’s your choice of whether you want to do it the “obscure, complex, and correct” way or the “easy, practical, but not ideal” way.

Appending strings

You can use operator+ to concatenate two strings together (returning a new string), or operator+= to append a string to the end of an existing string).

Here’s an example of both, also showing what happens if you try to use operator+ to add two numeric strings together:

This prints:

4511
45 volts

Note that operator+ concatenated the strings “45” and “11” into “4511”. It did not add them as numbers.

String length

If we want to know how long a string is, we can ask the string for its length. The syntax for doing this is different than you’ve seen before, but is pretty straightforward:

This prints:

Alex has 4 characters

Note that instead of asking for the string length as length(myName), we say myName.length().

The length function isn’t a normal standalone function like we’ve used up to this point -- it’s a special type of function that belongs to std::string called a member function. We’ll cover member functions, including how to write your own, in more detail later.

Conclusion

std::string is complex, leveraging many language features that we haven’t covered yet. It also has a lot of other capabilities that we haven’t touched on here. Fortunately, you don’t need to understand these complexities to use std::string for simple tasks, like basic string input and output. We encourage you to start experimenting with strings now, and we’ll cover additional string capabilities later.

Quiz

1) Write a program that asks the user to enter their full name and their age. As output, tell the user how many years they’ve lived for each letter in their name (for simplicity, count spaces as a letter).

Sample output:

Enter your full name: John Doe
Enter your age: 46
You've lived 5.75 years for each letter in your name.

Quiz solutions

1) Show Solution

S.4.5 -- Enumerated types
Index
S.4.4a -- Explicit type conversion (casting)

441 comments to S.4.4b — An introduction to std::string

  • VerticalLimit

    Hi Nascardriver
    Any suggestions to make it better ?

    Quiz 1

    • - Line 12: Initialize with empty curly braces. Only explicitly initialize if you're using the value.
      - Line 15: Brace initialization.
      - Line 15: Don't use C-style casts, they're unsafe.
      - Limit your lines to 80 characters in length for better readability.

  • Piyush Pranjal

    if this function call, what we get.

    My expectation to get, Underweight, Normal, Over Weight.

    Am I right or wrong?

    Because my program breaks when this function's call occurred.

    • Your function has to return, no matter what happens.
      If `x < 16.0f` or `x > 40.0f` your function doesn't return.

      You don't need all those duplicate comparisons, use `else if`.

      • Piyush

        Thanks Bro.
        Successfully updated my code and getting unknown at this moment.
        Now I need to find what is wrong with the argument.

        • You don't need to compare `x` to `18.5f` in line 7 or `25.0f` in line 11, you already checked those.

          • Piyush

            What happens if we get 6.0 as a parameter value. So, 9th line will be executed or not?

            if this function gets 6.0 as parameter value than 9th line will be executed or not?

  • Parsa

    Is there a particular reason why string variables are initialized using parenthesis?

  • Parsa

    Is the string library really necessary?

    The type string is already defined for me without the library.

  • Samira Ferdi

    Hi, Alex and Nascardriver!

    My compiler throw an error if I do this:

    But, if I do this:

    My program works! Why is that?

    • Assuming `name` is an `std::string`.
      `std::string::length` return an `std::size_t`, which is an unsigned integer type. Converting and unsigned integer to signed causes loss of precision.
      Add a `static_cast<int>`. Use brace initialization.

      • Samira Ferdi

        Thanks, for reply!

        So, you mean is

        or

        My next question is why 32767 in std::ignore(32767, '\n')?
        Why don't let's say 30, 300, 230 or 1?

        • The first version.
          Don't pass 32767 to `std::cin.ignore`. It's a magic number Alex made up because he's too lazy to type. It doesn't have any special meaning to the function.
          Pass `std::numeric_limits<std::streamsize>::max()`. It causes `std::cin.ignore` to ignore everything until the specified character ('\n') is found.

  • Grego

    Hello All,

    In "Appending strings" you state that "You can use operator+ to concatenate two strings together, or operator+= to append one string to another.", however in the following code block, you say this:

    Concatenate and append are both used when referring to '+' operator.
    Hence my question is : Should I worry about the functional difference between the two at this point and if yes, what is it?

Leave a Comment

Put all code inside code tags: [code]your code here[/code]