Стартер пак в C: 3 полезные библиотеки для начинающих. Часть 1

от автора

Привет, Хабр!

Если вы только начинаете свой путь в C, то наверняка уже знаете о том, насколько важны библиотеки. Они облегчают жизнь и позволяют сосредоточиться на решении задач, а не на создании всего с нуля. В статье расскажем о трех полезных библиотек на C, которые станут отличными прикладными помощниками.

GNU Scientific Library (GSL)

GNU Scientific Library — это свободно распространяемая библиотека для выполнения научных вычислений.

Линейная алгебра

GSL поддерживает создание и управление векторами и матрицами, включая базовые операции, такие как сложение, умножение и транспонирование.

Библиотека предоставляет функции для разложения матриц (LU, QR, Cholesky) и решения линейных систем уравнений.

#include <gsl/gsl_matrix.h> #include <gsl/gsl_linalg.h>  int main() {     gsl_matrix *m = gsl_matrix_alloc(3, 3);     gsl_vector *b = gsl_vector_alloc(3);     gsl_vector *x = gsl_vector_alloc(3);      // заполнение матрицы и вектора     gsl_matrix_set(m, 0, 0, 1.0);     gsl_matrix_set(m, 0, 1, 2.0);     gsl_matrix_set(m, 0, 2, 3.0);     gsl_vector_set(b, 0, 1.0);      gsl_linalg_HH_solve(m, b, x);      gsl_matrix_free(m);     gsl_vector_free(b);     gsl_vector_free(x);      return 0; }

Численное интегрирование

Существуют разные методы интегрирования, такие как адаптивные методы, методы Гаусса-Кронрода и интеграцию на бесконечных интервалах.

#include <gsl/gsl_integration.h>  double f(double x, void *params) {     return x*x; }  int main() {     gsl_integration_workspace *w = gsl_integration_workspace_alloc(1000);     double result, error;     gsl_function F;     F.function = &f;     gsl_integration_qags(&F, 0, 1, 0, 1e-7, 1000, w, &result, &error);     gsl_integration_workspace_free(w);     return 0; }

Функции хороши для вычисления определенных интегралов и обработки функций с особенностями и сингулярностями.

Генерация случайных чисел

Есть обширный набор генераторов случайных чисел и распределений, включая нормальное, экспоненциальное и другие распределения.

#include <gsl/gsl_rng.h> #include <gsl/gsl_randist.h>  int main() {     gsl_rng *r = gsl_rng_alloc(gsl_rng_default);     double x = gsl_ran_gaussian(r, 1.0);     gsl_rng_free(r);     return 0; }

Специальные функции

Есть в библиотеке множество специальных функций, таких как функции Бесселя, гамма-функции, полиномы Лежандра и многие другие, которые часто встречаются в научных вычислениях.

#include <gsl/gsl_sf_bessel.h>  int main() {     double x = 5.0;     double y = gsl_sf_bessel_J0(x);     printf("J0(%g) = %.18e\n", x, y);     return 0; }

Статистика и анализ данных

Еще есть инструменты для статистического анализа данных, включая методы оценки, тесты гипотез, и функции для работы с временными рядами.

#include <gsl/gsl_statistics.h>  int main() {     double data[] = {17.0, 15.0, 23.0, 7.0, 9.0, 13.0};     double mean = gsl_stats_mean(data, 1, 6);     double variance = gsl_stats_variance(data, 1, 6);     printf("Mean: %g, Variance: %g\n", mean, variance);     return 0; }

Пример применения

Провелем численное интегрирование функции, решим систему линейных уравнений и проведемстатистический анализ набора данных. Бдем использовать GSL для решения всех этих задач в одном проекте:

#include <stdio.h> #include <gsl/gsl_integration.h> #include <gsl/gsl_matrix.h> #include <gsl/gsl_linalg.h> #include <gsl/gsl_statistics.h>  double my_function(double x, void *params) {     return x*x; }  int main() {     // численное интегрирование     gsl_integration_workspace *workspace = gsl_integration_workspace_alloc(1000);     gsl_function F;     F.function = &my_function;     double result, error;     gsl_integration_qags(&F, 0, 1, 0, 1e-7, 1000, workspace, &result, &error);     printf("Integral result: %g, error: %g\n", result, error);     gsl_integration_workspace_free(workspace);      // решение системы линейных уравнений     gsl_matrix *m = gsl_matrix_alloc(2, 2);     gsl_vector *b = gsl_vector_alloc(2);     gsl_vector *x = gsl_vector_alloc(2);      gsl_matrix_set(m, 0, 0, 2.0);     gsl_matrix_set(m, 0, 1, 1.0);     gsl_matrix_set(m, 1, 0, 1.0);     gsl_matrix_set(m, 1, 1, 3.0);     gsl_vector_set(b, 0, 1.0);     gsl_vector_set(b, 1, 2.0);      gsl_linalg_HH_solve(m, b, x);      printf("Solution: x0 = %g, x1 = %g\n", gsl_vector_get(x, 0), gsl_vector_get(x, 1));      gsl_matrix_free(m);     gsl_vector_free(b);     gsl_vector_free(x);      // статистический анализ     double data[] = {17.0, 15.0, 23.0, 7.0, 9.0, 13.0};     double mean = gsl_stats_mean(data, 1, 6);     double variance = gsl_stats_variance(data, 1, 6);     printf("Mean: %g, Variance: %g\n", mean, variance);      return 0; }

Как можно увидеть, GSL — очень мощный инструмент. Подробнее с библиотекой можно ознакомиться здесь.

SQLite

SQLite — это легковесная, встроенная, самодостаточная и безсерверная библиотека, реализующая SQL-диск-движо

Архитектура SQLite

  • Токенизатор: Преобразует SQL-запросы в токены для их дальнейшей обработки. Эта стадия важна для правильной интерпретации SQL-команд.

  • Парсер: Использует Lemon парсер для создания синтаксического дерева запросов.

  • Генератор кода: Создает байт-код для выполнения SQL-запросов. Этот байт-код затем интерпретируется VM SQLite.

  • Виртуальная машина: Выполняет байт-код, обеспечивая выполнение SQL-команд. Виртуальная машина реализована в файле vdbe.c и управляется через API, такие как sqlite3_step().

Основные возможности

  • Создание и управление БД: SQLite позволяет создавать базы данных, таблицы и индексы с помощью стандартных SQL-команд.

  • SQL-запросы: Поддержка полного набора SQL-команд, включая SELECT, INSERT, UPDATE, DELETE и JOIN.

  • Встроенные функции: SQLite предоставляет множество встроенных функций, таких как abs(), length(), datetime(), coalesce() и многие другие.

  • Триггеры и представления: Поддержка триггеров и представлений для выполнения автоматических операций и упрощения сложных запросов.

  • Транзакции: Поддержка атомарных транзакций с возможностью отката ROLLBACK и фиксации COMMIT.

  • Пользовательские функции: Возможность создания пользовательских функций на C, которые могут быть вызваны из SQL-запросов.

Пример использования

#include <stdio.h> #include <sqlite3.h>  int main() {     sqlite3 *db;     char *err_msg = 0;      // открытие/создание БД     int rc = sqlite3_open("test.db", &db);     if (rc != SQLITE_OK) {         fprintf(stderr, "Cannot open database: %s\n", sqlite3_errmsg(db));         return rc;     }      // создание таблицы     char *sql = "CREATE TABLE IF NOT EXISTS Friends(Id INT, Name TEXT);"                 "INSERT INTO Friends VALUES(1, 'Tom');"                 "INSERT INTO Friends VALUES(2, 'Rebecca');"                 "INSERT INTO Friends VALUES(3, 'Jim');";      rc = sqlite3_exec(db, sql, 0, 0, &err_msg);     if (rc != SQLITE_OK) {         fprintf(stderr, "SQL error: %s\n", err_msg);         sqlite3_free(err_msg);         sqlite3_close(db);         return rc;     }      // чтение данных     sql = "SELECT * FROM Friends";     sqlite3_stmt *stmt;     rc = sqlite3_prepare_v2(db, sql, -1, &stmt, 0);     if (rc != SQLITE_OK) {         fprintf(stderr, "Failed to fetch data: %s\n", sqlite3_errmsg(db));         sqlite3_close(db);         return rc;     }      while (sqlite3_step(stmt) == SQLITE_ROW) {         printf("%s: %s\n", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1));     }      // завершение работы с базой данных     sqlite3_finalize(stmt);     sqlite3_close(db);      return 0; }

Подробнее про библиотеку можно посмотреть здесь.

SDL

Simple DirectMedia Layer — мощная кроссплатформенная библиотека для разработки мультимедийных приложений и игр. SDL предоставляет низкоуровневый доступ к аудио, клавиатуре, мыши, джойстику и графическому оборудованию.

Основные функции SDL

