Что программировать на C: идеи проектов для практики

Что программировать на C: идеи проектов для практики Полезное

Учебный проект на C — это небольшая законченная программа, которую пишут не ради оценки, а чтобы закрепить конкретный навык: работу с циклами, массивами, структурами, файлами или указателями. Хороший учебный проект узкий: он тренирует одну-две темы и доводится до работающего результата, который можно показать.

Ниже — идеи проектов на C, разбитые по уровням: новичок, средний, продвинутый. Для каждого указано, что он осваивает, а для ключевых — короткий рабочий пример на C, который можно скопировать, скомпилировать и запустить. Проекты — именно на C (не C++): без классов и объектов, на процедурных средствах и стандартной библиотеке.

Как выбрать проект под свой уровень

Проект полезен, когда он чуть сложнее того, что вы уже умеете, но не настолько, чтобы застрять на первом экране. Ориентир простой:

  • Новичок — освоены переменные, if, циклы и функции. Берите проекты с вводом-выводом и простой логикой в консоли.
  • Средний — уверенно работаете с массивами и функциями. Добавляйте структуры (struct), массивы структур и файлы.
  • Продвинутый — понятны указатели и динамическая память (malloc/free). Беритесь за алгоритмы, разбор строк и работу с внешними библиотеками.

Компилировать примеры ниже можно компилятором GCC или Clang:

cc project.c -o project
./project

Чтобы вывод был предсказуемым и его можно было сверить, входные данные в примерах заданы прямо в коде переменными. В реальной программе их читают с клавиатуры через scanf (не забывая & перед именем переменной) или из файла.

Проекты для новичков

На этом уровне цель — собрать законченную программу из базовых кирпичиков: ввод, ветвление, цикл. Идеи:

  • Игра «угадай число». Программа загадывает число, игрок называет варианты, программа подсказывает «больше» или «меньше». Осваивает: циклы, сравнения, генерацию случайных чисел (rand, srand из <stdlib.h>).
  • Консольный калькулятор. Два числа и знак операции, на выходе результат. Осваивает: оператор switch, обработку деления на ноль.
  • Конвертер величин (температура, валюта, единицы длины). Осваивает: арифметику с типом double и форматный вывод.
  • Таблица умножения заданного размера. Осваивает: вложенные циклы и выравнивание вывода.

Ядро игры «угадай число» — сравнение догадки с загаданным числом. Чтобы вывод был воспроизводимым, здесь загаданное и «догадки» заданы в коде; в настоящей игре загаданное берут из rand(), а догадки читают через scanf:

#include <stdio.h>

int main(void) {
    int secret = 42;
    int guesses[] = {50, 30, 42};  // что ввел бы игрок
    int n = sizeof(guesses) / sizeof(guesses[0]);
    for (int i = 0; i < n; i++) {
        int g = guesses[i];
        if (g == secret) {
            printf("Попытка %d: %d - угадал!\n", i + 1, g);
            break;
        } else if (g > secret) {
            printf("Попытка %d: %d - загаданное меньше\n", i + 1, g);
        } else {
            printf("Попытка %d: %d - загаданное больше\n", i + 1, g);
        }
    }
    return 0;
}

Вывод:

Попытка 1: 50 - загаданное меньше
Попытка 2: 30 - загаданное больше
Попытка 3: 42 - угадал!

Калькулятор строится вокруг switch по символу операции. Здесь важно отдельно обработать деление на ноль, иначе программа выдаст неопределенный результат:

#include <stdio.h>

int main(void) {
    double a = 12, b = 4;
    char op = '/';
    double res = 0;
    int ok = 1;
    switch (op) {
        case '+': res = a + b; break;
        case '-': res = a - b; break;
        case '*': res = a * b; break;
        case '/':
            if (b != 0) res = a / b;
            else ok = 0;
            break;
        default: ok = 0;
    }
    if (ok) printf("%.2f %c %.2f = %.2f\n", a, op, b, res);
    else printf("Операция невозможна\n");
    return 0;
}

Вывод:

12.00 / 4.00 = 3.00

Проекты среднего уровня

Здесь появляются собственные типы данных и хранение между запусками. Идеи:

  • Телефонная книга или список контактов. Осваивает: структуры struct, массивы структур, поиск и сравнение строк (strcmp).
  • Список дел (to-do) с сохранением в файл. Осваивает: файловый ввод-вывод (fopen, fprintf, fgets), чтобы записи не терялись после выхода.
  • Учет расходов с подсчетом итогов по категориям. Осваивает: массивы структур и агрегирование данных.
  • Простой текстовый квест с переходами между сценами. Осваивает: конечный автомат на switch и большом цикле.

Телефонная книга — это массив структур. Каждая запись хранит имя и телефон, а поиск идет по имени:

#include <stdio.h>
#include <string.h>

struct Contact {
    char name[32];
    char phone[16];
};

int main(void) {
    struct Contact book[3];
    strcpy(book[0].name, "Anna");  strcpy(book[0].phone, "+7-900-111");
    strcpy(book[1].name, "Boris"); strcpy(book[1].phone, "+7-900-222");
    strcpy(book[2].name, "Vera");  strcpy(book[2].phone, "+7-900-333");
    int n = 3;

    const char *query = "Boris";
    for (int i = 0; i < n; i++) {
        if (strcmp(book[i].name, query) == 0) {
            printf("%s: %s\n", book[i].name, book[i].phone);
            return 0;
        }
    }
    printf("Контакт не найден\n");
    return 0;
}

Вывод:

Boris: +7-900-222

Чтобы данные не терялись между запусками, их пишут в файл и читают обратно. Список дел в минимальном виде — это запись строк в файл и последующее чтение с нумерацией:

