C++ Arrays and Strings: Complete Guide With Examples, std::vector, std::string & DSA (2025)
⚡ Quick Answer: Arrays and Strings in C++
- Raw array —
int arr[5]: fixed size, zero-indexed, decays to pointer - std::vector — dynamic, resizable, full STL support (preferred for most cases)
- std::array — fixed-size with STL support, no pointer decay (C++11)
- C-style string —
char[]null-terminated, functions from<cstring> - std::string — dynamic, safe, rich member functions (preferred)
- Key functions:
.length(),.substr(),.find(),.sort(),getline()
Arrays and strings are the two most fundamental data structures in C++. Every algorithm you'll
write — from sorting to pattern matching — uses them. This guide covers everything: raw arrays,
std::vector, std::array, C-style strings vs std::string,
all key functions with examples, memory layout diagrams, and six complete DSA implementations.
Raw Arrays
Declaration, init, access
Memory Layout
How arrays live in RAM
vector & array
Modern C++ containers
2D Arrays
Matrices & grids
Strings
C-style vs std::string
String Functions
All key methods
Input / Output
cin, getline, cout
DSA Examples
6 real algorithms
Raw Arrays — Declaration, Initialization, and Access
A raw C++ array is a fixed-size contiguous block of elements of the same type. The size must be known at compile time. Elements are accessed with zero-based indices.
#include <iostream>
using namespace std;
int main() {
// 1. Declare, then assign
int arr[5];
arr[0]=10; arr[1]=20; arr[2]=30; arr[3]=40; arr[4]=50;
// 2. Initialize at declaration
int primes[5] = {2, 3, 5, 7, 11};
// 3. Omit size — deduced from initializer
double temps[] = {98.6, 99.1, 100.2};
// 4. C++11 uniform initialization
char grades[3]{'A', 'B', 'C'};
// 5. Partial init — rest zeroed
int partial[5] = {1, 2}; // {1, 2, 0, 0, 0}
// 6. Zero-initialize entire array
int zeroes[5] = {}; // all 0
// Range-based for (C++11)
cout << "Primes: ";
for (int p : primes) cout << p << " ";
cout << endl;
// Classic for loop
cout << "arr: ";
for (int i = 0; i < 5; i++) cout << arr[i] << " ";
cout << endl;
return 0;
}
Primes: 2 3 5 7 11
arr: 10 20 30 40 50 int arr[5]; without an initializer contains garbage values on the stack. Always initialize: int arr[5] = {}; (zeroes all) or assign every element before reading.
Memory Layout & the Array-Pointer Relationship
Arrays are stored in contiguous memory — every element immediately follows the previous one in RAM. This is why random access (arr[i]) is O(1): the address of element i is exactly &arr[0] + i × sizeof(type).
int arr[5] = {10, 20, 30, 40, 50} — memory layout
Array name = pointer to first element
int arr[5] = {10,20,30,40,50};
// arr decays to &arr[0]
cout << arr << endl; // address of first element
cout << &arr[0] << endl; // same address
// arr[i] == *(arr + i)
cout << arr[2] << endl; // 30
cout << *(arr + 2) << endl; // 30 — pointer arithmetic
// Passing array to function — decays to pointer, size lost!
void process(int* arr, int n) { // must pass size separately
for (int i = 0; i < n; i++) cout << arr[i] << " ";
}
int arr[] to a function, it becomes int* — the function cannot call sizeof(arr) to get the length. Always pass the size as a separate parameter, or use std::array or std::vector which carry their size.
Modern Alternatives: std::vector & std::array
| Feature | Raw array | std::array<T,N> | std::vector<T> |
|---|---|---|---|
| Size at compile time | Required | Required | Not required |
| Can grow at runtime | ✗ No | ✗ No | ✓ Yes |
| Decays to pointer | ✗ Yes | ✓ No | ✓ No |
| Has .size() | ✗ No | ✓ Yes | ✓ Yes |
| STL algorithms | ⚠ Manual | ✓ Full | ✓ Full |
| Bounds check (.at()) | ✗ No | ✓ Yes | ✓ Yes |
| Stack memory | ✓ Yes | ✓ Yes | ✗ Heap |
| When to use | Legacy/C compat | Fixed-size + STL | Most cases |
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> v = {5, 2, 8, 1, 9};
v.push_back(3);
v.pop_back();
v.insert(v.begin()+2, 99);
v.erase(v.begin()+2);
cout << "Size: " << v.size() << endl;
sort(v.begin(), v.end());
for (int x : v) cout << x << " ";
cout << endl;
int rows=3, cols=4;
vector<vector<int>> grid(rows, vector<int>(cols, 0));
grid[1][2] = 42;
cout << "grid[1][2]: " << grid[1][2] << endl;
return 0;
}
Size: 5
1 2 5 8 9
grid[1][2]: 42#include <iostream>
#include <array>
#include <algorithm>
using namespace std;
void printArray(const array<int,5>& a) {
for (int x : a) cout << x << " ";
cout << "(size=" << a.size() << ")" << endl;
}
int main() {
array<int, 5> a = {3, 1, 4, 1, 5};
sort(a.begin(), a.end());
printArray(a);
try {
cout << a.at(10);
} catch(const exception& e) {
cout << "Caught: " << e.what() << endl;
}
return 0;
}
1 1 3 4 5 (size=5)
Caught: array::at: __n (which is 10) >= _Nm (which is 5)2D Arrays and Matrices
#include <iostream>
using namespace std;
int main() {
int A[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
int B[3][3] = {{9,8,7},{6,5,4},{3,2,1}};
int C[3][3] = {};
for (int i=0; i<3; i++)
for (int j=0; j<3; j++)
C[i][j] = A[i][j] + B[i][j];
cout << "A + B:\n";
for (int i=0; i<3; i++) {
for (int j=0; j<3; j++) cout << C[i][j] << " ";
cout << endl;
}
return 0;
}
A + B:
10 10 10
10 10 10
10 10 10 Strings in C++: C-Style vs std::string
| Feature | C-style (char[]) | std::string |
|---|---|---|
| Declaration | char s[10]="Hi"; | string s="Hi"; |
| Null terminator | Manual \0 | Internal — automatic |
| Dynamic resizing | ✗ No | ✓ Yes |
| Concatenation | strcat() — unsafe | s1 + s2 — safe |
| Comparison | strcmp() | s1 == s2 |
| Buffer overflow risk | ✗ High | ✓ None |
| Memory management | Manual | Automatic |
| STL algorithm support | ⚠ Limited | ✓ Full |
| When to use | C APIs, embedded | Modern C++ — everything else |
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main() {
char cs1[] = "Hello";
char cs2[20];
strcpy(cs2, cs1);
strcat(cs2, " World");
cout << cs2 << endl;
cout << strlen(cs1) << endl;
cout << strcmp(cs1, "Hello") << endl;
string s1 = "Hello";
string s2 = s1 + " World";
cout << s2 << endl;
cout << s1.length() << endl;
cout << (s1 == "Hello") << endl;
const char* to_cs = s1.c_str();
cout << to_cs << endl;
return 0;
}
Hello World
5
0
Hello World
5
1
HelloComplete std::string Function Reference
| Method | What it does | Example |
|---|---|---|
| s.length() / s.size() | Number of characters | "hello".length() → 5 |
| s.empty() | True if zero characters | "".empty() → true |
| s[i] | Access char (no bounds check) | s[0] → 'h' |
| s.at(i) | Access char (throws on OOB) | s.at(0) → 'h' |
| s.front() / s.back() | First / last character | "hi".back() → 'i' |
| s.substr(pos, len) | Extract substring | "hello".substr(1,3) → "ell" |
| s.find("x") | First position of x (npos if absent) | "hello".find("ll") → 2 |
| s.rfind("x") | Last position of x | "abcabc".rfind("c") → 5 |
| s.replace(pos,len,"x") | Replace len chars at pos with x | s.replace(0,5,"world") |
| s.insert(pos, "x") | Insert x at position | s.insert(0,"!") |
| s.erase(pos, len) | Delete len chars starting at pos | s.erase(0,3) |
| s.append("x") / s += "x" | Add to end | s += "!" |
| s.compare(t) | 0 = equal, <0 = s<t, >0 = s>t | s.compare("hello") |
| s.c_str() | Convert to const char* | printf("%s", s.c_str()) |
| std::stoi(s) | String → int | stoi("42") → 42 |
| std::stod(s) | String → double | stod("3.14") → 3.14 |
| std::to_string(n) | int/double → string | to_string(42) → "42" |
| std::sort(s.begin(),s.end()) | Sort characters in place | "bca" → "abc" |
| std::reverse(s.begin(),s.end()) | Reverse in place | "abc" → "cba" |
String Input/Output: cin vs getline
#include <iostream>
#include <string>
using namespace std;
int main() {
string word, full_name;
int age;
cout << "Enter a word: ";
cin >> word;
cout << "Word: " << word << endl;
cin.ignore(); // discard leftover \n
cout << "Enter full name: ";
getline(cin, full_name);
cout << "Full name: " << full_name << endl;
cout << "Enter age: ";
cin >> age;
cin.ignore();
cout << "Enter message: ";
string msg;
getline(cin, msg);
cout << "Age: " << age << ", Message: " << msg << endl;
return 0;
}
cin >> and getline without cin.ignore() between them. Fix: always call cin.ignore() after any cin >> before calling getline.
DSA Applications: 6 Complete Algorithms
📊 Binary Search O(log n)
Search sorted array with STL and manual implementation
🔄 String Reversal & Palindrome O(n)
Two-pointer technique on strings
📈 Prefix Sum Array O(1) query
Range sum queries in constant time
🪟 Sliding Window Max O(n)
Maximum subarray sum of size k
🔍 Anagram Detection O(n)
Frequency array approach
📐 2D Matrix Rotation O(n²)
90-degree in-place matrix rotation
1. Binary Search — STL and manual
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int binarySearch(const vector<int>& v, int target) {
int lo = 0, hi = v.size() - 1;
while (lo <= hi) {
int mid = lo + (hi - lo) / 2;
if (v[mid] == target) return mid;
if (v[mid] < target) lo = mid + 1;
else hi = mid - 1;
}
return -1;
}
int main() {
vector<int> v = {1,3,5,7,9,11,15};
cout << "Index of 7: " << binarySearch(v, 7) << endl;
cout << "Index of 6: " << binarySearch(v, 6) << endl;
cout << boolalpha << binary_search(v.begin(), v.end(), 9) << endl;
auto it = lower_bound(v.begin(), v.end(), 9);
cout << "lower_bound(9) at index: " << it - v.begin() << endl;
return 0;
}
Index of 7: 3
Index of 6: -1
true
lower_bound(9) at index: 42. Palindrome Check & String Reversal
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
using namespace std;
bool isPalindrome(const string& s) {
int l = 0, r = (int)s.length() - 1;
while (l < r) {
if (s[l] != s[r]) return false;
l++; r--;
}
return true;
}
bool isPalindromeClean(const string& s) {
int l = 0, r = (int)s.length() - 1;
while (l < r) {
while (l < r && !isalnum(s[l])) l++;
while (l < r && !isalnum(s[r])) r--;
if (tolower(s[l]) != tolower(s[r])) return false;
l++; r--;
}
return true;
}
int main() {
cout << boolalpha;
cout << isPalindrome("racecar") << endl;
cout << isPalindrome("hello") << endl;
cout << isPalindromeClean("A man, a plan, a canal: Panama") << endl;
string s = "Hello World";
reverse(s.begin(), s.end());
cout << s << endl;
return 0;
}
true
false
true
dlroW olleH3. Prefix Sum & Sliding Window
#include <iostream>
#include <vector>
using namespace std;
int rangeSum(const vector<int>& pre, int l, int r) {
return pre[r] - (l > 0 ? pre[l-1] : 0);
}
int maxSumK(const vector<int>& arr, int k) {
int n = arr.size(), window = 0, maxSum = 0;
for (int i=0; i<k; i++) window += arr[i];
maxSum = window;
for (int i=k; i<n; i++) {
window += arr[i] - arr[i-k];
maxSum = max(maxSum, window);
}
return maxSum;
}
int main() {
vector<int> arr = {3,1,4,1,5,9,2,6};
int n = arr.size();
vector<int> pre(n);
pre[0] = arr[0];
for (int i=1; i<n; i++) pre[i] = pre[i-1] + arr[i];
cout << "Sum [2,5]: " << rangeSum(pre, 2, 5) << endl;
cout << "Max sum k=3: " << maxSumK(arr, 3) << endl;
return 0;
}
Sum [2,5]: 19
Max sum k=3: 164. Anagram Detection (Frequency Array)
#include <iostream>
#include <string>
using namespace std;
bool isAnagram(const string& s, const string& t) {
if (s.length() != t.length()) return false;
int freq[26] = {};
for (char c : s) freq[c - 'a']++;
for (char c : t) freq[c - 'a']--;
for (int f : freq) if (f != 0) return false;
return true;
}
int main() {
cout << boolalpha;
cout << isAnagram("listen", "silent") << endl;
cout << isAnagram("hello", "world") << endl;
cout << isAnagram("rat", "car") << endl;
return 0;
}
true
false
trueCommon Mistakes With Arrays & Strings
| Mistake | What happens | Fix |
|---|---|---|
| arr[n] on n-element array | Out-of-bounds — undefined behavior, possible crash or silent corruption | Use i < n, not i <= n. Use .at() for bounds check. |
| Uninitialized local array | Contains garbage values | int arr[5] = {}; zeroes all elements |
| Return pointer to local array | Dangling pointer — undefined behavior | Return std::vector or std::array by value |
| cin >> for strings with spaces | Reads only first word, rest stays in buffer | Use getline(cin, s) |
| getline after cin >> without ignore | getline reads leftover newline → empty string | Add cin.ignore(); between them |
| Comparing C-strings with == | Compares pointer addresses, not content | Use strcmp(s1, s2) == 0 or convert to std::string |
| Not checking string::npos | Treating npos as valid index → crash or wrong result | if (pos != string::npos) { use pos; } |
| Modifying string literal | char *s = "hi"; s[0]='H'; — undefined behavior | Use char s[] = "hi"; (array copy, not literal) |
| Off-by-one in mid=(lo+hi)/2 | Integer overflow if lo+hi exceeds INT_MAX | Use mid = lo + (hi-lo)/2 |
Frequently Asked Questions
std::vector is dynamic — it can grow with .push_back(), always knows its own size via .size(), and supports all STL algorithms natively. In modern C++, use std::vector for almost everything and raw arrays only for legacy C API compatibility.cin >> reads input, it stops at the newline but leaves \n in the buffer. The next getline immediately reads that newline and returns an empty string. Fix: add cin.ignore(); between them to discard the leftover newline.s.find("substring"). It returns the starting position if found, or string::npos if not. Always compare: if (s.find("world") != string::npos) { /* found */ }. For C++23, s.contains("world") returns a bool directly.std::sort from <algorithm>. For a vector: sort(v.begin(), v.end()) (ascending). For descending: sort(v.begin(), v.end(), greater<int>()). For raw array: sort(arr, arr+n). std::sort is O(n log n) guaranteed in C++11+.string::npos is the value returned by find() when the target is not found. Its value is (size_t)-1. Always check: if (pos != string::npos) { /* use pos */ } before treating it as an index.std::to_string(42) returns "42". String to int: std::stoi("42") returns 42. Also: stol, stoll, stof, stod. Prefer these C++11 tools over atoi (no error detection).Master C++ from arrays to advanced algorithms
Structured lessons, 200+ exercises, and a completion certificate. Join 50,000+ students on CoodeVerse.