STRINGS IN C++

Lesson Content: Strings in C++

Welcome to the lesson dedicated to strings in C++! In this lesson, you will learn what strings are, how to use them, and why they are one of the most important data types when working with text.

This lesson is structured from basic concepts to more advanced techniques, so you can gradually build a strong understanding of string manipulation.

We will cover:

  • basic concepts of working with text
  • the char data type
  • C-style strings (arrays of characters)
  • modern C++ strings using std::string
  • input, processing, and transformation of text
  • real-world string manipulation techniques
Why are strings important?

Strings are used everywhere:
  • user input (names, messages)
  • file processing
  • search algorithms
  • data parsing (e.g. CSV, logs)
Understanding strings is essential for solving real-world programming tasks.

Tip:

In modern C++, you should almost always use std::string instead of C-style character arrays, because it is safer, easier to use, and less error-prone.

What you will learn


Before you continue:

Think about this:
  • How is a word like hello stored in memory?
  • Is it one variable or multiple characters?
You will discover the answer in the next section.

Learning tip:

Try to understand not only what each function does, but also how they work together. Most real-world problems require combining multiple string operations.

Introduction to Strings in C++

Strings in C++ represent sequences of characters used to store and manipulate textual data.

There are two main approaches to working with strings:

  • C-style strings: arrays of characters terminated by a null character ('\0'). They require manual memory management and are more error-prone.
  • C++ strings (std::string): a modern and safer solution from the standard library (<string>). They automatically manage memory and provide many useful functions.
Key idea:

A string is not a single value — it is a sequence of characters stored in memory.
Best practice:

In modern C++, always prefer std::string over C-style strings. It is safer, easier to use, and less prone to errors.

In this lesson, you will learn how to create, modify, and analyze strings, as well as how to avoid common mistakes when working with text.

Think about it:

How is the word hello stored in memory?
  • Is it one variable?
  • Or multiple characters?
You will understand this after the next section.

Data Type char in C++

The char data type stores a single character. Internally, it is represented as a number (most commonly ASCII code).

It is actually an integer type that occupies 8 bits of memory and is mainly used for storing character codes.

Important:

A char is not just a symbol — it is a number behind the scenes.

// Example: char stores both character and number
#include <cstdio>

int main() {
    char c = 'A';

    printf("%d, %c\n", c, c);
    // %d → prints numeric value (ASCII code)
    // %c → prints character

    return 0;
}

// Output:
// 65, A

First, the integer value representing the character code of 'A' is displayed, followed by the character itself.

The format specifier "%d" is used for printing the numeric value, while "%c" is used for displaying the character.


ASCII table example


// Print uppercase letters and their ASCII codes
#include <cstdio>

int main() {
    for(char c = 'A'; c <= 'Z'; c++) {
        printf("%c = %d\n", c, c);
    }
    return 0;
}
Experiment:

Modify the loop to print:
  • lowercase letters ('a' - 'z')
  • digits ('0' - '9')

Special characters


// Apostrophe and escape characters
#include <iostream>
using namespace std;

int main() {
    char a = '\'';   // apostrophe
    char n = '\n';   // new line
    char t = '\t';   // tab

    cout << "Apostrophe: " << a << endl;
    cout << "New line test:" << n << "Next line" << endl;
    cout << "Tab test:" << t << "text" << endl;

    return 0;
}
Tip:

Escape characters like \n (new line) and \t (tab) are very useful when formatting text output.
1 2 3 4 5 6 7 8 9
G r e e t i n g \0

C-style string

C-style strings originate from the C language and are still supported in C++. They are arrays of characters that must end with a null character '\0'.

Key rule:

Every C-style string must end with '\0', otherwise it is not a valid string.

// Manual definition
char text[9] = {'G','r','e','e','t','i','n','g','\0'};

A simpler and safer way:


// Automatic null-termination
char text[] = "Greeting";
Tip:

When using quotes (" "), C++ automatically adds '\0' at the end.

Connection between char and strings


// Accessing characters inside a string
#include <iostream>
using namespace std;

