Arrays and Strings in C++
Hey! Welcome back. Today, we’re talking about how to handle collections of data in C++ using Arrays and Strings.
Imagine you’re building a game and need to store the top 5 high scores. Creating 5 separate variables (score1, score2, etc.) is incredibly tedious. Instead, you can store them all in a single variable called an Array. Similarly, if you want to store text (like player names or message logs), you’ll use Strings.
Let’s dive in and see how they work!
Arrays in C++
An array is a collection of elements of the same data type stored in contiguous (back-to-back) memory locations. You can access individual elements in the array using a zero-based index.
Properties of Arrays
- Fixed Size: Once you declare an array’s size, you cannot change it.
- Homogeneous: Every element in the array must be of the exact same data type (e.g., all integers, or all floats).
- Contiguous Memory: Array elements are placed right next to each other in RAM, which makes accessing them incredibly fast.
- Zero-Based Indexing: The first element is at index
0, the second is at index1, and the $N$-th element is at index $N-1$.
Declaring and Initializing Arrays
Syntax:
data_type array_name[size];
For example, to create an array that holds 5 integers:
int arr[5];
Array Initialization at Time of Declaration
You can initialize an array with values right when you declare it by placing them inside curly braces {}:
Example:
int arr[5] = {1, 2, 3, 4, 5};
Visualizing the Memory Layout:
graph LR
subgraph Array Memory Layout: arr[5]
direction LR
idx0[Index: 0 <br/> Value: 1 <br/> Address: 0x100]
idx1[Index: 1 <br/> Value: 2 <br/> Address: 0x104]
idx2[Index: 2 <br/> Value: 3 <br/> Address: 0x108]
idx3[Index: 3 <br/> Value: 4 <br/> Address: 0x10C]
idx4[Index: 4 <br/> Value: 5 <br/> Address: 0x110]
idx0 --- idx1
idx1 --- idx2
idx2 --- idx3
idx3 --- idx4
end
[!NOTE] Notice how the memory addresses offset by exactly 4 bytes (since an
inton most modern systems takes up 4 bytes of RAM). Because they are stored back-to-back, C++ can calculate the address of any index instantly!
Array Initialization After Declaration
You can declare an array first and assign values to its indices later:
Example:
#include <iostream>
int main() {
int arr[5]; // Declared with junk/garbage values inside
// Assigning values individually
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
arr[4] = 50;
std::cout << "Element at index 2: " << arr[2] << std::endl;
return 0;
}
Output:
Element at index 2: 30
[!TIP] If you partially initialize an array during declaration (e.g.,
int arr[5] = {1, 2};), C++ will automatically fill all the remaining uninitialized slots with0.
Partial Initialization Example:
#include <iostream>
int main() {
int arr[5] = {1, 2}; // Only slot 0 and 1 are explicitly set
std::cout << "arr[0]: " << arr[0] << std::endl;
std::cout << "arr[2]: " << arr[2] << " (automatically zeroed!)" << std::endl;
return 0;
}
Output:
arr[0]: 1
arr[2]: 0 (automatically zeroed!)
Accessing Array Elements
You access elements by placing their index inside square brackets [] after the array’s name.
Syntax:
array_name[index];
Example:
#include <iostream>
int main() {
int scores[3] = {95, 88, 72};
// Reading values
std::cout << "First score: " << scores[0] << std::endl;
// Modifying values
scores[1] = 90;
std::cout << "Updated second score: " << scores[1] << std::endl;
return 0;
}
Output:
First score: 95
Updated second score: 90
Multidimensional Arrays
You can think of multidimensional arrays as “arrays of arrays”. The most common type is the 2D array, which represents a grid or matrix with rows and columns.
Syntax:
data_type array_name[rows][columns];
Let’s look at a 2D array representing a $2 \times 3$ grid:
Example:
#include <iostream>
int main() {
// 2 rows, 3 columns
int matrix[2][3] = {
{1, 2, 3}, // Row 0
{4, 5, 6} // Row 1
};
// Accessing row 1, col 2 (value: 6)
std::cout << "Value at matrix[1][2]: " << matrix[1][2] << std::endl;
return 0;
}
Output:
Value at matrix[1][2]: 6
[!NOTE] You can have 3D, 4D, or even higher-dimensional arrays simply by chaining brackets (e.g.,
int hyperCube[2][3][4][5];), though they get hard to wrap your brain around!
Passing an Array to a Function
When you pass an array to a function, C++ does not copy the entire array (which would be slow and waste memory). Instead, it passes the base address (a pointer to the first element).
Because we pass the base address, any changes made to the array elements inside the function will affect the original array outside!
Example:
#include <iostream>
// We specify empty brackets [] in the parameter to indicate an array
void printArray(int arr[], int size) {
for (int i = 0; i < size; ++i) {
std::cout << arr[i] << " ";
}
std::cout << std::endl;
}
int main() {
int myArray[5] = {10, 20, 30, 40, 50};
// Pass only the name of the array (which acts as the base address pointer)
printArray(myArray, 5);
return 0;
}
Output:
10 20 30 40 50
Strings in C++
A string is a sequence of characters. In C++, there are two main ways to create strings: C-Style strings (inherited from C) and C++-Style strings (modern standard library).
1. C-Style Strings
A C-style string is just a one-dimensional array of characters (char) that is terminated by a special null character \0. The null character tells the compiler where the string ends.
Memory Representation of char s[14] = "striverA2Z";
flowchart LR
subgraph C-Style String: char s[14] = 'striverA2Z'
direction LR
c0[C] --- c1[i]
c1 --- c2[p]
c2 --- c3[h]
c3 --- c4[e]
c4 --- c5[r]
c5 --- c6[S]
c6 --- c7[c]
c7 --- c8[h]
c8 --- c9[o]
c9 --- c10[o]
c10 --- c11[l]
c11 --- c12[s]
c12 --- c13[\0]
style c13 fill:#ffcccc,stroke:#ff0000,stroke-width:2px
end
[!WARNING] Since a C-style string needs a null terminator, the size of your character array must be at least one character larger than the text itself. For example,
"Hello"has 5 characters, but needs an array of size 6 to store it!
Example:
#include <iostream>
#include <cstring> // Header containing C-style string functions
int main() {
// Declared by explicitly sizing it to make room for \0
char str1[14] = "striverA2Z";
// Or let the compiler deduce the size automatically (includes \0)
char str2[] = "striverA2Z";
std::cout << "str1: " << str1 << std::endl;
std::cout << "str2: " << str2 << std::endl;
return 0;
}
Output:
str1: striverA2Z
str2: striverA2Z
Common Functions for C-Style Strings (include <cstring>):
strcpy(s1, s2):Copies strings2intos1.strcat(s1, s2):Concatenates (glues) strings2onto the end ofs1.strlen(s1):Returns the length of strings1(not counting\0).strcmp(s1, s2):Compares strings lexicographically (returns0if they match).
Example:
#include <iostream>
#include <cstring>
int main() {
char s1[20] = "Hello ";
char s2[] = "World!";
std::strcat(s1, s2); // Appends s2 to s1
std::cout << "Concatenated: " << s1 << std::endl;
std::cout << "Length of string: " << std::strlen(s1) << std::endl;
return 0;
}
Output:
Concatenated: Hello World!
Length of string: 12
2. C++-Style Strings
Modern C++ provides a much safer and easier-to-use alternative: the std::string class. It manages its own memory dynamically, meaning you don’t have to worry about array sizes or null terminators.
To use it, simply #include <string>.
Example:
#include <iostream>
#include <string>
int main() {
std::string str = "Hello C++!";
std::cout << str << std::endl;
return 0;
}
Output:
Hello C++!
Common Methods for C++ Strings:
length()/size(): Returns the number of characters.empty(): Returnstrueif the string is empty.append(s)/+: Appends stringsor merges two strings.find(sub): Searches for a substring and returns its index.substr(pos, len): Returns a substring starting at indexposof lengthlen.clear(): Wipes out all characters.
Example:
#include <iostream>
#include <string>
int main() {
std::string text = "striverA2Z";
std::cout << "Length: " << text.length() << std::endl;
std::cout << "Substring: " << text.substr(0, 6) << std::endl; // Gets first 6 chars
// Find index of "Schools"
size_t pos = text.find("Schools");
std::cout << "'Schools' starts at index: " << pos << std::endl;
return 0;
}
Output:
Length: 13
Substring: striverA2Z
'Schools' starts at index: 6
Input Methods for Strings
Reading strings from users can be a bit tricky because some functions stop reading as soon as they hit whitespace (a space, tab, or newline).
C-Style String Inputs
scanf("%s", str): Stops reading at the first space. It also does not check buffer limits, posing a buffer overflow hazard!fgets(str, size, stdin): Read a whole line, including spaces, safely within the specified size buffer limit.
Example (using fgets):
#include <iostream>
int main() {
char name[30];
std::cout << "Enter your full name: ";
// Reads up to 29 characters and adds \0
std::fgets(name, 30, stdin);
std::cout << "Name read: " << name << std::endl;
return 0;
}
Output:
Enter your full name: Johnny C++
Name read: Johnny C++
C++-Style String Inputs
cin >> str: Reads a single word, stopping at whitespace.getline(cin, str): Reads a whole line, including spaces.
Example (using getline):
#include <iostream>
#include <string>
int main() {
std::string fullName;
std::cout << "Enter your full name: ";
std::getline(std::cin, fullName); // Safely reads spaces
std::cout << "Welcome, " << fullName << "!" << std::endl;
return 0;
}
Output:
Enter your full name: Johnny C++
Welcome, Johnny C++!
Level Up: Extra Practice & Interview Questions
Q1. What is the purpose of the null character \0 in C-style strings, and how does it affect their declaration?
The null character \0 marks the boundary/end of a C-style string in memory. Functions like printf or strlen read characters sequentially and stop only when they detect \0. Thus, C-style string arrays must always be declared with a size at least one element larger than the string’s text character count.
Q2. Write a program to remove the substring “Schools” from “striverA2Z”.
We can use the C++ string find() and erase() functions to dynamically slice the string.
Code:
#include <iostream>
#include <string>
int main() {
std::string text = "striverA2Z";
std::string sub = "Schools";
size_t pos = text.find(sub);
if (pos != std::string::npos) {
text.erase(pos, sub.length()); // Erases from match pos
}
std::cout << "Result: " << text << std::endl;
return 0;
}
Output:
Result: striverA2Z
Q3. Write C++ code to store even numbers from 2 to 20 in an array, and print them.
We’ll allocate an array of size 10, fill it inside a loop, and print elements sequentially.
Code:
#include <iostream>
int main() {
int evens[10];
// Fill array
for (int i = 0; i < 10; ++i) {
evens[i] = (i + 1) * 2;
}
// Print array
std::cout << "Even numbers: ";
for (int i = 0; i < 10; ++i) {
std::cout << evens[i] << " ";
}
std::cout << std::endl;
return 0;
}
Output:
Even numbers: 2 4 6 8 10 12 14 16 18 20
quiz Test Your Understanding
What character marks the end of a C-style character string?
C-style strings are character arrays terminated by a null character \0 to mark the end of the string.