Basic Examples

Example 1: Hello World and Basic I/O

#include <iostream> // Includes the standard input/output stream library

int main() {
    // Output text to the console using cout
    std::cout << "Hello, World!" << std::endl;

    // Declare a variable to store user input
    std::string name;

    // Prompt the user for input
    std::cout << "Enter your name: ";

    // Read input from the user and store in 'name'
    std::cin >> name;

    // Greet the user with their name
    std::cout << "Welcome, " << name << "!" << std::endl;

    return 0; // Indicates successful execution
}

Example 2: Variables, Arithmetic, and Constants

#include <iostream>

int main() {
    // Declare integer variables
    int a = 5;
    int b = 3;

    // Perform arithmetic operations
    int sum = a + b;
    int diff = a - b;
    int product = a * b;
    int quotient = a / b;
    std::string s = "hello"; 

    // Declare a constant
    const float pi = 3.14159f;

    // Output the results
    std::cout << "Sum: " << sum << std::endl;
    std::cout << "Difference: " << diff << std::endl;
    std::cout << "Product: " << product << std::endl;
    std::cout << "Quotient: " << quotient << std::endl;
    std::cout << "Constant pi: " << pi << std::endl;

    return 0;
}
Hint

string requires std usage

Useful string functions

length()
substr(1,2)
erase()
find('text')

Example 3: Conditionals and User Input

#include <iostream>

int main() {
    int age;

    // Ask the user for their age
    std::cout << "Enter your age: ";
    std::cin >> age;

    // Use conditional statements to evaluate input
    if (age >= 18) {
        std::cout << "You are an adult." << std::endl;
    } else if (age >= 13) {
        std::cout << "You are a teenager." << std::endl;
    } else {
        std::cout << "You are a child." << std::endl;
    }

    return 0;
}

Example 4: Loops

#include <iostream>

int main() {
    int n;

    // Ask user for how many numbers to sum
    std::cout << "Enter a number: ";
    std::cin >> n;

    int sum = 0;

    // Loop from 1 to n and accumulate the sum
    for (int i = 1; i <= n; i++) {
        sum += i; // Equivalent to sum = sum + i
    }

    std::cout << "The sum of numbers from 1 to " << n << " is " << sum << std::endl;

    return 0;
}

Example 5: Functions and Pointers

#include <iostream>

// Function that adds two integers and returns the result
int add(int x, int y) {
    return x + y;
}

// Function that modifies a value using a pointer
void doubleValue(int* ptr) {
    *ptr = *ptr * 2; // Dereference and double the value
}

int main() {
    // Demonstrate function call
    int result = add(10, 5);
    std::cout << "Sum from function: " << result << std::endl;

    // Demonstrate pointer manipulation
    int num = 7;
    std::cout << "Before doubling: " << num << std::endl;

#include <iostream>
    // Pass address of 'num' to the function
    doubleValue(&num);

    std::cout << "After doubling: " << num << std::endl;

    return 0;
}

Intermediate Examples

Example 1: Using std::vector and Iteration

#include <iostream>
#include <vector>

int main() {
    // Create a dynamic array (vector) to hold integers
    std::vector<int> numbers;

    // Populate the vector with user input
    int input;
    std::cout << "Enter 5 numbers:" << std::endl;

    for (int i = 0; i < 5; ++i) {
        std::cin >> input;
        numbers.push_back(input); // Append to the vector
    }

    // Calculate the average of the elements
    int sum = 0;
    for (int num : numbers) {
        sum += num;
    }

    float average = static_cast<float>(sum) / numbers.size();

    std::cout << "Average: " << average << std::endl;

    return 0;
}

useful vector functions:

at()         -  Return an indexed element from a vector
back()       -  Return iterator pointing to end of vector
begin()      -  Return iterator pointing to start of vector
pop_back()   -  Remove last item in vector
size()       -  Return number of elements within a vector

Example 2: Structs and Data Aggregation

#include <iostream>
#include <string>

// Define a struct to represent a person
struct Person {
    std::string name;
    int age;
};

int main() {
    // Declare and initialize a struct instance
    Person student;
    
    std::cout << "Enter your name: ";
    std::getline(std::cin, student.name); // Read full line (including spaces)

    std::cout << "Enter your age: ";
    std::cin >> student.age;

    // Display the struct's content
    std::cout << "Student Info - Name: " << student.name << ", Age: " << student.age << std::endl;

    return 0;
}

Example 3: File I/O (Reading and Writing Text Files)

#include <iostream>
#include <fstream>
#include <string>