int main() {
    char text[] = "Hello";

    cout << text[0] << endl; // H
    cout << text[1] << endl; // e

    return 0;
}
Important:

A string is just an array of char values. Each character can be accessed using an index.
Try it yourself:

  • Print the last character of the string
  • Change one character manually (e.g. H → J)
  • What happens if you remove '\0'?


Read more about strings in C language on the website:​ C Strings

Text data in C++

In modern C++, text is stored using the std::string type. It is part of the standard library and represents an object (class), not just a simple array.

Key idea:

A std::string is a dynamic structure that automatically manages memory, making it much safer and easier to use than C-style strings.

You can declare a string in two ways:


// Option 1: using namespace std
using namespace std;

string s = "This is some text.";

// Option 2: without using namespace
std::string s = "This is some text.";
Tip:

If you are working on larger projects, it is better to use std::string instead of using namespace std to avoid name conflicts.

Accessing characters


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

int main() {
    string s = "Hello";

    cout << s[0] << endl; // H
    cout << s[4] << endl; // o

    return 0;
}
Important:

Just like arrays, strings use indexing starting from 0.

Inputting strings from standard input

To read text from input, we use cin and cout from the <iostream> library.


Reading words (cin)

The cin command reads input until the first space.


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

int main() {
    string firstName, lastName;

    cin >> firstName >> lastName; // reads two words

    cout << firstName << " " << lastName << endl;

    return 0;
}
Important:

cin stops reading at a space. If you enter: John Doe It will store:
  • firstName = "John"
  • lastName = "Doe"

Reading full lines (getline)

To read a full line (including spaces), we use getline().


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

int main() {
    string fullName;

    getline(cin, fullName); // reads entire line

    cout << fullName << endl;

    return 0;
}
Tip:

Use getline() when working with sentences or text that contains spaces.

Common mistake: cin + getline


int age;
string name;

cin >> age;
getline(cin, name); // problem!

// name will be empty
Why does this happen?

After cin, a newline character (\n) remains in the input buffer. getline() reads that empty line instead of user input.

// Correct solution
int age;
string name;

cin >> age;
cin.ignore(); // remove leftover newline

getline(cin, name);

Experiment:

Try the following:
  • Enter your full name using cin → what happens?
  • Now use getline() → compare results
  • Mix cin and getline() and observe the bug

Entering a complete line of text

To read an entire line of text (including spaces), we use the getline() function.


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

int main() {
    string text;

    getline(cin, text); // reads entire line from input

    cout << text << endl;

    return 0;
}

The first argument of getline() is the input stream (usually cin), and the second argument is the variable where the text will be stored.

Important:

getline() reads everything until the user presses Enter, including spaces.
Tip:

Always use getline() when working with full sentences or user input that may contain spaces.

Splitting words from input text

Sometimes we need to split a sentence into individual words. This can be done using stringstream.


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

int main() {
    string text;
    getline(cin, text); // read full line

    stringstream ss(text); // create stream from string
    string word;
    int count = 0;

    // extract words separated by space
    while (getline(ss, word, ' ')) {
        cout << word << endl;
        count++;
    }

    cout << "The text contains " << count << " words" << endl;

    return 0;
}
How it works:

  • stringstream treats a string like an input stream
  • getline(ss, word, ' ') reads until a space
  • Each iteration extracts one word
Tip:

This approach is very useful in competitive programming and text processing problems.

Alternative: reading directly from input


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

int main() {
    string word;
    int count = 0;

    // reads words one by one from input
    while (getline(cin, word, ' ')) {
        cout << word << endl;
        count++;
    }

    cout << "There are " << count << " words" << endl;

    return 0;
}
Important:

This method reads input continuously until EOF (end of input), so it is more commonly used in advanced scenarios.

Experiment:

Try the following:
  • Change delimiter from space (' ') to comma (',')
  • Input a sentence with multiple spaces — what happens?
  • Try punctuation (e.g. Hello,world,test)

Test your code in the editor below

// Write your C++ code here...

Basic string operations

Assigning one string to another