#include <stdio.h>

int main(void) {
    FILE *f = fopen("todo.txt", "w");
    if (!f) { printf("Не удалось открыть файл\n"); return 1; }
    fprintf(f, "Купить хлеб\n");
    fprintf(f, "Позвонить в банк\n");
    fclose(f);

    f = fopen("todo.txt", "r");
    char line[128];
    int num = 1;
    while (fgets(line, sizeof(line), f))
        printf("%d. %s", num++, line);
    fclose(f);
    return 0;
}

Вывод:

1. Купить хлеб
2. Позвонить в банк

Формат fgets читает строку вместе с символом перевода строки, поэтому в printf дополнительный \n не нужен — он уже пришел из файла.

Проекты продвинутого уровня

Здесь основной вес — алгоритмы, разбор данных и указатели, а иногда и внешние библиотеки. Идеи:

  • Валидатор номеров карт по алгоритму Луна. Осваивает: разбор строки посимвольно и арифметику контрольной суммы.
  • Свое key-value хранилище (мини-база на файле). Осваивает: динамическую память (malloc/free) и хеширование ключей.
  • Игра «змейка» в терминале. Осваивает: работу с библиотекой ncurses и обновление экрана в цикле. ncurses — внешняя библиотека, ставится отдельно.
  • Мини-интерпретатор арифметических выражений. Осваивает: разбор (парсинг) и стек.

Алгоритм Луна проверяет, могла ли строка цифр быть корректным номером карты: он не подтверждает существование карты, а лишь ловит опечатки. Идут по цифрам справа налево, каждую вторую удваивают (если получилось больше 9 — вычитают 9), складывают все и проверяют, делится ли сумма на 10:

#include <stdio.h>
#include <string.h>

int luhn_valid(const char *number) {
    int sum = 0, alt = 0;
    for (int i = (int)strlen(number) - 1; i >= 0; i--) {
        int d = number[i] - '0';
        if (alt) {
            d *= 2;
            if (d > 9) d -= 9;
        }
        sum += d;
        alt = !alt;
    }
    return sum % 10 == 0;
}

int main(void) {
    const char *cards[] = {"79927398713", "79927398710"};
    for (int i = 0; i < 2; i++)
        printf("%s: %s\n", cards[i], luhn_valid(cards[i]) ? "проходит" : "не проходит");
    return 0;
}

Вывод:

79927398713: проходит
79927398710: не проходит

Первое число — классический пример корректной по Луну последовательности, второе отличается последней цифрой и проверку не проходит. На этом проекте видно, зачем нужны контрольные суммы: одна опечатка в цифре ломает делимость суммы на 10.

Как довести проект до конца

Учебный проект ценен только доведенным до работающего состояния. Практичный порядок:

  1. Опишите одним предложением, что программа принимает на входе и что выдает на выходе.
  2. Соберите минимальную версию с данными, зашитыми прямо в код, — без ввода с клавиатуры и файлов. Главное, чтобы заработала логика.
  3. Добавьте ввод (scanf или чтение файла) и проверку некорректных данных: пустой ввод, деление на ноль, число вне диапазона.
  4. Разбейте код на функции: одна функция — одна задача. Так проект проще расширять и отлаживать.
  5. Проверьте на граничных случаях: пустой список, одно значение, максимально большое число.

Если не получается, диагностируйте по симптому: программа не компилируется — читайте первую ошибку компилятора, а не последнюю; компилируется, но падает при запуске — частая причина в выходе за границы массива или в отсутствии & в scanf; работает, но результат неверный — проверьте = вместо == в условиях и типы (целочисленное деление отбрасывает дробную часть).

FAQ

Можно ли эти проекты писать на C++, а не на C? Да, базовые конструкции совпадают, а код на C почти без изменений компилируется как C++. Отличие в том, что C++ дает дополнительные средства (классы, контейнеры, строки std::string), которых в чистом C нет.

Нужна ли графика для первого проекта? Нет. Консольные проекты тренируют ту же логику, что и графические, но без возни с библиотеками отрисовки. Графику (ncurses, SDL) стоит подключать, когда консольные проекты уже даются легко.

Как показать проект работодателю или в портфолио? Выложите исходный код в публичный репозиторий с коротким описанием: что программа делает, как ее собрать и запустить. Для джуна важнее читаемый код и доведенный до конца результат, чем масштаб.

Выводы

  • Учебный проект на C полезен, когда он узкий и доведен до работающего результата; выбирайте тему чуть сложнее текущего уровня.
  • Новичку подойдут консольные проекты на вводе-выводе и ветвлении: «угадай число», калькулятор, конвертер.
  • На среднем уровне добавляются структуры и файлы: телефонная книга, список дел с сохранением, учет расходов.
  • Продвинутые проекты держатся на алгоритмах и указателях: валидатор по Луну, key-value хранилище, игра в терминале.
  • Любой проект стоит собирать от минимальной версии с данными в коде, а ввод, проверки и разбиение на функции добавлять шагами.

Освойте тему на практике

Систематизировать эти навыки и получить обратную связь от практикующих разработчиков помогает курс Программирование на C++ с нуля: C и C++ разделяют общее процедурное ядро, с которого начинают оба языка, поэтому проекты на C — естественная точка входа. Посмотреть, как разбирают такие задачи вживую, и задать вопросы преподавателям можно на открытых вебинарах Otus — они бесплатные и проходят регулярно.

Смежные темы: C: описание языка и его основы, Как написать программу с нуля и стать программистом.

OTUS Журнал
Скидка 5% 14-20 сентября на курсы (popup)