Lesson 01beginnerFoundation

Introduction to C

Transition from C++ to C. Covers scanf/printf, string handling with fgets, file I/O using fopen/fclose, structs, complex format specifiers, functions with pointer parameters, and dynamic 2D allocation.

scanfprintffopenstructspointers
1

Basic Input & Output

Side-by-side comparison of C scanf/printf versus C++ cin/cout, showing equivalent I/O operations.

01-basic-input-output.c186 lines
2

More Basic I/O

Extended I/O examples covering multiple data types and format specifiers.

02-more-basic-input-output.c64 lines
/*
 * 02-more-basic-input-output.c — More I/O — multiple data types and format specifiers
 *
 * Key concepts: scanf, printf, data types
 * Compile: gcc -o prog 02-more-basic-input-output.c
 * Run:     ./prog
 */




// to write the same program in c:
//https://en.cppreference.com/w/c/io //IMPORTANT
#include <stdio.h>
//https://en.cppreference.com/w/c/io/fscanf
int main()
{
    // there are MANY variant of scanf and printf
    // scanf() and printf() are the most basic ones
    //basic scanf:
    printf("\n");
    printf("========================================\n");
    printf("  C I/O Variants: scanf, sscanf, snprintf\n");
    printf("========================================\n\n");

    // --- Section 1: Basic scanf ---
    printf("--- Section 1: Basic scanf (reading from keyboard) ---\n\n");
    int number;
    printf("  Enter a number: ");
    fflush(stdout);
    scanf("%d", &number);
    printf("  You entered: %d\n\n", number);

    // --- Section 2: sscanf (parsing from a string) ---
    printf("--- Section 2: sscanf (reading from a string) ---\n\n");
    //its very helpful, when you have a string and you need to
    // extract some data from it
    char data[] = "123 456";
    int a, b;
    // (parameters: string, format, variables)
    sscanf(data, "%d %d", &a, &b);
    printf("  Input string: \"%s\"\n", data);
    printf("  sscanf(data, \"%%d %%d\", &a, &b)\n");
    printf("  Result: a = %d, b = %d\n\n", a, b);

    // --- Section 3: snprintf (safe formatted printing to a string) ---
    printf("--- Section 3: snprintf (print to string, not screen) ---\n\n");
    // another usefull in my opinion is snprintf
    // which instead of printing to std output, it prints to a string
    // which buffer overflow protection

    char buffer[10]; // Small buffer to demonstrate overflow protection
    int length = snprintf(buffer, sizeof(buffer), "Hello, %s!", "World");
    printf("  Buffer size: %zu bytes\n", sizeof(buffer));
    printf("  snprintf(buffer, %zu, \"Hello, %%s!\", \"World\")\n", sizeof(buffer));
    printf("  Result:  \"%s\"\n", buffer);
    printf("  Wanted length: %d  (truncated because buffer is only %zu bytes)\n\n", length, sizeof(buffer));

    printf("========================================\n");
    printf("  End of demo\n");
    printf("========================================\n");

    return 0;
}
3

String Reading with fgets

Safe string input using fgets instead of the dangerous gets function, with buffer size handling.

03-more-basic-input-output.c83 lines
4

File I/O Basics

File operations with fopen, fclose, fprintf, and fscanf — the C equivalent of C++ fstream.

04-basic-files-ptrs.c116 lines
5

Structs with File I/O

Reading and writing struct data to files, combining struct definitions with file operations.

05-more-files-struct.c113 lines
6

Complex Format Specifiers

Advanced printf/scanf formatting: width, precision, padding, and field alignment.

06-complex-usage-scanf-printf.c75 lines
/*
 * 06-complex-usage-scanf-printf.c — Advanced scanf/printf formatting — width, precision, flags
 *
 * Key concepts: format specifiers, width modifiers, precision
 * Compile: gcc -o prog 06-complex-usage-scanf-printf.c
 * Run:     ./prog
 */


// to write the same program in c:
// https://en.cppreference.com/w/c/io //IMPORTANT
#include <stdio.h>