We can assign the value of one string to another.


#include <string>
using namespace std;

string str1 = "Hello!";
string str2;

str2 = str1; // copy value from str1 to str2

We can also initialize a string directly from another:


string str1 = "Hello!";
string str2 = str1;
Important:

This creates a copy, not a reference. Changing str2 will NOT affect str1.

Concatenating strings

Strings can be joined using the + operator.


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

int main() {
    string first_name = "Nenad";
    string last_name = "Milenkovic";

    string full_name = first_name + " " + last_name;

    cout << full_name << endl;

    return 0;
}
Note:

You must use quotes for spaces: " " Otherwise strings will be glued together.
Experiment:

  • Add middle name
  • Try without space
  • Concatenate 3+ strings

String length

To get the number of characters in a string, use length().


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

int main() {
    string city_name;

    cout << "Enter city name: ";
    getline(cin, city_name);

    int length = city_name.length();

    cout << "City: " << city_name << endl;
    cout << "Length: " << length << endl;

    return 0;
}
Important:

length() counts ALL characters:
  • letters
  • spaces
  • symbols
Common mistake:

❌ length() - 1 is NOT needed (unless you explicitly want to ignore something)

String comparison

Strings can be compared using standard operators:

  • == equal
  • != not equal
  • <, > lexicographical order

bool b;

b = ("abak" == "abak"); // true
b = ("Ab" < "AA");      // false
Important:

String comparison is lexicographical:
  • Compared character by character
  • Based on ASCII values
---

Password example


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

int main() {
    string password;

    cin >> password;

    if (password == "@n0nimus_@n0nimus") {
        cout << "Correct password" << endl;
    } else {
        cout << "Incorrect password" << endl;
    }

    return 0;
}
Security note:

Real applications NEVER store passwords like this. This is just a learning example.
Try this:

  • Change password
  • Test uppercase vs lowercase
  • Use getline() instead of cin

Testing characters using <cctype>

When working with characters in C++, we often need to check their type: whether they are letters, digits, spaces, or special characters.

Instead of writing complex conditions, we can use ready-made functions from the <cctype> header.

Why use <cctype>?

  • Cleaner and more readable code
  • Less chance for errors
  • Standardized and optimized functions

Common functions from <cctype>

  • isalnum(ch) → letter or digit
  • isalpha(ch) → letter
  • isdigit(ch) → digit
  • islower(ch) → lowercase letter
  • isupper(ch) → uppercase letter
  • isspace(ch) → whitespace (space, tab, newline)
  • ispunct(ch) → punctuation
  • iscntrl(ch) → control character
  • tolower(ch) → convert to lowercase
  • toupper(ch) → convert to uppercase
Tip:

All functions return a non-zero value (true) or 0 (false).

Example: Character analysis program

This program reads one character and analyzes its properties.


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

int main() {
    char ch;

    cout << "Enter a character: ";
    cin >> ch;

    // letter or digit
    if (isalnum(ch)) {
        cout << ch << " is a letter or digit.\n";
    }

    // letter
    if (isalpha(ch)) {
        cout << ch << " is a letter.\n";
    }

    // digit
    if (isdigit(ch)) {
        cout << ch << " is a digit.\n";
    }

    // lowercase
    if (islower(ch)) {
        cout << ch << " is lowercase.\n";
        cout << "Uppercase: " << (char)toupper(ch) << '\n';
    }

    // uppercase
    if (isupper(ch)) {
        cout << ch << " is uppercase.\n";
        cout << "Lowercase: " << (char)tolower(ch) << '\n';
    }

    // whitespace
    if (isspace(ch)) {
        cout << "Whitespace character detected.\n";
    }

    // punctuation
    if (ispunct(ch)) {
        cout << ch << " is punctuation.\n";
    }

    // control character
    if (iscntrl(ch)) {
        cout << "Control character detected.\n";
    }

    return 0;
}

How this works

  • Each function checks one property of the character
  • Multiple conditions can be true at the same time
  • Example: 'A' is both isalpha and isupper
Important:

These functions are based on ASCII values, so behavior depends on character encoding.
Try this:

  • Enter a digit (e.g. 5)
  • Enter a symbol (e.g. @)
  • Enter a space or press Enter
  • Try uppercase and lowercase letters

Mini challenge

Write a program that:
  • Counts how many letters are in a string
  • Counts digits
  • Counts spaces
Hint: Use a loop + cctype functions.

Splitting a string using "," as a separator

Task: Split the text into two parts using a comma as a separator.

Input example:
Masarikova 18, Belgrade

Expected output:

Masarikova 18
Belgrade

Step-by-step solution

  • read the entire line (getline)
  • find the position of the comma (find())
  • extract the parts (substr())

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

int main() {

    string inputLine;
    string leftPart, rightPart;

    cout << "Enter a line of text: ";
    getline(cin, inputLine);

    // Find the position of the comma
    size_t sepIndex = inputLine.find(',');

    // Check if the comma exists
    if (sepIndex != string::npos) {

        // Left side (before the comma)
        leftPart = inputLine.substr(0, sepIndex);

        // Right side (after the comma)
        rightPart = inputLine.substr(sepIndex + 1);

        cout << leftPart << endl;
        cout << rightPart << endl;

    } else {
        cout << "Comma not found!" << endl;
    }

    return 0;
}
Tip:

Use find() instead of find_first_of() when searching for a specific character or exact text.
Important:

If the separator does not exist, find() returns string::npos.

Mini challenge

Extend the program to:

  • remove the space after the comma (trim)
  • handle multiple commas (e.g. CSV format)

Functions for searching within a string

To search for a character or substring inside a larger string, we use the find() function.

Example:


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

int main() {
    string str = "This is a simple example string.";

    // First occurrence of "is"
    size_t pos1 = str.find("is");

    // Search starting from index 5
    size_t pos2 = str.find("is", 5);

    // Last occurrence (search from the end)
    size_t pos3 = str.rfind("is");

    cout << pos1 << " " << pos2 << " " << pos3 << endl;

    return 0;
}
Important: If the substring is not found, find() returns string::npos.

The find() function returns the position of the first occurrence of the given substring.

  • find("text") → searches from the beginning
  • find("text", pos) → searches starting from position pos
  • rfind("text") → searches from the end of the string
Tip: Always check if the result is equal to string::npos before using the position.

Substrings

To extract a part of a string, we use the substr() function.

Example 1:


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

int main() {
    string text = "Hello world";
    
    // Extract "world"
    string sub = text.substr(6, 5);

    cout << sub << endl;

    return 0;
}
Explanation:
  • First parameter → starting index (starts from 0)
  • Second parameter → number of characters

Example 2 (without length):


string text = "Hello world";

// From index 6 to the end
string sub = text.substr(6);
Tip: If you omit the second parameter, substr() returns everything until the end of the string.

Edge cases:


string text = "012345";

// Valid
string a = text.substr(2, 3); // "234"

// Starting index out of range → throws exception (modern C++)
// string b = text.substr(10, 2);

// Length too large → returns available characters
string c = text.substr(3, 100); // "345"
Warning: If the starting index is out of range, the program may throw an exception.
Challenge: Find all occurrences of the word "is" in a string and print their positions.

Useful helper functions for working with strings

In practice, we often need additional operations that are not directly part of the std::string interface, such as:

  • splitting a string (split)
  • removing whitespace (trim)
Note:

These functions are not available directly in the standard library as built-in functions, but they can be easily implemented.

Split function (string splitting)

The split function divides a string into multiple parts based on a separator.


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

/*
INPUT:
    inputString = "Ana,Marko,Jovan"
    delimiter = ','

OUTPUT:
    vector containing: ["Ana", "Marko", "Jovan"]
*/