int main() {
    std::string filename = "example.txt";

    // Write to a file
    std::ofstream outfile(filename); // Open for output
    if (outfile.is_open()) {
        outfile << "This is a test.\n";
        outfile << "Written by C++.\n";
        outfile.close(); // Close after writing
    } else {
        std::cerr << "Failed to open file for writing." << std::endl;
    }

    // Read from the file
    std::ifstream infile(filename); // Open for input
    if (infile.is_open()) {
        std::string line;
        while (std::getline(infile, line)) {
            std::cout << line << std::endl;
        }
        infile.close(); // Close after reading
    } else {
        std::cerr << "Failed to open file for reading." << std::endl;
    }

    return 0;
}

Example 4: Dynamic Memory and Array Allocation

#include <iostream>

int main() {
    int size;

    std::cout << "Enter the size of the array: ";
    std::cin >> size;

    // Dynamically allocate an array of integers
    int* arr = new int[size];

    // Fill the array
    for (int i = 0; i < size; ++i) {
        arr[i] = (i + 1) * 10;
    }

    // Display contents
    std::cout << "Array contents: ";
    for (int i = 0; i < size; ++i) {
        std::cout << arr[i] << " ";
    }
    std::cout << std::endl;

    // Free the allocated memory
    delete[] arr;

    return 0;
}
Hint

Any time you use the new keyword, you should use delete to free the allocated memory>


Example 5: Function Decomposition and Header Inclusion

math_utils.h (header file):

#ifndef MATH_UTILS_H
#define MATH_UTILS_H

int add(int a, int b);
int multiply(int a, int b);

#endif

math_utils.cpp (implementation):

#include "math_utils.h"

int add(int a, int b) {
    return a + b;
}

int multiply(int a, int b) {
    return a * b;
}

main.cpp (main file):

#include <iostream>
#include "math_utils.h"

int main() {
    int x = 4, y = 5;

    std::cout << "Addition: " << add(x, y) << std::endl;
    std::cout << "Multiplication: " << multiply(x, y) << std::endl;

    return 0;
}

Compile all three files together:

g++ main.cpp math_utils.cpp -o program

Advanced Examples

Example 1: Generic Functions with Templates

#include <iostream>

// Define a function template that works with any type
template <typename T>
T maxValue(T a, T b) {
    return (a > b) ? a : b;
}

int main() {
    std::cout << "Max (int): " << maxValue(10, 20) << std::endl;
    std::cout << "Max (double): " << maxValue(5.5, 2.3) << std::endl;
    std::cout << "Max (char): " << maxValue('a', 'z') << std::endl;

    return 0;
}

Concepts demonstrated:

  • Function templates
  • Type-generic logic
  • Reusability and type safety

Example 2: RAII – Automatic Resource Management

#include <iostream>
#include <fstream>

// A wrapper class that opens a file and closes it automatically
class FileLogger {
private:
    std::ofstream file;

public:
    FileLogger(const std::string& filename) {
        file.open(filename);
        if (!file) {
            throw std::runtime_error("Unable to open file");
        }
    }

    void log(const std::string& message) {
        file << message << std::endl;
    }

    ~FileLogger() {
        if (file.is_open()) {
            file.close(); // Automatically closes the file
        }
    }
};

int main() {
    try {
        FileLogger logger("log.txt");
        logger.log("This is a log message.");
        logger.log("Resource management done right.");
    } catch (const std::exception& e) {
        std::cerr << "Error: " << e.what() << std::endl;
    }

    return 0;
}

Concepts demonstrated:

  • RAII (Resource Acquisition Is Initialization)
  • Constructors/destructors
  • Exception handling
  • File management with automatic cleanup

Example 3: Lambdas and Functors

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

// A custom functor (function object)
struct IsEven {
    bool operator()(int x) const {
        return x % 2 == 0;
    }
};

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5, 6};

    // Use lambda to print all numbers
    std::cout << "All numbers: ";
    std::for_each(numbers.begin(), numbers.end(), [](int x) {
        std::cout << x << " ";
    });
    std::cout << std::endl;

    // Count how many even numbers using the functor
    int evens = std::count_if(numbers.begin(), numbers.end(), IsEven());

    std::cout << "Even numbers count: " << evens << std::endl;

    return 0;
}

Concepts demonstrated:

  • Lambda expressions
  • Function objects (functors)
  • Use of standard algorithms (for_eachcount_if)
  • Functional programming style

Example 4: Smart Pointers and Shared Ownership

#include <iostream>
#include <memory>

class Resource {
public:
    Resource() {
        std::cout << "Resource acquired" << std::endl;
    }
    ~Resource() {
        std::cout << "Resource destroyed" << std::endl;
    }
    void greet() {
        std::cout << "Hello from resource!" << std::endl;
    }
};

int main() {
    std::shared_ptr<Resource> ptr1 = std::make_shared<Resource>();
    {
        std::shared_ptr<Resource> ptr2 = ptr1; // Shared ownership
        ptr2->greet();
        std::cout << "Reference count: " << ptr1.use_count() << std::endl;
    }

    std::cout << "Back to main scope. Reference count: " << ptr1.use_count() << std::endl;

    return 0;
}

Concepts demonstrated:

  • std::shared_ptr
  • Reference counting
  • Object lifetime control
  • Avoiding manual delete

Example 5: Multithreading with std::thread

#include <iostream>
#include <thread>

// A function that will run in a separate thread
void task(int id) {
    std::cout << "Thread " << id << " is running" << std::endl;
}

int main() {
    std::thread t1(task, 1);
    std::thread t2(task, 2);

    // Wait for both threads to complete
    t1.join();
    t2.join();

    std::cout << "Main thread finished" << std::endl;

    return 0;
}

Concepts demonstrated:

  • Thread creation
  • Function passing to threads
  • Synchronization with join()
  • Parallel execution

Example 6: std::variant and std::visit for Type-Safe Unions

#include <iostream>
#include <variant>

// Define a variant that can hold multiple types
using Data = std::variant<int, float, std::string>;

void printData(const Data& d) {
    std::visit([](auto&& value) {
        std::cout << "Value: " << value << std::endl;
    }, d);
}

int main() {
    Data d1 = 42;
    Data d2 = std::string("C++ Advanced");
    Data d3 = 3.14f;

    printData(d1);
    printData(d2);
    printData(d3);

    return 0;
}

Concepts demonstrated:

  • Type-safe unions (std::variant)
  • Pattern matching via std::visit
  • Generic lambdas

Example 7: Custom Exception Class

#include <iostream>
#include <stdexcept>

// Define a custom exception class
class InvalidOperation : public std::runtime_error {
public:
    explicit InvalidOperation(const std::string& message)
        : std::runtime_error(message) {}
};

int divide(int a, int b) {
    if (b == 0) {
        throw InvalidOperation("Division by zero is not allowed.");
    }
    return a / b;
}

int main() {
    try {
        std::cout << divide(10, 2) << std::endl;
        std::cout << divide(5, 0) << std::endl; // Will throw
    } catch (const InvalidOperation& e) {
        std::cerr << "Caught custom exception: " << e.what() << std::endl;
    }

    return 0;
}

Concepts demonstrated:

  • Inheritance from std::runtime_error
  • Custom error classes
  • Robust exception handling

Example 8: Operator Overloading

#include <iostream>

class Vector2D {
public:
    float x, y;

    Vector2D(float x, float y) : x(x), y(y) {}

    // Overload the + operator
    Vector2D operator+(const Vector2D& other) const {
        return Vector2D(x + other.x, y + other.y);
    }

    // Output formatting
    void print() const {
        std::cout << "(" << x << ", " << y << ")" << std::endl;
    }
};

int main() {
    Vector2D a(2.0f, 3.0f);
    Vector2D b(1.5f, 4.5f);

    Vector2D result = a + b;
    result.print();

    return 0;
}

Concepts demonstrated:

  • Operator overloading (operator+)
  • Code expressiveness through custom operators
  • Object modeling

Example 9: Associative Containers (std::map)

#include <iostream>
#include <map>
#include <string>

int main() {
    std::map<std::string, int> scoreBoard;

    // Insert values
    scoreBoard["Alice"] = 100;
    scoreBoard["Bob"] = 80;
    scoreBoard["Charlie"] = 95;

    // Iterate and print
    for (const auto& entry : scoreBoard) {
        std::cout << entry.first << " : " << entry.second << std::endl;
    }

    // Lookup
    std::string name = "Alice";
    if (scoreBoard.find(name) != scoreBoard.end()) {
        std::cout << name << "'s score: " << scoreBoard[name] << std::endl;
    }

    return 0;
}

Concepts demonstrated:

  • Key-value associative containers
  • Fast lookups
  • Iteration using range-based for

Example 10: Pattern Matching with std::regex

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string input;
    std::regex pattern(R"(\w+@\w+\.\w+)"); // Simple email regex

    std::cout << "Enter an email address: ";
    std::getline(std::cin, input);

    if (std::regex_match(input, pattern)) {
        std::cout << "Valid email format." << std::endl;
    } else {
        std::cout << "Invalid email format." << std::endl;
    }

    return 0;
}

Concepts demonstrated:

  • Regular expressions with std::regex
  • Pattern validation
  • Input sanitization (relevant for parsing/filters)