int main()
{

    printf("\n");
    printf("========================================\n");
    printf("  Advanced scanf/printf Formatting\n");
    printf("========================================\n\n");

    // --- Section 1: Multi-type scanf ---
    printf("--- Section 1: Reading multiple types at once ---\n\n");
    int integer;
    float realNumber;
    char character;
    char string[100];

    printf("  Enter: integer float char string (e.g., 42 3.14 A hello): ");
    fflush(stdout);
    scanf("%d %f %c %s", &integer, &realNumber, &character, string);

    printf("\n  %-12s | %s\n", "Type", "Value");
    printf("  ------------ | -----\n");
    printf("  %%d (int)     | %d\n", integer);
    printf("  %%f (float)   | %.2f\n", realNumber);
    printf("  %%c (char)    | '%c'\n", character);
    printf("  %%s (string)  | \"%s\"\n\n", string);

    // --- Section 2: Precision and width ---
    printf("--- Section 2: Precision and width formatting ---\n\n");
    double pi = 3.141592653589793;
    int number = 50;

    printf("  Pi with different precision:\n");
    printf("    %%.2f  -> %.2f\n", pi);
    printf("    %%.5f  -> %.5f\n", pi);
    printf("    %%.10f -> %.10f\n\n", pi);

    printf("  Width formatting (| shows boundaries):\n");
    printf("    %%10d  (right-aligned) -> |%10d|\n", number);
    printf("    %%-10d (left-aligned)  -> |%-10d|\n\n", number);

    // --- Section 3: Parsing a date string ---
    printf("--- Section 3: Parsing a formatted string ---\n\n");
    char line[256];
    int day, year;
    char month[20];
    fgetc(stdin); // Consume leftover newline from previous scanf

    printf("  Enter a date (e.g., January 1, 2020): ");
    fflush(stdout);
    fgets(line, sizeof(line), stdin);
    sscanf(line, "%s %d, %d", month, &day, &year);

    printf("\n  Parsed result:\n");
    printf("    Month: %s\n", month);
    printf("    Day:   %d\n", day);
    printf("    Year:  %d\n", year);
    if (year == 0) printf("    NOTE: Year is 0 — did you forget the comma?\n");

    printf("\n========================================\n");
    printf("  End of demo\n");
    printf("========================================\n");
}
7

More Complex Formatting

Parsing mixed-type input with sscanf, handling whitespace in format strings, and using scansets to extract substrings.

07-another-complex.c80 lines
/*
 * 07-another-complex.c — More complex scanf/printf patterns
 *
 * Key concepts: format strings, type modifiers
 * Compile: gcc -o prog 07-another-complex.c
 * Run:     ./prog
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int main() {
    char *line = NULL;   // Pointer to the buffer allocated by getline
    size_t len = 0;      // Size of the allocated buffer
    size_t read;        // Number of characters read by getline
    int *grades = NULL;  // Array to store grades
    int numGrades = 0;   // Number of grades read
    char name[100];      // String to store the name

    printf("\n");
    printf("========================================\n");
    printf("  Tokenizing Input (strtok + realloc)\n");
    printf("========================================\n\n");
    printf("  Enter grades followed by a name\n");
    printf("  Example: 90 85 72 John Smith\n\n");
    printf("  > ");
    fflush(stdout);
    read = getline(&line, &len, stdin); // Read the line
    if (read == -1) {
        printf("Failed to read input\n");
        return 1; // Exit if input reading fails
    }

    // Tokenize the input to separate grades from the name
    char *token = strtok(line, " \n");
    while (token != NULL) {
        int grade;
        if (sscanf(token, "%d", &grade) == 1) {
            // Reallocate grades array to hold new grade
            int *newGrades = realloc(grades, (numGrades + 1) * sizeof(int));
            if (newGrades == NULL) {
                printf("Failed to allocate memory for grades\n");
                free(grades);
                free(line);
                return 1;
            }
            grades = newGrades;
            grades[numGrades++] = grade;
        } else {
            // Assume the token is part of the name
            strcpy(name, token);
            // Collect the remaining part of the name
            while ((token = strtok(NULL, "\n")) != NULL) {
                strcat(name, " ");
                strcat(name, token);
            }
            break;
        }
        token = strtok(NULL, " \n");
    }

    // Output the results
    printf("\n  --- Parsed Result ---\n\n");
    printf("  Name:   %s\n", name);
    printf("  Grades: ");
    for (int i = 0; i < numGrades; i++) {
        printf("%d%s", grades[i], (i < numGrades - 1) ? ", " : "");
    }
    printf("  (%d total)\n\n", numGrades);
    printf("========================================\n");

    // Clean up
    free(grades);
    free(line);

    return 0;

}
8

Functions with Pointers

Passing pointers to functions for output parameters — the C pattern for returning multiple values.

08-dont-forget-functions.c105 lines
9

Advanced Patterns

A multi-struct program that reads structured records from files using fopen/fscanf and processes them with pointer-based functions.

09-last-example.c71 lines
/*
 * 09-last-example.c — Advanced pointer patterns and string manipulation
 *
 * Key concepts: pointers, strings, arrays
 * Compile: gcc -o prog 09-last-example.c
 * Run:     ./prog
 */

#include <stdio.h>
#include <stdlib.h>

void initializeData(int **data, int rows, int cols);

int main() {
    
    printf("\n");
    printf("========================================\n");
    printf("  Dynamic 2D Array with int**\n");
    printf("========================================\n\n");

    int rows = 3, cols = 4;
    printf("  Allocating %dx%d matrix with malloc...\n\n", rows, cols);
    int **data = malloc(rows * sizeof(int*));
    initializeData(data, rows, cols);

    printf("  Values (data[i][j] = i * %d + j):\n\n", cols);
    printf("       ");
    for (int j = 0; j < cols; j++) printf("col%-2d ", j);
    printf("\n       ");
    for (int j = 0; j < cols; j++) printf("----- ");
    printf("\n");
    for (int i = 0; i < rows; i++) {
        printf("  row%d |", i);
        for (int j = 0; j < cols; j++) {
            printf(" %3d  ", data[i][j]);
        }
        printf("\n");
    }
    printf("\n========================================\n");

    // Free the allocated memory
    for (int i = 0; i < rows; i++) {
        free(data[i]);
    }
    free(data);

    return 0;
}


void initializeData(int **data, int rows, int cols) {
    // Allocate memory for the array of row pointers
    
    if (data == NULL) {
        perror("Failed to allocate memory for row pointers");
        exit(EXIT_FAILURE);
    }

    // Allocate memory for each row and initialize values
    for (int i = 0; i < rows; i++) {
        (data)[i] = malloc(cols * sizeof(int));
        if ((data)[i] == NULL) {
            perror("Failed to allocate memory for rows");
            exit(EXIT_FAILURE);
        }
        for (int j = 0; j < cols; j++) {
            (data)[i][j] = i * cols + j;  // Example data
        }
    }
}
Expected Outputclick Run to execute live
========================================
  Dynamic 2D Array with int**
========================================

  Allocating 3x4 matrix with malloc...

  Values (data[i][j] = i * 4 + j):

       col0  col1  col2  col3  
       ----- ----- ----- ----- 
  row0 |   0     1     2     3  
  row1 |   4     5     6     7  
  row2 |   8     9    10    11  

========================================
10

2D Dynamic Allocation

Dynamically allocating a 2D array using pointer-to-pointer, with proper malloc/free patterns.

10-last-last-example.c76 lines
/*
 * 10-last-last-example.c — 2D dynamic allocation in C (malloc/free)
 *
 * Key concepts: malloc, free, 2D arrays, pointer-to-pointer
 * Compile: gcc -o prog 10-last-last-example.c
 * Run:     ./prog
 */

#include <stdio.h>
#include <stdlib.h>

void initializeData(int ***data, int rows, int cols);

int main() {
    
    printf("\n");
    printf("========================================\n");
    printf("  Dynamic 2D Array with int*** (triple pointer)\n");
    printf("========================================\n\n");
    printf("  Same as example 09, but the function\n");
    printf("  receives int*** so it can allocate\n");
    printf("  the array itself (modify caller's pointer).\n\n");

    int rows = 3, cols = 4;
    int ** data;
    printf("  Calling initializeData(&data, %d, %d)...\n\n", rows, cols);
    initializeData(&data, rows, cols);

    printf("  Values (data[i][j] = i * %d + j):\n\n", cols);
    printf("       ");
    for (int j = 0; j < cols; j++) printf("col%-2d ", j);
    printf("\n       ");
    for (int j = 0; j < cols; j++) printf("----- ");
    printf("\n");
    for (int i = 0; i < rows; i++) {
        printf("  row%d |", i);
        for (int j = 0; j < cols; j++) {
            printf(" %3d  ", data[i][j]);
        }
        printf("\n");
    }
    printf("\n========================================\n");

    // Free the allocated memory
    for (int i = 0; i < rows; i++) {
        free(data[i]);
    }
    free(data);

    return 0;
}


void initializeData(int ***data, int rows, int cols) {
    // Allocate memory for the array of row pointers
    
    *data = malloc(rows*sizeof(int*));

    if (data == NULL) {
        perror("Failed to allocate memory for row pointers");
        exit(EXIT_FAILURE);
    }

    // Allocate memory for each row and initialize values
    for (int i = 0; i < rows; i++) {
        (*data)[i] = malloc(cols * sizeof(int));
        if ((*data)[i] == NULL) {
            perror("Failed to allocate memory for rows");
            exit(EXIT_FAILURE);
        }
        for (int j = 0; j < cols; j++) {
            (*data)[i][j] = i * cols + j;  // Example data
        }
    }
}
Expected Outputclick Run to execute live
========================================
  Dynamic 2D Array with int*** (triple pointer)
========================================

  Same as example 09, but the function
  receives int*** so it can allocate
  the array itself (modify caller's pointer).

  Calling initializeData(&data, 3, 4)...

  Values (data[i][j] = i * 4 + j):

       col0  col1  col2  col3  
       ----- ----- ----- ----- 
  row0 |   0     1     2     3  
  row1 |   4     5     6     7  
  row2 |   8     9    10    11  

========================================

Open Full Terminal

Get a Linux terminal with all 10 files from this lesson pre-loaded. Compile, run, and experiment freely.