vector<string> split(const string& inputString, char delimiter) {

    vector<string> tokens;   // result container (output)
    size_t startIndex = 0;   // starting position of current token
    size_t delimiterPos;     // position of delimiter in string

    // Loop until no more delimiters are found
    while ((delimiterPos = inputString.find(delimiter, startIndex)) != string::npos) {

        // Extract substring from startIndex to delimiter position
        string token = inputString.substr(startIndex, delimiterPos - startIndex);

        tokens.push_back(token); // store token

        // Move startIndex after the delimiter
        startIndex = delimiterPos + 1;
    }

    // Add the last part (after the final delimiter)
    tokens.push_back(inputString.substr(startIndex));

    return tokens; // return all extracted parts
}

int main() {

    // INPUT STRING (what we want to split)
    string names = "Ana,Marko,Jovan";

    // CALL FUNCTION → OUTPUT is stored in vector
    vector<string> result = split(names, ',');

    // PRINT RESULT
    // Expected output:
    // Ana
    // Marko
    // Jovan
    for (string name : result) {
        cout << name << endl;
    }

    return 0;
}
Tip:

This function does not modify the original string – it returns a new collection of strings (vector).

Trim function (removing whitespace)

The trim function removes whitespace from the beginning and the end of a string.


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

/*
INPUT:
    inputString = "   C++ is awesome!   "

OUTPUT:
    "C++ is awesome!"  (without leading/trailing spaces)
*/

string trim(const string& inputString) {

    size_t startIndex = 0;
    size_t endIndex = inputString.length();

    // Remove leading whitespace
    while (startIndex < endIndex && isspace(inputString[startIndex])) {
        startIndex++;
    }

    // Remove trailing whitespace
    while (endIndex > startIndex && isspace(inputString[endIndex - 1])) {
        endIndex--;
    }

    // Return cleaned substring
    return inputString.substr(startIndex, endIndex - startIndex);
}

int main() {

    // INPUT STRING (contains spaces)
    string text = "   C++ is awesome!   ";

    // CALL FUNCTION → OUTPUT is trimmed string
    string cleanedText = trim(text);

    // PRINT RESULT
    // Expected output: [C++ is awesome!]
    cout << "[" << cleanedText << "]" << endl;

    return 0;
}
Important:

The isspace() function removes all whitespace characters: spaces, tabs, new lines, etc.

Mini challenge

Combine split and trim:
  • split the string by comma
  • remove whitespace from each part
  • print the result neatly
Input example:
" Ana, Marko , Jovan "

Deleting and inserting substrings

To remove or modify parts of a string, we use functions such as erase() and replace().

Example: Deleting part of a string


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

int main() {
    string text = "This is a test";

    // Delete first 7 characters ("This is ")
    text.erase(0, 7);

    cout << text << endl; // Output: "a test"

    return 0;
}
Explanation:
  • First parameter → starting index
  • Second parameter → number of characters to delete

Example: Replacing part of a string


string text = "This is a test";

// Replace "is" with "was"
text.replace(5, 2, "was");

cout << text << endl; // "This was a test"
Tip: Replacement string can be longer or shorter than the original substring.
Try it yourself: Replace the word "test" with "program" in the given string.

Iterating Through a String in C++

Very often we need to process a string character by character. For example, we may want to:

  • count digits in a string,
  • convert letters to uppercase or lowercase,
  • remove spaces,
  • analyze characters in a text.
Key idea: A string is just a sequence of characters, so we can process it like an array.

In C++, there are several ways to iterate through a string:

  • using a classic for loop with an index,
  • using a range-based for loop,
  • using iterators.

1. Iteration using an index

This method gives full control because we know the position of each character.


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

int main() {

    string text = "Programming";

    // Loop through all characters using index
    for (size_t i = 0; i < text.length(); i++) {
        cout << "Index: " << i 
             << ", Character: " << text[i] << endl;
    }

    return 0;
}
Tip: Use size_t instead of int for indexing strings.

This approach is useful when:

  • we need the index (position),
  • we modify characters (text[i] = 'A'),
  • we compare neighboring characters.
---

2. Range-based for loop

This is the simplest and most readable way to iterate through a string.


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

int main() {

    string text = "Programming";

    // Loop through characters directly
    for (char c : text) {
        cout << c << " ";
    }

    return 0;
}

