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
Strings are used everywhere:
- user input (names, messages)
- file processing
- search algorithms
- data parsing (e.g. CSV, logs)
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
Think about this:
- How is a word like
hellostored in memory? - Is it one variable or multiple characters?
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.
A string is not a single value — it is a sequence of characters stored in memory.
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.
How is the word
hello stored in memory?
- Is it one variable?
- Or multiple characters?
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.
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;
}
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;
}
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'.
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";
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;
}
A string is just an array of
char values.
Each character can be accessed using an index.
- Print the last character of the string
- Change one character manually (e.g. H → J)
- What happens if you remove
'\0'?
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.
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.";
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;
}
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;
}
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;
}
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
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);
Try the following:
- Enter your full name using
cin→ what happens? - Now use
getline()→ compare results - Mix
cinandgetline()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.
getline() reads everything until the user presses Enter,
including spaces.
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;
}
stringstreamtreats a string like an input streamgetline(ss, word, ' ')reads until a space- Each iteration extracts one word
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;
}
This method reads input continuously until EOF (end of input), so it is more commonly used in advanced scenarios.
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
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;
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;
}
You must use quotes for spaces:
" "
Otherwise strings will be glued together.
- 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;
}
length() counts ALL characters:
- letters
- spaces
- symbols
❌
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
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;
}
Real applications NEVER store passwords like this. This is just a learning example.
- Change password
- Test uppercase vs lowercase
- Use
getline()instead ofcin
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.
- Cleaner and more readable code
- Less chance for errors
- Standardized and optimized functions
Common functions from <cctype>
isalnum(ch)→ letter or digitisalpha(ch)→ letterisdigit(ch)→ digitislower(ch)→ lowercase letterisupper(ch)→ uppercase letterisspace(ch)→ whitespace (space, tab, newline)ispunct(ch)→ punctuationiscntrl(ch)→ control charactertolower(ch)→ convert to lowercasetoupper(ch)→ convert to uppercase
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
isalphaandisupper
These functions are based on ASCII values, so behavior depends on character encoding.
- 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
cctype functions.
Splitting a string using "," as a separator
Task: Split the text into two parts using a comma as a separator.
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;
}
Use find() instead of find_first_of() when searching for a specific character or exact text.
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;
}
find() returns string::npos.
The find() function returns the position of the first occurrence of the given substring.
find("text")→ searches from the beginningfind("text", pos)→ searches starting from positionposrfind("text")→ searches from the end of the string
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;
}
- 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);
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"
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)
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;
}
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;
}
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
" 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;
}
- 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"
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.
In C++, there are several ways to iterate through a string:
- using a classic
forloop with an index, - using a range-based
forloop, - 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;
}
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
}
&, 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"
---
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().
|
Previous
|< Two-dimensional dynamic arrays in c++ |
Next
Pointers in C++ >| |