C++ Fundamentals for Algorithmic Programming

I/O Performance and Formatting

Utilizing <cstdio> over standard streams provides significant throughput advantages in computational environments where input volume is high. The scanf and printf functions bypass stream synchronization overhead. When handling floating-point precision, %.2f truncates output to two decimal places. Note that printf does not support %lf for double; %f suffices. Conversely, scanf requires %lf for double variables, and cannot restrict input precision via format specifiers like %.2lf, which yields undefined behavior or zero.

#include <cstdio>

int main() {
    double value = 0.0;
    // Correct usage for reading doubles
    scanf("%lf", &value);
    // Formatting output to two decimal places
    printf("Formatted: %.2f\n", value);
    return 0;
}

Variable Declaration and Arithmetic Operators

Every identifier must be declared with an explicit type before use. Reusing names within the same scope triggers compilation errors. Arithmetic operations follow standard precedence rules. Integer division truncates fractional parts, whereas floating-point division preserves decimals. Pre-increment (++i) modifies the variable prior to evaluation, while post-increment (i++) evaluates first, then increments. Type casting can be explicit (type)value or implicit through promotion rules.

#include <iostream>

int main() {
    int base_price = 150;
    double tax_rate = 0.18;
    double final_amount = static_cast<double>(base_price) * (1.0 + tax_rate);
    std::cout << final_amount << '\n';
    return 0;
}

Conditional Execution

The if-else construct directs program flow based on Boolean evaluations. Comparison operators include >, <, >=, <=, ==, and !=. Logical operators allow complex condition aggregation: && (AND), || (OR), and ! (NOT). Chaining multiple else if branches handles mutually exclusive ranges efficiently. Nested conditions are valid but should be flattened for readability when possible.

#include <iostream>

void evaluate_score(int mark) {
    if (mark >= 90) {
        std::puts("Distinction");
    } else if (mark >= 75) {
        std::puts("Pass");
    } else {
        std::puts("Fail");
    }
}

int main() {
    evaluate_score(82);
    return 0;
}

Iterative Structures

Looping constructs automate repetitive tasks. A while loop evaluates its condition before each iteration. A do-while loop guarantees at least one execution by checking the condition afterward. The for loop consolidates initialization, termination criteria, and iteration updates into a single header line, keeping the loop body uncluttered. Jump statements alter control flow: break terminates the innermost loop immediately, while continue skips the remainder of the current iteration. Infinite loops occur when the termination condition never evaluates to false; always ensure progress toward exit.

#include <iostream>

int main() {
    int limit = 50;
    int accumulator = 0;
    for (int index = 1; index <= limit; ++index) {
        accumulator += index * index;
    }
    std::cout << accumulator << '\n';
    return 0;
}

Array Management

Static arrays allocate fixed memory blocks. Elements are accessed via zero-based indexing. Uninitialized local arrays contain indeterminate values; explicit initialization or global placement resolves this. Multidimensional arrays store data in row-major order. Traversal requires nested iterations. Bounds checking is manual; accessing arr[size] invokes undefined behavior.

#include <iostream>

int main() {
    const int rows = 3, cols = 4;
    int grid[rows][cols] = {{0}};

    // Populate matrix diagonally
    for (int r = 0; r < rows; ++r) {
        for (int c = 0; c < cols; ++c) {
            grid[r][c] = (r + 1) * (c + 1);
        }
    }

    // Output transposed view
    for (int c = 0; c < cols; ++c) {
        for (int r = 0; r < rows; ++r) {
            std::cout << grid[r][c] << ' ';
        }
        std::cout << '\n';
    }
    return 0;
}

String Processing and Character Encodings

Plain character arrays require manual management of the null terminator \0. The fgets function safely reads lines from streams, stopping at newline or buffer limits, and automatically appends \0. Direct manipulation involves strlen, strcmp, and strcpy from <cstring>. Modern C++ favors std::string, which manages memory dynamically, supports concatenation via +, and provides member functions like empty() and size(). Character-to-integer conversion relies on ASCII mappings: '0' is 48, 'A' is 65, 'a' is 97. Subtraction between characters yields their numeric difference.