If you want to modify characters, use a reference:


for (char &c : text) {
    c = toupper(c); // convert to uppercase
}
Important: Without &, you only get a copy of the character.
---

3. Using iterators

Iterators are more advanced and are often used with STL algorithms.


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

int main() {

    string text = "Programming";

    for (string::iterator it = text.begin(); it != text.end(); ++it) {
        cout << *it << " ";
    }

    return 0;
}

The iterator behaves like a pointer:

  • it → position
  • *it → character
---

Practical examples

1. Counting digits in a string


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

int main() {

    string text = "a1b2c3";
    int count = 0;

    for (char c : text) {
        if (isdigit(c)) {
            count++;
        }
    }

    cout << "Number of digits: " << count << endl;

    return 0;
}
---

2. Removing spaces from a string


string text = "Hello World Example";
string result = "";

for (char c : text) {
    if (c != ' ') {
        result += c;
    }
}

cout << result; // "HelloWorldExample"
---
Challenge: Write a program that counts how many uppercase and lowercase letters a string contains.
---

In practice:

  • Index-based loops → when position matters
  • Range-based loops → clean and readable
  • Iterators → advanced usage (STL)

Advanced Operations with std::string in C++

The std::string class in C++ allows powerful text manipulation by combining multiple standard functions into more complex operations.

Note: Advanced string processing is less about individual functions and more about combining them effectively (find(), substr(), erase(), etc.).


1. Inserting Substrings

The insert() function allows inserting text at a specific position.


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

int main() {
    string s = "Welcome!";

    s.insert(7, " to C++");

    cout << s << endl;

    return 0;
}

2. Changing Letter Case

Using transform with functions from <cctype>, we can modify all characters in a string.


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

int main() {
    string s = "Welcome to C++";

    transform(s.begin(), s.end(), s.begin(), ::toupper);

    cout << s << endl;

    return 0;
}

3. Combining Multiple Operations

Advanced tasks often require combining several functions together.


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

int main() {
    string s = "   Hello, World!   ";

    // Remove leading spaces
    size_t start = s.find_first_not_of(' ');

    // Remove trailing spaces
    size_t end = s.find_last_not_of(' ');

    // Extract cleaned string
    string trimmed = s.substr(start, end - start + 1);

    cout << trimmed << endl;

    return 0;
}

Tip: Combining find() and substr() is a common pattern for building custom string processing logic.


Mini Challenge:

  • Convert the string to lowercase
  • Remove punctuation marks
  • Count how many words the string contains

By mastering these combinations, you can handle real-world tasks like parsing input, cleaning data, and processing text efficiently.

Final Quiz: Strings in C++

Test your understanding of strings in C++. Try to answer the questions before checking the solutions.

1. What will be the output of the following code?


string s = "Hello";
s += " World";
cout << s;
  • A) Hello
  • B) HelloWorld
  • C) Hello World
  • D) Compilation error
Show Answer

Answer: C) Hello World

The += operator appends text to the existing string.


2. Which function reads an entire line including spaces?

  • A) cin >>
  • B) getline()
  • C) read()
  • D) scan()
Show Answer

Answer: B) getline()

getline() reads input until ENTER is pressed, including spaces.


3. What does find() return if the substring is NOT found?

  • A) -1
  • B) 0
  • C) string::npos
  • D) null
Show Answer

Answer: C) string::npos


4. What will this code print?


string s = "ABCDE";
cout << s.substr(1, 3);
  • A) ABC
  • B) BCD
  • C) BCDE
  • D) CDE
Show Answer

Answer: B) BCD

Starts at index 1 and takes 3 characters.


5. Which loop is the simplest for iterating through characters?

  • A) for(int i = 0; i < s.length(); i++)
  • B) while loop
  • C) range-based for loop
  • D) goto
Show Answer

Answer: C) range-based for loop


Challenge Task:

Write a program that:

  • Reads a full line of text
  • Counts how many vowels (a, e, i, o, u) it contains
  • Prints the result

Hint: Use a loop and tolower().