Last updated: December 2025

C++ Arrays and Strings: Complete Guide With Examples, std::vector, std::string & DSA (2025)

By CoodeVerse Editorial Team ✓ 2025 Verified ⏱ 20 min read 🎯 Beginner–Intermediate 📦 C++11/17
Difficulty:
Beginner–Intermediate — Prerequisites: Variables & Types, Functions

⚡ Quick Answer: Arrays and Strings in C++

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

📦 Section 1

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.

array_basics.cppC++
#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;
}
Output
Primes: 2 3 5 7 11
arr: 10 20 30 40 50
⚠ Local arrays are NOT zero-initialized. 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.
🧠 Section 2

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

10
[0]
0x1000
20
[1]
0x1004
30
[2]
0x1008
40
[3]
0x100C
50
[4]
0x1010
← arr[5] OOB! ⚠
Value
Index (zero-based)
Address (+4 bytes per int)

Array name = pointer to first element

array-pointer equivalenceC++
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] << " ";
}
Array decay loses size information. When you pass 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.
🚀 Section 3

Modern Alternatives: std::vector & std::array

FeatureRaw arraystd::array<T,N>std::vector<T>
Size at compile timeRequiredRequiredNot 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 useLegacy/C compatFixed-size + STLMost cases
std::vector — dynamic arrayC++
#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;
}
Output
Size: 5
1 2 5 8 9
grid[1][2]: 42
std::array — fixed size, no decay (C++11)C++
#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;
}
Output
1 1 3 4 5 (size=5)
Caught: array::at: __n (which is 10) >= _Nm (which is 5)
⊞ Section 4

2D Arrays and Matrices

2D array — matrix operationsC++
#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;
}
Output
A + B:
10 10 10
10 10 10
10 10 10
2D arrays are stored in row-major order. Iterating row-by-row is cache-friendly and faster than column-by-column — an important optimization in matrix algorithms.
📝 Section 5

Strings in C++: C-Style vs std::string

FeatureC-style (char[])std::string
Declarationchar s[10]="Hi";string s="Hi";
Null terminatorManual \0Internal — automatic
Dynamic resizing✗ No✓ Yes
Concatenationstrcat() — unsafes1 + s2 — safe
Comparisonstrcmp()s1 == s2
Buffer overflow risk✗ High✓ None
Memory managementManualAutomatic
STL algorithm support⚠ Limited✓ Full
When to useC APIs, embeddedModern C++ — everything else
C-style vs std::string — side by sideC++
#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;
}
Output
Hello World
5
0
Hello World
5
1
Hello
⚙️ Section 6

Complete std::string Function Reference

MethodWhat it doesExample
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 xs.replace(0,5,"world")
s.insert(pos, "x")Insert x at positions.insert(0,"!")
s.erase(pos, len)Delete len chars starting at poss.erase(0,3)
s.append("x") / s += "x"Add to ends += "!"
s.compare(t)0 = equal, <0 = s<t, >0 = s>ts.compare("hello")
s.c_str()Convert to const char*printf("%s", s.c_str())
std::stoi(s)String → intstoi("42") → 42
std::stod(s)String → doublestod("3.14") → 3.14
std::to_string(n)int/double → stringto_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"
⌨️ Section 7

String Input/Output: cin vs getline

cin vs getline — the classic pitfallC++
#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;
}
The #1 string input bug: Mixing cin >> and getline without cin.ignore() between them. Fix: always call cin.ignore() after any cin >> before calling getline.
🏆 Section 8

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

binary_search.cppC++
#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;
}
Output
Index of 7: 3
Index of 6: -1
true
lower_bound(9) at index: 4

2. Palindrome Check & String Reversal

palindrome.cppC++
#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;
}
Output
true
false
true
dlroW olleH

3. Prefix Sum & Sliding Window

prefix_sum_sliding_window.cppC++
#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;
}
Output
Sum [2,5]: 19
Max sum k=3: 16

4. Anagram Detection (Frequency Array)

anagram.cppC++
#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;
}
Output
true
false
true

Common Mistakes With Arrays & Strings

MistakeWhat happensFix
arr[n] on n-element arrayOut-of-bounds — undefined behavior, possible crash or silent corruptionUse i < n, not i <= n. Use .at() for bounds check.
Uninitialized local arrayContains garbage valuesint arr[5] = {}; zeroes all elements
Return pointer to local arrayDangling pointer — undefined behaviorReturn std::vector or std::array by value
cin >> for strings with spacesReads only first word, rest stays in bufferUse getline(cin, s)
getline after cin >> without ignoregetline reads leftover newline → empty stringAdd cin.ignore(); between them
Comparing C-strings with ==Compares pointer addresses, not contentUse strcmp(s1, s2) == 0 or convert to std::string
Not checking string::nposTreating npos as valid index → crash or wrong resultif (pos != string::npos) { use pos; }
Modifying string literalchar *s = "hi"; s[0]='H'; — undefined behaviorUse char s[] = "hi"; (array copy, not literal)
Off-by-one in mid=(lo+hi)/2Integer overflow if lo+hi exceeds INT_MAXUse mid = lo + (hi-lo)/2

Frequently Asked Questions

A raw array has fixed size set at compile time, decays to a pointer when passed to functions (losing size), and has no member functions. 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.
When 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.
Use 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.
Use 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.
int to string: 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).

Related C++ Topics on CoodeVerse

Variables & Types Functions Pointers & Memory STL Containers Sorting Algorithms Advanced OOP DSA in C++ 📚 Full C++ Reading Materials

CoodeVerse Editorial Team

Senior engineers and CS educators. All code tested with GCC 13 and Clang 16, updated to C++17 standard.