#include <string>
#include <iostream>

void shift_characters(const std::string& source) {
    std::string transformed = "";
    for (char ch : source) {
        if (ch >= 'a' && ch <= 'z') {
            transformed += static_cast<char>('a' + (ch - 'a' + 1) % 26);
        } else {
            transformed += ch;
        }
    }
    std::cout << transformed << '\n';
}

int main() {
    shift_characters("abcxyz");
    return 0;
}

Function Abstraction and Recursion

Functions encapsulate reusable logic. Definitions consist of a return type, identifier, parameter list, and body. Pass-by-value creates independent copies; pass-by-reference (&) allows modification of original arguments. Default parameters must trail required ones. Recursive functions call themselves with reduced problem size, requiring a base case to prevent stack overflow. Scope resolution dictates whether a variable refers to a local or global entity.

#include <iostream>

long long compute_factorial(int n) {
    if (n <= 1) return 1;
    return static_cast<long long>(n) * compute_factorial(n - 1);
}

int main() {
    std::cout << compute_factorial(6) << '\n';
    return 0;
}

Object Modeling and Memory Addressing

Classes bundle state (data members) and behavior (member functions) under access specifiers. private members restrict external access, enforcing encapsulation via public getters/setters. struct defaults to public visibility. Pointers store memory addresses and enable dynamic allocation via new/delete or malloc/free. Dereferencing retrieves values. References act as permanent aliases to existing objects, simplifying syntax compared to pointer indirection.

#include <iostream>
#include <string>

class Counter {
private:
    int m_value;
public:
    Counter() : m_value(0) {}
    void increment() { ++m_value; }
    int get() const { return m_value; }
};

int main() {
    Counter tracker;
    tracker.increment();
    std::cout << tracker.get() << '\n';
    return 0;
}

Standard Template Library (STL) Containers

Dynamic sequences rely heavily on STL abstractions. std::vector offers contiguous storage with amortized O(1) append operations. Access uses iterators or square brackets. std::queue implements FIFO semantics; priority_queue provides heap-based sorting with O(log n) insertion/removal. std::stack enforces LIFO constraints. std::deque extends vector capabilities with efficient front-end insertions. Ordered collections std::set and std::map maintain sorted keys via red-black trees, enabling O(log n) lookups. Map subscripts automatically insert missing keys with default-constructed values.

#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> dataset = {9, 3, 7, 1, 5};
    std::sort(dataset.begin(), dataset.end());

    auto it = std::lower_bound(dataset.begin(), dataset.end(), 5);
    if (it != dataset.end()) {
        std::cout << "Found target: " << *it << '\n';
    }
    return 0;
}

Bitwise Manipulation and Utility Algorithms

Low-level operations leverage machine registers directly. Bitwise AND (&), OR (|), XOR (^), NOT (~), and shifts (<<, >>) perform fast mathematical shortcuts. Extracting the k-th bit uses (x >> k) & 1. Isolating the lowest set bit employs x & -x. Standard utilities streamline data preparation: std::reverse swaps element positions, std::unique removes consecutive duplicates and returns an iterator to the new logical end, allowing subsequent resize or range erasure. Sorting accepts custom comparators or operator overloading. Binary search functions std::lower_bound and std::upper_bound locate insertion points in sorted ranges without full traversal.

#include <vector>
#include <algorithm>
#include <iostream>

int main() {
    std::vector<int> nums = {10, 10, 5, 5, 3, 8, 8, 2};
    std::sort(nums.begin(), nums.end());

    auto last = std::unique(nums.begin(), nums.end());
    nums.erase(last, nums.end());

    for (int val : nums) {
        std::cout << val << ' ';
    }
    std::cout << '\n';
    return 0;
}

Tags: c-plus-plus algorithmic-syntax standard-template-library computational-efficiency control-flow

Posted on Sat, 09 May 2026 06:35:20 +0000 by xeelee