Skip to main content

Arrays & Strings

Arrays

Complete lesson for Arrays using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with C++ OOP and STL where relevant.

L1

Basics — Arrays

Section: Arrays & Strings. 1D and 2D arrays — why we need them, initialization, memory layout, and real-life examples.

What is an array?

  • An **array** stores **many values of the same type** under one name, in contiguous memory.
  • Each value is reached by an **index** (position). In C++, the first index is **0**.
  • **1D array:** a single row/list — marks of 5 students, temperatures for 7 days.
  • **2D array:** a table/grid — cinema seats (rows × columns), marks of students in subjects.
  • Fixed size at creation for C-style arrays; for growable lists prefer std::vector later.
IdeaMeaningReal-life mapping
NameOne label for many values“Week temperatures”
IndexPosition of one elementDay 0 = Monday
ElementValue at that index32°C on Monday
Size / lengthHow many slots7 days in a week

1D & 2D arrays — layout, uses, and comparison

Arrays store many same-type values in contiguous memory. The diagram below compares 1D (linear list) and 2D (matrix / table) arrays — characteristics, operations, uses, and real-life analogies (books vs seating).

C++ 1D and 2D arrays infographic: linear vs matrix layout, characteristics, operations, uses, comparison table, and real-life analogies of books on a shelf versus seats in rows and columns.
C++ arrays — 1D for linear data (book shelf); 2D for tabular data (classroom seats)
  • 1D: one index a[i] — list of marks, ages, temperatures.
  • 2D: two indices a[r][c] — seats, marks sheets, matrices.
  • Memory: contiguous; 2D stored in row-major order in C++.
  • Indexing: starts at 0; size is fixed at declaration.

Why we need 1D arrays

  • Without arrays you would invent many separate variables: m1, m2, m3, m4, m5 — hard to loop, search, or pass around.
  • A **1D array** gives one name + indices so you can process a **list** with a single loop.
  • Use 1D when data is a **sequence** of the same kind of value (one dimension is enough).
Without 1D arrayWith 1D arrayBenefit
int m0,m1,m2,m3,m4;int marks[5];One name, easy loops
Repeat print 5 timesfor (i=0;i<5;i++)Scales to N students
Hard to find maxScan marks[i]Same code for any size
Pass many argsPass array + sizeCleaner functions
// Painful without array:
int m0 = 80, m1 = 70, m2 = 90, m3 = 60, m4 = 85;
cout << m0 << " " << m1 << " " << m2 << " " << m3 << " " << m4;

// Clean with 1D array:
int marks[5] = {80, 70, 90, 60, 85};
for (int i = 0; i < 5; i++) cout << marks[i] << " ";

Why we need 2D arrays

  • Some data is naturally a **table**: rows and columns together (student × subject, seat row × seat number).
  • With only 1D you would flatten awkwardly (index = row * cols + col) or use many separate 1D arrays.
  • A **2D array** keeps the table shape: data[row][col] matches how people think about grids.
  • Use 2D when each value needs **two coordinates** to make sense.
ProblemAwkward 1D approachNatural 2D approach
3 students × 4 subjects12 separate vars / one long listmarks[3][4]
Cinema 5×10 seats50 flags in one listseats[5][10]
Sales: product × monthHard to read totalssales[p][m]
Chess 8×8Index math everywhereboard[r][c]
// Same data as a flat 1D list (harder to read):
int flat[12] = {80,70,90,60, 75,85,80,70, 90,88,92,85};
int student = 1, subject = 2;
cout << flat[student * 4 + subject]; // manual formula

// Clear 2D table:
int marks[3][4] = {
    {80, 70, 90, 60},
    {75, 85, 80, 70},
    {90, 88, 92, 85}
};
cout << marks[1][2]; // student 1, subject 2

Array initialization

  • **Initialization** means giving array elements values at (or right after) creation.
  • Uninitialized local C arrays hold **garbage** until you assign values — always initialize or fill before reading.
  • Common styles: full list, partial list (rest zeroed), all zeros, and (for 2D) row-by-row braces.
StyleExampleResult
Full initint a[5] = {1,2,3,4,5};All five set
Partial initint a[5] = {1,2};1,2,0,0,0 (rest 0)
All zerosint a[5] = {};0,0,0,0,0
Size from listint a[] = {1,2,3};Size becomes 3
Later assigna[0]=10; a[1]=20;Fill in a loop / input
2D rowsint m[2][3]={{1,2,3},{4,5,6}};Two rows filled
2D partial rowint m[2][3]={{1},{4,5}};Missing cells → 0
#include <iostream>
using namespace std;

int main() {
    // 1D initialization forms
    int marks[5] = {80, 70, 90, 60, 85}; // full
    int scores[5] = {50, 60};            // rest become 0
    int zeros[5] = {};                   // all 0
    int autoSize[] = {10, 20, 30};       // size = 3

    // Fill from input / loop
    int temp[3];
    for (int i = 0; i < 3; i++) temp[i] = 30 + i;

    // 2D initialization
    int seats[2][3] = {
        {1, 0, 1},
        {0, 1, 1}
    };
    int grid[2][3] = {{1}, {4, 5}}; // others 0

    cout << marks[0] << " " << scores[2] << " " << seats[1][2] << "\n";
    return 0;
}

1D arrays

  • Syntax: type name[size]; — example: int marks[5];
  • Valid indices: 0 to size - 1. Access: marks[0], marks[4].
  • Traverse with a for loop from 0 to n - 1.
Indexmarks[i]Real-life meaning
080Student A score
170Student B score
290Student C score
360Student D score
485Student E score
#include <iostream>
using namespace std;

int main() {
    int marks[5] = {80, 70, 90, 60, 85};
    for (int i = 0; i < 5; i++) {
        cout << "Student " << (i + 1) << ": " << marks[i] << "\n";
    }
    return 0;
}

Real-life examples of 1D arrays

  • **Student marks list:** one mark per student in a class test.
  • **Daily temperatures:** 7 values for Mon–Sun weather log.
  • **Bus stop times:** arrival minutes for stops on a route.
  • **Playlist durations:** length of each song in seconds.
  • **Monthly expenses:** spending for months 1–12.
  • **Sensor readings:** last 10 humidity samples from a device.
// 7-day temperature log (°C)
int temp[7] = {32, 31, 33, 30, 29, 34, 32};
int sum = 0;
for (int d = 0; d < 7; d++) sum += temp[d];
cout << "Weekly average = " << (sum / 7.0) << "\n";

2D arrays

  • A **2D array** is an array of arrays — think of a **table** with rows and columns.
  • Syntax: type name[rows][cols]; — example: int seats[3][4];
  • Access: name[row][col] — both indices start at 0.
  • Nested loops: outer = rows, inner = columns (same idea as nested loops lesson).
PartMeaningReal-life mapping
seats[r][c]One cell in the gridSeat in row r, column c
Row index rWhich horizontal lineCinema row A/B/C → 0/1/2
Column index cWhich seat in that rowSeat number 1–4 → 0–3
Nested forVisit every cellCheck all seats for booking
#include <iostream>
using namespace std;

int main() {
    int seats[3][4] = {
        {1, 1, 0, 1}, // 1 = free, 0 = booked
        {1, 0, 0, 1},
        {1, 1, 1, 0}
    };
    for (int r = 0; r < 3; r++) {
        for (int c = 0; c < 4; c++)
            cout << (seats[r][c] ? "F " : "B ");
        cout << "\n";
    }
    return 0;
}

Real-life examples of 2D arrays

  • **Cinema / stadium seating:** rows × seats — free or booked.
  • **Class marks sheet:** students (rows) × subjects (columns).
  • **Chess / ludo board:** 8×8 or N×N cells with piece codes.
  • **Spreadsheet / fee table:** products × months of sales.
  • **Hotel rooms:** floors × room numbers on each floor.
  • **Image (tiny grayscale):** height × width pixels (each cell = brightness).
  • **Timetable:** days × periods with subject codes.
// 3 students × 4 subjects marks
int marks[3][4] = {
    {80, 70, 90, 60},
    {75, 85, 80, 70},
    {90, 88, 92, 85}
};
for (int s = 0; s < 3; s++) {
    int total = 0;
    for (int sub = 0; sub < 4; sub++) total += marks[s][sub];
    cout << "Student " << (s + 1) << " total = " << total << "\n";
}

Differences between 1D and 2D arrays

  • Pick 1D for a list; pick 2D when data naturally forms a table or grid.
Point1D array2D array
ShapeSingle list / rowTable / grid
IndicesOne: a[i]Two: a[r][c]
Typical loopOne forNested for
Real-lifeMarks list, week tempsSeats, marks sheet, board
Declarationint a[5];int a[3][4];
Why neededAvoid m1,m2,m3… for a listKeep table shape clear

Memory allocation to 1D arrays

  • A local/global C array gets a **contiguous block** of memory: all elements sit one after another.
  • If each int is 4 bytes, int a[5] needs about **5 × 4 = 20 bytes**.
  • Address of a[i] ≈ base address of a + i × sizeof(element).
  • That is why index 0 is the start, and why arrays are fast for sequential access.
  • **Real-life analogy:** 5 lockers in a straight corridor — locker number = index.
ElementOffset from startExample address (base 1000)Bytes (int=4)
a[0]0 × 410004
a[1]1 × 410044
a[2]2 × 410084
a[3]3 × 410124
a[4]4 × 410164
#include <iostream>
using namespace std;

int main() {
    int a[5] = {10, 20, 30, 40, 50};
    cout << "sizeof(a) = " << sizeof(a) << " bytes\n";
    cout << "elements = " << sizeof(a) / sizeof(a[0]) << "\n";
    for (int i = 0; i < 5; i++) {
        cout << "&a[" << i << "] = " << &a[i]
             << " value = " << a[i] << "\n";
    }
    return 0;
}

Memory allocation to 2D arrays

  • A 2D array int m[R][C] is also one contiguous block (usually **row-major**): row 0’s columns, then row 1’s columns, …
  • Total elements = R × C. Bytes ≈ R × C × sizeof(int). Example: int m[3][4] → 12 ints → ~48 bytes.
  • Address of m[r][c] ≈ base + (r × C + c) × sizeof(element).
  • So 2D is “logical table,” but memory is still a **straight line** of cells.
  • **Real-life analogy:** classroom desks arranged in rows — row 1 seats, then row 2 seats, in one long seating order in memory.
CellRow-major orderFormula r*C+c (C=4)Meaning
m[0][0]1st0Start of row 0
m[0][3]4th3End of row 0
m[1][0]5th4Start of row 1
m[2][3]12th11Last cell (3×4)
#include <iostream>
using namespace std;

int main() {
    int m[2][3] = {{1, 2, 3}, {4, 5, 6}};
    cout << "sizeof(m) = " << sizeof(m) << " bytes\n";
    cout << "rows*cols = " << 2 * 3 << " elements\n";
    for (int r = 0; r < 2; r++) {
        for (int c = 0; c < 3; c++) {
            cout << "&m[" << r << "][" << c << "]=" << &m[r][c]
                 << " val=" << m[r][c] << "\n";
        }
    }
    // Flat view: same memory as one 1D sequence 1 2 3 4 5 6
    return 0;
}

std::array (modern fixed array)

  • std::array knows its size via .size() and does not decay as easily as C arrays when passed carefully.
  • Still fixed length — for dynamic size use std::vector.
  • Works with range-based for: for (int x : arr).
#include <array>
#include <iostream>
using namespace std;

int main() {
    array<int, 5> marks = {80, 70, 90, 60, 85};
    cout << "Count = " << marks.size() << "\n";
    for (int m : marks) cout << m << " ";
    return 0;
}
L2

Advanced — Arrays

Memory allocation deep dive

  • Stack arrays (typical locals): size usually known at compile time; freed when the function returns.
  • sizeof(arrayName) on a true array object gives total bytes; after decay to a pointer, sizeof gives pointer size — a common interview trap.
  • 2D T a[R][C] is contiguous; “array of pointers” (T* rows[R] each new T[C]) is a **different** layout (rows may not be adjacent).
  • Dynamic 1D: int* p = new int[n]; … delete[] p; — size can come from runtime n.
  • Going outside bounds still does not “allocate more” — it is undefined behaviour.
KindHow memory is obtainedFreed how
Local int a[5]Stack (automatic)End of block/function
std::arrayUsually stack objectDestructor / end of scope
new int[n]Heap (dynamic)delete[]
int m[3][4]One contiguous blockAutomatic if local
#include <iostream>
using namespace std;

int main() {
    int a[5] = {1, 2, 3, 4, 5};
    cout << sizeof(a) << "\n";          // 20 if int is 4 bytes
    int* p = a;
    cout << sizeof(p) << "\n";          // pointer size (e.g. 8), not 20

    int n = 4;
    int* heap = new int[n]{10, 20, 30, 40}; // dynamic 1D
    cout << heap[2] << "\n";
    delete[] heap;
    return 0;
}

Memory, indexing, and bounds

  • Elements of a 1D array sit in contiguous memory; a[i] is roughly *(a + i).
  • A 2D array a[R][C] is stored row-major: row 0’s columns, then row 1’s columns, and so on.
  • Going outside 0 .. size-1 is **undefined behaviour** — no automatic bounds check on C arrays.
  • Prefer std::array / std::vector and .at(i) when you want bounds-checked access.
  • When passing a C array to a function it **decays to a pointer** — pass the size separately.
void print1D(const int a[], int n) {
    for (int i = 0; i < n; i++) cout << a[i] << " ";
}

// For 2D, columns size must be known in the parameter type:
void print2D(int a[][4], int rows) {
    for (int r = 0; r < rows; r++) {
        for (int c = 0; c < 4; c++) cout << a[r][c] << " ";
        cout << "\n";
    }
}

Common 1D operations

  • Sum / average, find max/min, search a value, reverse, count even/odd.
  • **Real-life:** highest temperature in a week; total monthly expense; find a roll number in a list.
int a[5] = {80, 70, 90, 60, 85};
int maxv = a[0];
for (int i = 1; i < 5; i++)
    if (a[i] > maxv) maxv = a[i];
cout << "Highest marks = " << maxv << "\n";

Common 2D operations

  • Row sum (per student total), column sum (per subject total), transpose, diagonal of a square matrix.
  • **Real-life:** total sales per product (row), total sales per month (column).
  • Count free seats in a cinema grid; find first booked seat with nested loops + flag.
int sales[2][3] = {{10, 20, 15}, {5, 8, 12}};
// Column totals = sales per month
for (int m = 0; m < 3; m++) {
    int col = 0;
    for (int p = 0; p < 2; p++) col += sales[p][m];
    cout << "Month " << (m + 1) << " total = " << col << "\n";
}

Real-life models (combined)

  • 1D: elevators store floor request flags; traffic lights store timer phases.
  • 1D: OTP digits or PIN digits as char pin[4] / int digits[6].
  • 2D: parking lot floors × slots; warehouse racks × bins.
  • 2D: game map tiles; LED matrix display; seating chart with VIP rows.
  • Rule: if you say “list of …”, think 1D; if you say “table of …”, think 2D.
L3

Tricky Interview Points

Q1) What is an array in C++?

Answer A fixed-size collection of elements of the same type stored in contiguous memory and accessed by index (starting at 0).

Q2) What is the difference between a 1D and a 2D array?

Answer A 1D array is a single list accessed as a[i]. A 2D array is a table/grid accessed as a[row][col], usually traversed with nested loops.

Q3) Give a real-life example of a 1D array.

Answer Student marks in one test, daily temperatures for a week, or monthly expenses for 12 months.

Q4) Give a real-life example of a 2D array.

Answer Cinema seats (rows × columns), student-subject marks sheet, hotel floors × rooms, or a chessboard.

Q5) Why do we need 1D arrays?

Answer To store and process a list of same-type values with one name and a loop, instead of many separate variables like m1, m2, m3.

Q6) Why do we need 2D arrays?

Answer When data is naturally a table or grid needing two coordinates (row and column), such as seats or student×subject marks — clearer than flattening into one long 1D list.

Q7) What is array initialization? Give examples.

Answer Giving elements values when created. Examples: int a[5]={1,2,3,4,5}; partial int a[5]={1,2}; (rest 0); int a[5]={}; (all 0); 2D int m[2][3]={{1,2,3},{4,5,6}};

Q8) What happens if a local array is not initialized?

Answer Elements hold indeterminate (garbage) values until assigned. Reading them before writing is undefined behaviour in practice — always initialize or fill first.

Q9) How is memory allocated for a 1D array?

Answer As one contiguous block. Address of a[i] ≈ base + i × sizeof(element). Example: int a[5] needs about 5 × sizeof(int) bytes.

Q10) How is memory allocated for a 2D array?

Answer Usually one contiguous row-major block: row0 columns, then row1, and so on. Address of m[r][c] ≈ base + (r × cols + c) × sizeof(element). Total elements = rows × cols.

Q11) What are valid indices for int a[5]?

Answer 0, 1, 2, 3, and 4. Accessing a[5] or negative indices is out of bounds (undefined behaviour).

Q12) Why do arrays use 0-based indexing?

Answer Histor historically equals base address + index × element size; index 0 means “no offset from the start.”

Q13) What happens when a C-style array is passed to a function?

Answer It decays to a pointer to the first element. The function does not automatically know the array length — pass the size separately.

Q14) How is a 2D array stored in memory?

Answer Typically in row-major order: all columns of row 0, then row 1, and so on.

Q15) std::array vs C-style array?

Answer std::array is a fixed-size container with .size(), better type safety, and STL compatibility. C arrays are lower-level and decay to pointers more easily.

Q16) When should you prefer std::vector over arrays?

Answer When the number of elements can grow or shrink at runtime, or when you want dynamic sizing and rich STL operations.

Q17) How do you traverse a 2D array?

Answer Use nested loops: outer loop over rows, inner loop over columns (or vice versa if column-major traversal is required).

Q18) What is an out-of-bounds access?

Answer Reading or writing an index outside the valid range. In C++ this is undefined behaviour and can crash or corrupt data.

L4

Simple Programs

1D — print and sum marks

#include <iostream>
using namespace std;

int main() {
    int marks[5] = {80, 70, 90, 60, 85};
    int sum = 0;
    for (int i = 0; i < 5; i++) {
        cout << marks[i] << " ";
        sum += marks[i];
    }
    cout << "\nSum = " << sum << "\n";
    return 0;
}

1D — weekly temperature average

#include <iostream>
using namespace std;

int main() {
    int temp[7] = {32, 31, 33, 30, 29, 34, 32};
    int sum = 0, maxv = temp[0];
    for (int i = 0; i < 7; i++) {
        sum += temp[i];
        if (temp[i] > maxv) maxv = temp[i];
    }
    cout << "Avg = " << (sum / 7.0) << "\n";
    cout << "Hottest = " << maxv << "\n";
    return 0;
}

1D — search roll number

#include <iostream>
using namespace std;

int main() {
    int rolls[6] = {101, 104, 108, 110, 115, 120};
    int key = 110, found = -1;
    for (int i = 0; i < 6; i++) {
        if (rolls[i] == key) { found = i; break; }
    }
    if (found >= 0) cout << "Found at index " << found << "\n";
    else cout << "Not found\n";
    return 0;
}

2D — cinema free/booked seats

#include <iostream>
using namespace std;

int main() {
    int seats[3][4] = {
        {1, 1, 0, 1},
        {1, 0, 0, 1},
        {1, 1, 1, 0}
    };
    int freeCount = 0;
    for (int r = 0; r < 3; r++) {
        for (int c = 0; c < 4; c++) {
            cout << (seats[r][c] ? "F " : "B ");
            if (seats[r][c]) freeCount++;
        }
        cout << "\n";
    }
    cout << "Free seats = " << freeCount << "\n";
    return 0;
}

2D — student × subject totals

#include <iostream>
using namespace std;

int main() {
    int marks[3][4] = {
        {80, 70, 90, 60},
        {75, 85, 80, 70},
        {90, 88, 92, 85}
    };
    for (int s = 0; s < 3; s++) {
        int total = 0;
        for (int sub = 0; sub < 4; sub++) total += marks[s][sub];
        cout << "Student " << (s + 1) << " total = " << total
             << " avg = " << (total / 4.0) << "\n";
    }
    return 0;
}

2D — matrix row and column sums

#include <iostream>
using namespace std;

int main() {
    int a[2][3] = {{1, 2, 3}, {4, 5, 6}};
    for (int r = 0; r < 2; r++) {
        int rs = 0;
        for (int c = 0; c < 3; c++) rs += a[r][c];
        cout << "Row " << r << " sum = " << rs << "\n";
    }
    for (int c = 0; c < 3; c++) {
        int cs = 0;
        for (int r = 0; r < 2; r++) cs += a[r][c];
        cout << "Col " << c << " sum = " << cs << "\n";
    }
    return 0;
}

std::array — playlist durations

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

int main() {
    array<int, 4> sec = {210, 185, 240, 195};
    int total = 0;
    for (int t : sec) total += t;
    cout << "Playlist length = " << total << " seconds\n";
    return 0;
}

Initialization styles demo

#include <iostream>
using namespace std;

int main() {
    int full[4] = {1, 2, 3, 4};
    int partial[4] = {1, 2}; // -> 1 2 0 0
    int zeros[4] = {};
    int m[2][3] = {{10, 20}, {30}}; // rest 0
    for (int i = 0; i < 4; i++) cout << partial[i] << " ";
    cout << "\n";
    for (int r = 0; r < 2; r++) {
        for (int c = 0; c < 3; c++) cout << m[r][c] << " ";
        cout << "\n";
    }
    return 0;
}

Memory layout — print addresses (1D & 2D)

#include <iostream>
using namespace std;

int main() {
    int a[4] = {11, 22, 33, 44};
    cout << "1D contiguous addresses:\n";
    for (int i = 0; i < 4; i++)
        cout << "&a[" << i << "] = " << &a[i] << "\n";

    int m[2][3] = {{1, 2, 3}, {4, 5, 6}};
    cout << "2D row-major addresses:\n";
    for (int r = 0; r < 2; r++)
        for (int c = 0; c < 3; c++)
            cout << "&m[" << r << "][" << c << "] = " << &m[r][c] << "\n";

    cout << "sizeof(a)=" << sizeof(a)
         << " sizeof(m)=" << sizeof(m) << "\n";
    return 0;
}
L5

Problem Solving Tricks

  • Remember: first index is 0; last index is size − 1.
  • Need a list? → 1D. Need a table/grid? → 2D.
  • Initialize: full {…}, partial (rest 0), {} for all zeros, or fill in a loop.
  • Uninitialized local arrays hold garbage — do not read before writing.
  • 1D memory: contiguous; address ≈ base + i × sizeof(T).
  • 2D memory: row-major contiguous; address ≈ base + (r × cols + c) × sizeof(T).
  • Use sizeof(a)/sizeof(a[0]) for element count on a real array object (not a decayed pointer).
  • Always loop with i < n, not i <= n, for 0-based arrays of length n.
  • For 2D print, put cout << "\n" after the inner loop (end of each row).
  • Name indices meaningfully: day, student, row, col — not only i and j.
  • Never read/write outside bounds — that is undefined behaviour.
  • Pass size with C arrays: void f(int a[], int n);
  • Prefer std::array for fixed size with .size(); prefer vector when size changes.
  • Draw a small 3×4 grid on paper before coding 2D logic.
L6

Practice Programs List

  1. Create a 1D array of 10 integers, read them, and print in reverse.
  2. Show why 1D is needed: rewrite five separate mark variables into marks[5] and find the average.
  3. Show why 2D is needed: store 3×4 marks as marks[3][4] and compare with a flat marks[12] index formula.
  4. Practice initialization: create partial, zero, full, and size-from-list 1D arrays and print them.
  5. Initialize a 2D array with partial rows and print which cells became 0.
  6. Print addresses of all elements of int a[5] and verify they increase by sizeof(int).
  7. Print addresses of int m[2][3] in row-major order and confirm &m[1][0] follows &m[0][2].
  8. Compute and print sizeof for 1D and 2D arrays; explain the byte totals.
  9. 1D: store 7 daily step counts and print the day with maximum steps.
  10. 2D: build a 4×5 cinema seat map; book seat (2,3); reprint the map.
  11. 2D: 5 students × 3 subjects — print each student average and class topper.
  12. Write a function that takes a 1D array and size and returns the maximum.
  13. Transpose a 2×3 matrix into a 3×2 matrix using nested loops.
  14. Use std::array for a fixed PIN of 4 digits and verify a user input.