Все приложения на SDL начинаются с инициализации, которая выполняется с помощью функции SDL_Init. Эта функция принимает флаги, определяющие подсистемы, которые необходимо инициализировать, такие как видео, аудио, джойстики и т.д.

Для корректного завершения работы и освобождения ресурсов используется функция SDL_Quit:

if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0) {     printf("SDL_Init Error: %s\n", SDL_GetError());     return 1; } // завершение работы SDL_Quit();

SDL позволяет создавать окна с помощью функции SDL_CreateWindow, которая принимает параметры для установки заголовка окна, его позиции и размеров. Для рендеринга используется функция SDL_CreateRenderer, которая создает контекст рендера для заданного окна:

SDL_Window *win = SDL_CreateWindow("Hello SDL", 100, 100, 640, 480, SDL_WINDOW_SHOWN); if (win == NULL) {     printf("SDL_CreateWindow Error: %s\n", SDL_GetError());     SDL_Quit();     return 1; }  SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); if (ren == NULL) {     SDL_DestroyWindow(win);     printf("SDL_CreateRenderer Error: %s\n", SDL_GetError());     SDL_Quit();     return 1; }

Функция SDL_PollEvent используется для извлечения событий из очереди:

SDL_Event e; while (SDL_PollEvent(&e)) {     if (e.type == SDL_QUIT) {         break;     } }

Для работы с изображениями SDL предоставляет функции загрузки текстур и их рендеринга на экран. Функция SDL_CreateTextureFromSurface создает текстуру из загруженного изображения, а SDL_RenderCopy используется для её отображения:

SDL_Surface *bmp = SDL_LoadBMP("image.bmp"); if (bmp == NULL) {     printf("SDL_LoadBMP Error: %s\n", SDL_GetError());     SDL_DestroyRenderer(ren);     SDL_DestroyWindow(win);     SDL_Quit();     return 1; }  SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp); SDL_FreeSurface(bmp); if (tex == NULL) {     printf("SDL_CreateTextureFromSurface Error: %s\n", SDL_GetError());     SDL_DestroyRenderer(ren);     SDL_DestroyWindow(win);     SDL_Quit();     return 1; }  SDL_RenderClear(ren); SDL_RenderCopy(ren, tex, NULL, NULL); SDL_RenderPresent(ren);

Пример использования

Рассмотрим простой пример создания окна, рендеринга изображения и обработки событий:

#include <SDL.h> #include <stdio.h>  int main(int argc, char **argv) {     if (SDL_Init(SDL_INIT_VIDEO) != 0) {         printf("SDL_Init Error: %s\n", SDL_GetError());         return 1;     }      SDL_Window *win = SDL_CreateWindow("Hello SDL", 100, 100, 640, 480, SDL_WINDOW_SHOWN);     if (win == NULL) {         printf("SDL_CreateWindow Error: %s\n", SDL_GetError());         SDL_Quit();         return 1;     }      SDL_Renderer *ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);     if (ren == NULL) {         SDL_DestroyWindow(win);         printf("SDL_CreateRenderer Error: %s\n", SDL_GetError());         SDL_Quit();         return 1;     }      SDL_Surface *bmp = SDL_LoadBMP("image.bmp");     if (bmp == NULL) {         printf("SDL_LoadBMP Error: %s\n", SDL_GetError());         SDL_DestroyRenderer(ren);         SDL_DestroyWindow(win);         SDL_Quit();         return 1;     }      SDL_Texture *tex = SDL_CreateTextureFromSurface(ren, bmp);     SDL_FreeSurface(bmp);     if (tex == NULL) {         printf("SDL_CreateTextureFromSurface Error: %s\n", SDL_GetError());         SDL_DestroyRenderer(ren);         SDL_DestroyWindow(win);         SDL_Quit();         return 1;     }      SDL_RenderClear(ren);     SDL_RenderCopy(ren, tex, NULL, NULL);     SDL_RenderPresent(ren);      SDL_Event e;     while (1) {         if (SDL_PollEvent(&e) && e.type == SDL_QUIT) {             break;         }     }      SDL_DestroyTexture(tex);     SDL_DestroyRenderer(ren);     SDL_DestroyWindow(win);     SDL_Quit();     return 0; }

Код создает окно, загружает изображение, отображает его и обрабатывает событие закрытия окна.

Подробнее про библиотеку


В завершение хочу порекомендовать вам бесплатный вебинар про основы работы с памятью в языке C. Зарегистрироваться можно по этой ссылке.


ссылка на оригинал статьи https://habr.com/ru/articles/827918/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *