c-cpp-cookies
  • Полезные материалы
    • About
  • Настройка окружения
    • Git
      • Git CLI
      • Git GUI
      • Git Web
      • Git в среде разработке
        • Visual Studio
        • Visual Studio Code
        • CLion
        • Qt Creator
    • Стандарты (они же ISO)
    • Qt about
    • IDE
      • Visual Studio Code
        • Код в Visual Studio Code
        • Разработка в Visual Studio Code
      • Visual Studio
        • Настройки Visual Studio и проектов
        • Код в Visual Studio
        • Visual Studio + GitHub
      • Qt + Qt Creator
        • Установка Qt и QtCreator
        • Примеры проектов на Qt
      • CLion
        • Настройки CLion
        • Код в CLion
        • CLion + GitHub
    • Компиляторы
      • Clang + Visual Studio
      • Clang + CLion
  • Best practices
    • Антипаттерны и способы улучшения кода
      • 0. Освобождение ресурсов
      • 1. Чтение данных из файла
      • 2. Открытие файлов
      • 3. Объявление переменных
      • 4. Выделение памяти
      • 5. Необдуманный код
      • 6. Глубокие if
      • 7. Длинные if
      • 9. Non-void функции
      • 10. Создание массивов
      • 11. Проверка формата файла
  • Сборка программы
    • Сборка программы
    • Системы сборки / Build systems
      • Проект и решение
      • Make
      • Ninja
      • CMake
      • MSBuild
    • Подключение внешних библиотек
    • Библиотеки
  • Отладка
    • Отладка / Debugging
    • Запуск программы
    • Точки останова / Breakpoints
      • Обычные точки останова / General breakpoint
      • Условные точки останова / Conditional breakpoint
      • Зависимые точки останова / Dependent breakpoint
      • Временные точки останова / Temporary breakpoint
      • Точки трассировки / Breakpoint actions и tracepoints
    • Стек вызовов / Call stack
    • Локальные переменные / Locals
    • Просмотр области памяти / Memory view
    • Исключения / Exceptions
  • Анализ
    • Поиск утечек памяти
    • Санитайзеры
  • Возможности IDE
    • Возможности IDE
    • Продвинутый текстовый редактор
    • Закладки / Bookmarks
    • Платформы / Platforms
    • Конфигурации сборки / Build configurations
    • Шаблонные проекты / Project templates
    • Терминал / Terminal
    • Сборка / Build
    • Запуск программы / Run program
    • Code style
    • Работа с Github Actions
  • Тестирование
    • Тестирование
    • Google test
      • Gtest в VS
      • Gtest в CLion
      • Gtest в VSCode
    • Покрытие кода (code coverage)
Powered by GitBook
On this page
  1. Best practices
  2. Антипаттерны и способы улучшения кода

10. Создание массивов

Previous9. Non-void функцииNext11. Проверка формата файла

Last updated 6 months ago

#include <stdio.h>

#define ARRAY_MAX_SIZE 2500
int array[ARRAY_MAX_SIZE];

Решение: не использовать такие массивы, особенно с выдуманными ограничениями по размеру никак не связанному с условием работ.

int n; // размер матрицы
float **read_matrix_from_file(char *filename)
{
    FILE *f = fopen(filename, "r");
    fscanf(f, "%d", &n);
    if (n <= 0) // "Error: negative size"
        exit(1);

    float **matrix = malloc(sizeof(float *) * n);
    for (int i = 0; i < n; i++)
    {
        matrix[i] = malloc(sizeof(float) * n);
        if (matrix[i] == NULL) // "Error: Memory allocation failed."
        {
            free(matrix);
            exit(1);
        }

        for (int j = 0; j < n; j++)
            if (!fscanf(f, "%float", &matrix[i][j])) // "Error: Invalid file format."
            {
                free(matrix);
                exit(1);
            }
    }
    fclose(f);
    return matrix;
}

int main(void)
{
    read_matrix_from_file("inputfile");
}
Вариант реорганизации и исправления кода

Однако в C++: "Stack is not unwound: destructors of variables with automatic storage duration are not called."

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

Более лучшее решение:

float **read_matrix_from_file(char *filename, int *n)
{
    FILE *f = fopen(filename, "r");
    if (fscanf(f, "%d", &n) != 1 && n <= 0) // "Error: negative size"
        return NULL;

    float **matrix = malloc(sizeof(float *) * *n);
    if (matrix == NULL)
    {
        return NULL;
    }
    for (int i = 0; i < n; i++)
    {
        matrix[i] = malloc(sizeof(float) * *n);
        if (matrix[i] == NULL)
        {
            for (int k = 0; k < i; ++k)
                free(matrix[k]);
            free(matrix);
            return NULL;
        }
        for (int j = 0; j < n; j++)
            if (!fscanf(f, "%f", &matrix[i][j]))
            {
                for (int k = 0; k < i; ++k)
                    free(matrix[k]);
                free(matrix);
                return NULL;
            }
    }
    fclose(f);
    return matrix;
}

int main(void)
{
    int n;
    read_matrix_from_file("inputfile", &n);
}

А вот в коде выше появилась новая проблема – exit. Если обратиться к стандарту или , то можно заметить, что гарантируются "several cleanup steps".

C
C++
3KB
.clang-format
Весь приведённый далее код оформлен с использованием clang-format