InfoCode

C++ · Strings

Strings

Trace the newline left after numeric cin input and use getline to read a full line with spaces, alongside character counts, palindromes, find and substr.

Written by InfoCode · Technical references below

Practice this topic in the app Read the lesson in the app

String access and common operations

You can think of a string as a train: each car holds one letter, and the indices are numbered starting from 0. s[0] is the first car, s[1] is the second car……

There are two common ways in C++:

Common practice tasks: counting characters, reversing strings, checking palindromes, finding substrings, and converting character case.

Common member functions: size()/length() returns the length, empty() checks whether the string is empty; substr(pos,len) takes a substring, find returns a position or string::npos; insert(pos,text) inserts, erase(pos,len) deletes, replace(pos,len,text) replaces. pos must be valid, and len is a length rather than an ending index. To read an entire line containing spaces, use getline; if a number was read before, handle the leftover newline first.

After cin, what is left for getline?

cin >> name reads one word and stops at whitespace. By default, getline(cin, name) reads through the next newline, preserving spaces within the line and consuming the newline. Assume the input format is an integer on the first line and a full name on the next: 3\nAda Lovelace\n. Here \n denotes a newline character.

OperationRemaining inputValue obtained
Start3\nAda Lovelace\nNothing read
cin >> n\nAda Lovelace\nn = 3
Discard the rest of the first line, including its newlineAda Lovelace\nName not read yet
getline(cin, name)Emptyname = "Ada Lovelace"

If getline follows the number immediately, it encounters the leftover newline and returns an empty string. It has not skipped the next line automatically. For this input format, after successful numeric extraction, use cin.ignore(numeric_limits<streamsize>::max(), '\n') to discard the remainder of the current line, then read the name. This discards any other characters on that line too, so it is unsuitable when the number and name share a line.

First common error: calling getline twice unconditionally can consume a line that should be kept. Second: treating getline(cin >> ws, name) as a universal fix. ws skips all leading whitespace, including blank lines and spaces at the start of a name. When those matter, handle only the current line according to the input format. The program below checks extraction success; recovering from invalid numeric input is a separate topic. Reading k text characters involves processing them, rather than fixed O(1) work.

Run and check: a number followed by a full line

#include <iostream>
#include <limits>
#include <string>
int main() {
    int n;
    std::string name;
    if (!(std::cin >> n)) { return 0; }
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    if (!std::getline(std::cin, name)) { return 0; }
    std::cout << n << " [" << name << "]\n";
}

Input two lines: 3 and Ada Lovelace. Output: 3 [Ada Lovelace]. Brackets make empty strings and preserved spaces visible.

Try before revealing each answer

Does ignoring through the newline still work if two spaces follow 3 on the first line?

Yes. The remaining spaces and newline on that line are discarded. Ignoring only one character can leave other whitespace behind.

If the next line starts with two spaces followed by Ada, does the example keep those spaces?

Yes. getline does not skip leading spaces on the next line. Applying ws first would discard them.

Can you use the same ignore step if the input is 3 Ada Lovelace on one line?

No: it would discard the name too. Establish the input format before deciding how to read the remaining text.

Character counts, palindromes and string edits

Example 1: Count the number of occurrences of each letter in a string

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s = "Hello World";
    int cnt[26] = {0};
    for (char c : s) {
        if (c >= 'a' && c <= 'z') cnt[c - 'a']++;
        if (c >= 'A' && c <= 'Z') cnt[c - 'A']++;
    }
    for (int i = 0; i < 26; i++) {
        if (cnt[i] > 0)
            cout << (char)('a' + i) << ": " << cnt[i] << endl;
    }
    return 0;
}

Use c-'a' to convert a letter into an index from 0 to 25 and store it in an array, then traverse and output at the end. In "Hello World", d:1 e:1 h:1 l:3 o:2 r:1 w:1.

Example 2: Determine whether a string is a palindrome

#include <iostream>
#include <string>
using namespace std;

int main() {
    string s;
    cin >> s;
    int n = s.length();
    bool ok = true;
    for (int i = 0; i < n / 2; i++) {
        if (s[i] != s[n - 1 - i]) {
            ok = false;
            break;
        }
    }
    cout << (ok ? "YES" : "NO") << endl;
    return 0;
}

Input "racecar", n=7, compare s[0] with s[6], s[1] with s[5], s[2] with s[4], all are equal, output YES.

Example 3: Find, substring, insert, and delete

#include <iostream>
#include <string>
using namespace std;
int main() {
    string s = "hello world";
    auto pos = s.find("world");
    if (pos != string::npos) s.replace(pos, 5, "C++");
    s.insert(0, "Hi! "); s.erase(0, 4);
    cout << s << " " << s.substr(0, 5) << endl;
}

Output hello C++ hello. Only use the position after find succeeds; the 5 in replace is the number of characters to replace.

Tips

Prerequisites

Technical references

Scope note

This lesson is written by InfoCode and is not an official syllabus; the reference level is a site mapping and does not represent official levels, certification or eligibility. Practice records do not establish mastery or eligibility.

Reference level: GESP Level 3 (site mapping)

See contest pathways