HackIndia Logo
HackathonsNewsSkillsGrowth
HackIndia LogoContact: +91 9910125804

General

  • Companies
  • Colleges
  • Board of Advisors
  • Brand Ambassadors
  • FAQ
  • Contact
  • Report a Bug

Hackathons

  • Upcoming Hackathons
  • Judges
  • Mentors
  • Partners
  • Participating Colleges
  • Testimonials

Resources

  • About Us
  • Branding
  • Latest News
  • Growth
  • Skills
  • Builders
  • Ecosystem
  • Forum
  • Ideas
  • Prompt Optimizer
  • Games

© 2026 HackIndia. All rights reserved.

Privacy PolicyTerms of ServiceCode of ConductSitemap

Build 2.139 · 05 Nov 2026, 10:27 UTC

    HackIndia
    HackathonsNewsInternshipsSkillsGrowthPro Perks
    ← Build safer C++ projects

    All the reading

    C++

    8 lessons, about 38 minutes. The check's questions come from these.

    Contents
    Safer control flow and pointers
    1. 1. Write C++ that does not break
    2. 2. Use references and pointers safely
    STL and text input
    1. 3. Solve faster with STL
    2. 4. Handle strings and parsing
    Resource handling and project delivery
    1. 5. Design classes with RAII
    2. 6. Understand move semantics plainly
    3. 7. Compile, debug, and test locally
    4. 8. Ship your C++ repo

    Safer control flow and pointers

    1. Write C++ that does not break

    5 min

    In 30 seconds
    • Spot the C++ habits that cause random crashes and wrong answers.
    • Write input, indexing, and integer code that fails less often.
    • Start a small safety checklist you will use in every C++ repo.

    Why this matters

    In C++, your code can compile and still be unsafe. It may pass your sample test, then crash on a judge, a friend’s laptop, or during a demo.

    This lesson is about avoiding the common break points first: bad input handling, out-of-range access, uninitialised values, and integer surprises.

    Key point

    One rule

    Do not trust memory, input, or indexes by default. Check sizes, initialise values, and make invalid states hard to reach.

    Safe C++ is not fancy C++. It is boring code that behaves the same way every time you run it.

    Your to-do

    Write safer basics

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 6 done

    Common mistake

    Silent wrong code

    A common beginner mistake is assuming the input is always perfect. In a project repo, your sample data may be clean, but users can type empty input, text instead of numbers, or a negative value.

    2. Use references and pointers safely

    5 min

    In 30 seconds
    • Choose references for required objects and pointers for optional objects.
    • Avoid dangling addresses from locals, temporaries, and vector reallocation.
    • Use nullptr checks and pass-by-reference to write safer project code.
    Key point

    One rule

    A reference means: this object must exist. A pointer means: this object may be missing, shared by address, or changed to point elsewhere.

    Use the stricter option first. If a function does not need null, take a reference, not a pointer.

    Why it matters

    Many C++ bugs in student projects are not syntax bugs. They are lifetime bugs. You keep an address after the real object is gone, then the program behaves strangely.

    Your repo should show that you know when data lives, who owns it, and whether a function can receive nothing.

    Your to-do

    Choose the parameter

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    STL and text input

    3. Solve faster with STL

    4 min

    In 30 seconds
    • Pick the right STL container for common project tasks.
    • Use algorithms like sort, find, count_if, and lower_bound safely.
    • Replace long manual loops with clearer STL code.
    Key point

    Main idea

    STL gives you tested containers and algorithms. Your job is to choose the right one and keep the code readable.

    In a hackathon project, STL saves time and reduces bugs. You should not write your own dynamic array, sorting function, or map unless the problem asks for it.

    What STL means

    STL is the C++ standard library part you use for common data work. It includes containers like vector, map, set, queue, and algorithms like sort, find, count, and binary_search.

    Think of it as your project toolbox. If your app stores expenses, votes, tasks, marks, or UPI-like transactions, STL probably has the data structure you need.

    Your to-do

    Choose containers

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    Resource handling and project delivery

    5. Design classes with RAII

    5 min

    In 30 seconds
    • Design a C++ class that owns a resource and frees it automatically.
    • Use constructors, destructors, and deleted copy to prevent leaks and double frees.
    • Add one RAII-style class to your project and explain it in your README.
    Key point

    One ownership rule

    RAII means Resource Acquisition Is Initialization. Put the resource inside an object, acquire it in the constructor, and release it in the destructor.

    The resource can be a file, socket, database handle, mutex lock, heap buffer, or any thing that must be closed, unlocked, or freed.

    Why it matters

    In hackathon code, crashes often come from cleanup being skipped after an early return or error. RAII makes cleanup happen when the object goes out of scope.

    You already use RAII when you use std::string, std::vector, std::ifstream, and std::lock_guard. They clean themselves up without you calling free or close in many places.

    Example

    10 questions, 7 to pass.

    Sign in to take the test

    Another mistake is reading n items and then accessing v[n]. The last valid index is n - 1. C++ may not stop you. It may just give garbage or crash later.

    Example

    Before and after

    This small program reads daily expenses and prints the total. The safe version checks input, rejects negative counts, and never reads outside the vector.

    #include <iostream>
    #include <vector>
    using namespace std;
    
    int main() {
        int n = 0;
        if (!(cin >> n)) {
            cout << "Invalid count\n";
            return 1;
        }
    
        if (n < 0) {
            cout << "Count cannot be negative\n";
            return 1;
        }
    
        vector<int> expenses(n);
        for (int i = 0; i < n; i++) {
            if (!(cin >> expenses[i])) {
                cout << "Invalid expense\n";
                return 1;
            }
            if (expenses[i] < 0) {
                cout << "Expense cannot be negative\n";
                return 1;
            }
        }
    
        long long total = 0;
        for (int amount : expenses) {
            total += amount;
        }
    
        cout << total << "\n";
        return 0;
    }
    
    // Sample input:
    // 4
    // 120 50 30 200
    // Output:
    // 400
    Tip

    Use AI carefully

    You can ask ChatGPT or Gemini to review your C++ for undefined behaviour. Paste a function and ask: “Find uninitialised variables, out-of-range access, integer overflow risk, and bad input handling.”

    Do not accept the answer blindly. Check each suggestion against your code. AI often suggests style changes too. Keep the fixes that prevent real bugs.

    Your repo habit

    From lesson one, keep sample input near your code. A future internship reviewer should be able to run your program without guessing what to type.

    For now, a simple input.txt is enough. Later you will improve build instructions and README structure.

    // input.txt
    4
    120 50 30 200
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Safe function inputs

    This pattern fits many hackathon projects: read a list, compute something, and optionally print extra details.

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    struct Expense {
        string label;
        int amount;
    };
    
    int totalAmount(const vector<Expense>& expenses) {
        int total = 0;
        for (const Expense& e : expenses) {
            total += e.amount;
        }
        return total;
    }
    
    void addExpense(vector<Expense>& expenses, const string& label, int amount) {
        expenses.push_back({label, amount});
    }
    
    void printFirst(const vector<Expense>* expenses) {
        if (expenses == nullptr || expenses->empty()) {
            cout << "No expenses\n";
            return;
        }
        cout << expenses->at(0).label << " " << expenses->at(0).amount << "\n";
    }
    
    int main() {
        vector<Expense> trip;
        addExpense(trip, "chai", 20);
        addExpense(trip, "metro", 60);
    
        cout << totalAmount(trip) << "\n";
        printFirst(&trip);
        printFirst(nullptr);
    }
    Common mistake

    Dangling addresses

    Do not return a reference or pointer to a local variable. The local dies when the function ends.

    Also be careful with addresses of vector elements. push_back can move the vector storage, so old pointers or references to elements may become invalid.

    int& badRef() {
        int marks = 95;
        return marks; // bad: marks dies here
    }
    
    Expense* badPtr() {
        Expense e{"idli", 40};
        return &e; // bad: e dies here
    }
    Tip

    Use AI carefully

    If you ask ChatGPT or Gemini to refactor C++ code, ask it to explain every pointer and reference it uses.

    Check three things in the answer: can this be nullptr, who owns this object, and can this address outlive the object? If the answer is unclear, prefer a reference or a normal value.

    Prompt:
    Refactor this C++ function to avoid unsafe raw pointers where possible.
    For every reference or pointer you use, explain whether it can be null and who owns the object.
    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    0 of 5 done

    Example

    Expense summary example

    Here is a small pattern you can use in a project. It stores spends by category, sorts them, and prints the biggest categories first.

    This is useful for a hostel expense tracker, event budget tool, or any project with grouped totals.

    #include <algorithm>
    #include <iostream>
    #include <string>
    #include <unordered_map>
    #include <vector>
    using namespace std;
    
    int main() {
        vector<pair<string, int>> expenses = {
            {"food", 120}, {"travel", 40}, {"food", 80},
            {"printing", 30}, {"travel", 60}
        };
    
        unordered_map<string, int> total;
        for (const auto& item : expenses) {
            const string& category = item.first;
            int amount = item.second;
            total[category] += amount;
        }
    
        vector<pair<string, int>> report(total.begin(), total.end());
    
        sort(report.begin(), report.end(), [](const auto& a, const auto& b) {
            return a.second > b.second;
        });
    
        for (const auto& row : report) {
            cout << row.first << ": Rs " << row.second << '\n';
        }
    }
    Tip

    Use algorithms first

    Before writing a loop, ask if an STL algorithm already does it. This makes your intent clear to a reviewer reading your GitHub repo.

    Common picks: sort for ordering, find for search, count_if for filtering count, accumulate for totals, and lower_bound for binary search on sorted data.

    #include <algorithm>
    #include <numeric>
    #include <vector>
    using namespace std;
    
    vector<int> marks = {55, 82, 41, 90, 76};
    
    sort(marks.begin(), marks.end());
    
    int passed = count_if(marks.begin(), marks.end(), [](int x) {
        return x >= 50;
    });
    
    int total = accumulate(marks.begin(), marks.end(), 0);
    Common mistake

    Common mistakes

    Do not use lower_bound on an unsorted vector. It only works correctly when the range is sorted in the same order you search.

    Do not keep iterators or references after changing a vector size with push_back if the vector may reallocate. Use indexes, or finish adding data before storing references.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    4. Handle strings and parsing

    5 min

    In 30 seconds
    • Read whole lines safely, even when they contain spaces.
    • Split simple text formats using getline, stringstream, and checks.
    • Add sample input so your C++ repo is easy to run and review.
    Key point

    One habit

    Treat input as text first. Then convert it only after checking that the pieces exist.

    This keeps your program safer when a user types extra spaces, leaves a field empty, or pastes data from a file.

    Why parsing matters

    Most hackathon C++ projects need some input. It may be a CSV of expenses, a timetable, a list of tasks, or commands typed in a terminal.

    Bad parsing makes good logic look broken. Your repo should include sample input so reviewers can run the same case you tested.

    Common mistake

    Common input trap

    Do not mix cin >> with getline without handling the leftover newline. cin >> reads one token. getline reads the rest of the current line.

    If you read an int with cin, then want a full name or sentence, clear the newline first.

    int n;
    cin >> n;
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    
    string title;
    getline(cin, title);
    Example

    Parse simple CSV

    For project data, keep the format simple. This example reads lines like item,category,amount and skips bad rows instead of crashing.

    It uses getline with a comma delimiter, then converts the amount with stod inside a try block.

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <vector>
    using namespace std;
    
    struct Expense {
        string item;
        string category;
        double amount;
    };
    
    int main() {
        vector<Expense> expenses;
        string line;
    
        while (getline(cin, line)) {
            if (line.empty()) continue;
    
            stringstream ss(line);
            string item, category, amountText;
    
            if (!getline(ss, item, ',')) continue;
            if (!getline(ss, category, ',')) continue;
            if (!getline(ss, amountText, ',')) continue;
    
            try {
                double amount = stod(amountText);
                expenses.push_back({item, category, amount});
            } catch (const invalid_argument&) {
                cerr << "Skipping bad amount: " << line << '\n';
            }
        }
    
        double total = 0;
        for (const auto& e : expenses) total += e.amount;
        cout << "Total: " << total << '\n';
    }
    Tip

    Ask AI carefully

    You can ask ChatGPT or Gemini to generate parsing code, but give the exact input format and bad cases.

    Check what it returns. Look for unchecked indexing, missing failed-read checks, and conversions that can throw without being handled.

    Prompt:
    Write C++17 code to read lines in this format:
    item,category,amount
    Skip blank lines. If amount is invalid, print an error to cerr and continue.
    Do not use non-standard libraries.
    Example

    Sample input file

    Add a small sample file to your repo. Name it something obvious, like sample_expenses.txt.

    This helps another builder or internship reviewer run your project without guessing the input shape.

    chai,canteen,15
    bus pass,travel,450
    notebook,stationery,60
    wrong row,canteen,abc
    Your to-do

    Parsing checklist

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Small file wrapper

    This class owns a C FILE pointer. It opens the file in the constructor and closes it in the destructor.

    Copying is disabled because two objects closing the same file would be unsafe. Move semantics comes next lesson, so keep this simple for now.

    #include <cstdio>
    #include <stdexcept>
    #include <string>
    
    class FileReader {
        FILE* file;
    
    public:
        explicit FileReader(const std::string& path) : file(std::fopen(path.c_str(), "r")) {
            if (!file) {
                throw std::runtime_error("Could not open file: " + path);
            }
        }
    
        ~FileReader() {
            if (file) {
                std::fclose(file);
            }
        }
    
        FileReader(const FileReader&) = delete;
        FileReader& operator=(const FileReader&) = delete;
    
        int getChar() {
            return std::fgetc(file);
        }
    };
    
    int main() {
        FileReader input("sample.txt");
        int ch = input.getChar();
        return 0;
    }
    Your to-do

    Design the class

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Common mistake

    Common bad pattern

    Do not make users remember to call cleanup manually. Someone will return early during a contest fix and forget it.

    If your class has open(), close(), and no destructor doing cleanup, it is not protecting the rest of your code.

    void process() {
        FILE* f = std::fopen("data.txt", "r");
        if (!f) return;
    
        // Bug risk: any early return before fclose leaks the file handle.
        if (someCondition()) return;
    
        std::fclose(f);
    }
    Tip

    Prefer existing RAII

    Before writing your own RAII class, check if the standard library already has one. Use std::ifstream for files, std::vector for dynamic arrays, std::unique_ptr for single ownership, and std::lock_guard for locks.

    Write your own wrapper only when your project uses a C library, system handle, or custom resource that the STL does not already manage.

    README proof

    For your HackIndia repo, explain one class that manages ownership. Mention what it owns, where it acquires the resource, where it releases it, and why copying is disabled or safe.

    This is useful for internships because it shows you can write C++ that survives errors, not just pass sample test cases.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    6. Understand move semantics plainly

    5 min

    In 30 seconds
    • Know why moves avoid expensive copies in C++.
    • Use std::move only when you are done with an object.
    • Spot when classes need move support because they own resources.
    Key point

    One idea

    A move transfers ownership of a value’s inside data instead of copying it. After you move from an object, keep it valid but do not depend on its old contents.

    Why moves matter

    In C++ projects, you often pass around big strings, vectors, maps, buffers, or objects that own files and memory. Copying them can be costly because it duplicates their contents.

    Moving is cheaper when the type supports it. A vector move usually hands over its internal storage pointer instead of copying every element.

    Example

    Copy versus move

    This example shows the difference in intent. The moved-from string is still safe to destroy or assign to, but you should not print it expecting the old text.

    #include <iostream>
    #include <string>
    #include <utility>
    
    int main() {
        std::string a = "HackIndia C++ project";
    
        std::string b = a;              // copy: a still has the text
        std::string c = std::move(a);   // move: c takes a's contents if possible
    
        std::cout << "b = " << b << '\n';
        std::cout << "c = " << c << '\n';
    
        a = "new value";               // OK: reuse after assigning a fresh value
        std::cout << "a = " << a << '\n';
    }

    What std::move does

    std::move does not move by itself. It casts an object so C++ is allowed to use a move constructor or move assignment operator.

    If the type has no move support, C++ may copy instead. Standard library types like std::string, std::vector, and std::unique_ptr support move behaviour.

    Common mistake

    Do not overuse it

    Beginners often write std::move everywhere to make code look faster. That can make code harder to read and can cause bugs when the old object is used later.

    Use std::move only when the source object will not be needed with its current value. Good places are returning ownership, pushing temporary data into a container, or transferring a resource.

    Example

    A project-style use

    Suppose your project reads tasks from input and stores them. If you build a Task object locally and then store it, move it when you are done with the local object.

    #include <string>
    #include <vector>
    #include <utility>
    
    struct Task {
        std::string title;
        std::string owner;
    };
    
    int main() {
        std::vector<Task> backlog;
    
        Task t{"Fix login bug", "Asha"};
        backlog.push_back(std::move(t));   // t is no longer needed here
    
        // Do not read t.title here expecting "Fix login bug".
    }
    Tip

    Prefer simple ownership

    Most of the time, you do not write move constructors yourself. Let std::string, std::vector, std::map, std::unique_ptr, and your simple classes handle it.

    If your class only contains safe standard library members, the compiler-generated move operations are usually enough. If your class manually owns a raw resource, first ask if you can replace it with RAII types from the previous lesson.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    7. Compile, debug, and test locally

    4 min

    In 30 seconds
    • Compile C++ locally with useful warnings and a simple command.
    • Debug crashes and wrong answers with gdb and small test cases.
    • Add repeatable local tests before you push your project.
    Key point

    One habit

    Never trust a C++ project that only ran once in your IDE. Build it from the terminal, run small tests, then debug with tools when it fails.

    Your HackIndia repo should let another builder clone it, compile it, and check sample cases without guessing.

    Compile locally

    For a small project, one clear compile command is enough. Keep it in your README and test it on your own laptop before submitting.

    Use warnings while building. They catch many bugs before your program runs.

    Example

    Starter command

    This builds one file into an executable named app. It uses a modern C++ standard and common warning flags.

    g++ -std=c++17 -Wall -Wextra -pedantic -g main.cpp -o app
    ./app
    Your to-do

    Test with files

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    mkdir -p samples
    ./app < samples/input1.txt > samples/output1_actual.txt
    diff samples/output1_expected.txt samples/output1_actual.txt
    Example

    Tiny test setup

    For a student expense splitter, your sample data can be simple. The point is repeatability, not a huge dataset.

    samples/input1.txt
    3
    Asha 120
    Ravi 60
    Imran 0
    
    samples/output1_expected.txt
    Each person should pay: 60
    Asha gets 60
    Imran pays 60
    Tip

    Use gdb calmly

    When your program crashes, do not add random cout lines everywhere first. Rebuild with -g, then run it inside gdb.

    The backtrace shows where the program failed. The frame command lets you inspect that exact function.

    g++ -std=c++17 -Wall -Wextra -pedantic -g main.cpp -o app
    gdb ./app
    run < samples/input1.txt
    bt
    frame 0
    print variableName
    Common mistake

    Common trap

    Do not test only the happy case. Add cases for empty input, one item, duplicate names, large values, and invalid lines if your project accepts user text.

    Also avoid hardcoded absolute paths like C:\Users\name\file.txt or /home/name/data.txt. They will break on someone else’s machine.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    8. Ship your C++ repo

    5 min

    In 30 seconds
    • Turn a local C++ project into a clean public GitHub repo.
    • Write a README that explains the problem, approach, build, and run steps.
    • Add sample input or data so reviewers can try your project fast.
    Key point

    One idea

    Your repo is part of your project. A reviewer should understand what it does, build it, run it, and see one sample result in under five minutes.

    What to ship

    For HackIndia, do not submit only a zip file or a single .cpp pasted somewhere. Submit a public GitHub repository with a clear structure and a README.

    Keep the project small but complete. A hostel mess expense tracker, DSA visual helper, UPI split calculator, or file search tool is fine if it works and is easy to run.

    Example

    Simple repo layout

    Use boring names. They help recruiters and teammates scan your work quickly.

    mess-expense-tracker/
      README.md
      src/
        main.cpp
        Expense.cpp
        Expense.h
      data/
        sample_expenses.csv
      tests/
        sample_input.txt
      .gitignore
    Your to-do

    Prepare the repo

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done

    Example

    Useful .gitignore

    This is enough for many student C++ repos. Add more only when you need it.

    # build outputs
    build/
    *.o
    *.exe
    *.out
    
    # editor files
    .vscode/
    .idea/
    
    # OS files
    .DS_Store
    Example

    README template

    Your README should answer four questions: what problem, how it works, how to run it, and what C++ features you used.

    Use AI to draft the README if you want. Check that every command is real for your repo, every file name exists, and the feature list is honest.

    # Mess Expense Tracker
    
    ## Problem
    Students often split mess and canteen expenses in groups. This tool reads expenses from a CSV file and prints how much each person owes or should receive.
    
    ## Approach
    The program stores each expense as an object, groups totals by name, and calculates the final balance for each student.
    
    ## C++ features used
    - std::vector for storing expenses
    - std::map for totals by student name
    - Classes to model Expense records
    - RAII through standard library containers
    - File input using std::ifstream
    
    ## Build
    Run from the project root:
    
    g++ -std=c++17 src/main.cpp src/Expense.cpp -o mess_tracker
    
    ## Run
    ./mess_tracker data/sample_expenses.csv
    
    ## Sample output
    Asha should receive Rs 120
    Rahul should pay Rs 80
    Neha should pay Rs 40
    Common mistake

    Common repo mistakes

    Do not submit a repo that only works on your laptop because it uses an absolute path like C:\Users\You\Desktop\data.csv. Use relative paths such as data/sample_expenses.csv.

    Do not claim advanced C++ features just to sound better. If you did not use move semantics or RAII directly, say you used standard library containers safely.

    Your to-do

    Do this now

    Do each one yourself, then tap it to tick it off. The ticks are only a checklist for you: they are not marked or scored.

    0 of 5 done