Remember Language C examples

07.01.2021

Почти весь СИ на одной страничке

Являюсь обычным web прогером (php, JavaScript, html, css)
И тут будет как бы видение языка С моими глазами. Сразу скажу, что многие языки очень на него похожи. Если вы забыли, как тут что пишется, то можно найти на этой стр. Так то все примеры и кодец скопировал с sololearn.com просто расположил их удобно на одной странице. Если кому нравится воспринимать больше по видео, то Гоша Дударь попытается вас обучить. Посмотрев несколько его видео, он показывает не всё, а только часть на скорую руку, тип как это всё может работать. Если бы показывал всё, то не все бы досматривали, так же, как не все дочитают этот текст..
Язык С создан в 1969 - 1973 годах сотрудником Bell Labs Деннисом Ритчи как улучшение языка Би.
Тут будет много примеров кода, чтобы начать компилировать C, вам поможет эта статья
Это не для обучения а больше для вспоминания языка, так же для копирования кода
#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
#include <stdio.h> int main() /*простая программа*/ { int num; num = 1; printf ("Я простая"); printf ("вычислительная машина.\n"); printf ("Мое любимое число %d, потому что оно самое первое.\n", num); return 0; }
на разных компах переменные по разному весят
#include <stdio.h> int main() { printf("int: %d \n", sizeof(int)); printf("float: %d \n", sizeof(float)); printf("double: %d \n", sizeof(double)); // this float with big 0 printf("char: %d \n", sizeof(char)); return 0; }

Целые числа

  • short предназначен для хранения целых чисел. Диапазон чисел от
    -32 768 до 32 767
  • unsigned short от 0 до 65 535
  • int от -2 147 483 648 до 2 147 483 647
  • unsigned int - от 0 до 4 294 967 295
  • long от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807
  • unsigned long от 0 до 18 446 744 073 709 551 615

Числа с точкой

  • float для создания чисел с плавающей точкой. Диапазон чисел от
    -3.4*10(в степ 38) до 3.4*10(в степ 38)
  • double от (+-)4.9*10(в степ -324) до (+-)1.8*10(в степ 308)

Прочие типы данных

  • bool логический тип данных. Предназначен для записи истинного (true) или ложного (false) значения
  • char тип данных для работы с символами. Позволяет поместить в одинарных кавычках какой-либо символ
#include <stdio.h> int main() { int a, b; float salary = 56.23; char letter = 'Z'; a = 8; b = 34; int c = a+b; printf("%d \n", c); // for int printf("%f \n", salary); // for float printf("%c \n", letter); // for char return 0; }
printf

%с Символ типа char
%d Десятичное число целого типа со знаком
%i Десятичное число целого типа со знаком
%е Научная нотация (е нижнего регистра)
%Е Научная нотация (Е верхнего регистра)
%f Десятичное число с плавающей точкой
%g Использует код %е или %f — тот из них, который короче (при использовании %g используется е нижнего регистра)
%G Использует код %Е или %f — тот из них, который короче (при использовании %G используется Е верхнего регистра)
%о Восьмеричное целое число без знака
%s Строка символов
%u Десятичное число целого типа без знака
%х Шестнадцатиричное целое число без знака (буквы нижнего регистра)
%Х Шестнадцатиричное целое число без знака (буквы верхнего регистра)
%р Выводит на экран значение указателя
%n Ассоциированный аргумент — это указатель на переменную целого типа, в которую помещено количество символов, записанных на данный момент
%% Выводит символ %
%4.2f Это выводит float, где показанно, сколько знаков до запятой и после
\" Выводит "
\n Выводит переход на след строку
Const. Define не использует память, а чисто заменяет значения перед компиляцией.
#include <stdio.h> int main() { const double PI = 3.14; printf("%f", PI); return 0; } OR #include <stdio.h> #define PI 3.14 int main() { printf("%f", PI); return 0; }
Input
getchar() считывает первый символ, если достигнут конец файла, то возвращается EOF. #include <stdio.h> int main() { char a = getchar(); printf("You entered: %c", a); return 0; } #include <stdio.h> int main() { char a[100]; gets(a); printf("You entered: %s", a); return 0; } scanf([формат считывания], [адрес переменной]) Адрес переменной взде, кроме текста. Если воодить цифры с буквами, он будет считывать с лева, пока введённое соответствует формату #include <stdio.h> int main() { int a; scanf("%d", &a); printf("You entered: %d", a); return 0; } #include <stdio.h> int main() { int a, b; printf("Enter two numbers:"); scanf("%d %d", &a, &b); printf("\nSum: %d", a+b); return 0; } #include <stdio.h> int main() { int x; float num; char text[20]; scanf("%d %f %s", &x, &num, text); } d decimal c character s string f float x hexadecimal
Output
#include <stdio.h> int main() { char a = getchar(); printf("You entered: "); putchar(a); return 0; } #include <stdio.h> int main() { char a[100]; gets(a); printf("You entered: "); puts(a); return 0; } ------ #include <stdio.h> int main() { int x, y; char text[20]; scanf("%2d %d %*f %5s", &x, &y, text); /* input: 1234 5.7 elephant */ printf("%d %d %s", x, y, text); /* output: 12 34 eleph */ return 0; } #include <stdio.h> int main() { printf("The tree has %d apples.\n", 22); /* output: The tree has 22 apples. */ printf("\"Hello World!\"\n"); /* output: "Hello World!" */ } \n new line \t horizontal tab \\ backslash \b backspace \' single quote \" double quote \% (not) => %% (yes) #include <stdio.h> int main() { printf("Color: %s, Number: %d, float: %5.2f \n", "red", 42, 3.14159); /* Color: red, Number: 42, float: 3.14 */ printf("Pi = %3.2f \n", 3.14159); /* Pi = 3.14 */ printf("Pi = %8.5f \n", 3.14159); /* Pi = 3.14159 */ printf("Pi = %-8.5f \n", 3.14159); /* Pi = 3.14159 */ printf("There are %d %s in the tree. \n", 22, "apples"); /* There are 22 apples in the tree. */ }
operators (mod %)
#include <stdio.h> int main() { int a = 6; int b = 4; int c = 2; int result; result = a - b + c; // 4 printf("%d \n", result); result = a + b / c; // 8 printf("%d \n", result); result = (a + b) / c; // 5 printf("%d \n", result); return 0; } #include <stdio.h> int main() { float price = 6.50; int increase = 2; float new_price; new_price = price + increase; printf("New price is %4.2f", new_price); /* Output: New price is 8.50 */ return 0; } #include <stdio.h> int main() { float average; int total = 23; int count = 4; average = (float) total / count; printf("%4.2f", average); return 0; } #include <stdio.h> int main() { int x = 2; x += 1; // 3 x -= 1; // 2 x *= 3; // 6 x /= 2; // 3 x %= 2; // 1 x += 3 * 2; // 7 printf("%d", x); return 0; } #include <stdio.h> int main() { int x, y, z; z = 3; x = z--; /* assign 3 to x, then decrement z to 2 */ printf("x=%d \n", x); y = 3; x = ++y; /* increment y to 4, then assign 4 to x */ printf("x=%d \n", x); printf("y=%d \n", y); return 0; }
Conditionals (Условные)
#include <stdio.h> int main() { int score = 89; if (score > 75) printf("You passed.\n"); return 0; } < less than <= less than or equal to > greater than >= greater than or equal to == equal to != not equal to #include <stdio.h> int main() { int num = 41; num += 1; if (num == 42) { printf("You won!"); } } #include <stdio.h> int main() { int in_stock = 20; if (in_stock) printf("Order received.\n"); } #include <stdio.h> int main() { int score = 89; if (score >= 90) printf("Top 10%%.\n"); else printf("Less than 90.\n");v return 0; } #include <stdio.h> int main() { int y; int x = 3; y = (x >= 5) ? 5 : x; printf("%d", y); return 0; } #include <stdio.h> int main() { int profit = 500; int clients = 12; int bonus = 0; if (profit > 1000) { if (clients > 15) bonus = 100; } else bonus = 25; printf("%d", bonus); } #include <stdio.h> int main() { int score = 89; if (score >= 90) printf("%s", "Top 10% \n"); else if (score >= 80) printf("%s", "Top 20% \n"); else if (score > 75) printf("%s", "You passed.\n"); else printf("%s", "You did not pass.\n"); } #include <stdio.h> int main() { int num = 3;b switch (num) { case 1: printf("One\n"); break; case 2: printf("Two\n"); break; case 3: printf("Three\n"); break; default: printf("Not 1, 2, or 3.\n"); } } #include <stdio.h>b int main() { int num = 3; switch (num) { case 1: case 2: case 3: printf("One, Two, or Three.\n"); break; case 4: case 5: case 6: printf("Four, Five, or Six.\n"); break; default: printf("Greater than Six.\n"); } } && || ! #include <stdio.h> int main() { int n = 42; if (n == 999 || (n > 0 && n <= 100)) printf("Input valid.\n"); } #include <stdio.h> int main() { char n = 'V'; if (!(n == 'x' || n == 'X')) printf("Roman numeral is not 10.\n"); } int v = 5 > 4 ? 6 : 8;
while
#include <stdio.h> int main() { int count = 1; while(count < 8) { printf("Count = %d\n", count); count++; } return 0; } #include <stdio.h> int main() { int count = 1; do{ printf("Count = %d\n", count); count++; } while(count < 8); return 0; } #include <stdio.h> int main() { int num = 5; while (num > 0) { if (num == 3) break; printf("%d\n", num); num--; } return 0; } #include <stdio.h> int main() { int num = 5; while (num > 0) { num--; if (num == 3) continue; printf("%d\n", num); } } #include <stdio.h> int main() { int i; int max = 10; for(i = 0; i < max; i++) { printf("%d\n", i); } }
function
void display_message();
#include <stdio.h> /* declaration */ int square(int num); int main(){ int x, result; x = 5; result = square(x); printf("%d squared is %d\n", x, result); return 0; } /* definition */ int square(int num){ int y; y = num * num; return(y); } #include <stdio.h> int sum_up(int x, int y); int main(){ int x, y, result; x = 3; y = 22; //result = sum_up(x, y); printf("%d + %d = %d", x, y, sum_up(x, y)); return 0; } int sum_up(int x, int y){ x += y; return(x); } демонстрация рекурсии #include <stdio.h> //function declaration int factorial(int num); int main() { int x = 5; printf("The factorial of %d is %d\n", x, factorial(x)); return 0; } //function definition int factorial(int num) { if (num == 1) /* base case */ return (1); else return (num * factorial(num - 1)); } The factorial of 5 is 120 просто выйти с функции без выполнения return;
глобальные переменные
#include int global1 = 0; int main() { int local1, local2; local1 = 5; local2 = 10; global1 = local1 + local2; printf("%d \n", global1); /* 15 */ return 0; } статичная переменная обьявляется 1 раз и сохраняется на протяжен всей программы #include void say_hello(); int main() { int i; for (i = 0; i < 5; i++) { say_hello(); } return 0; } void say_hello() { static int num_calls = 1; printf("Hello number %d\n", num_calls); num_calls++; } Hello number 1 Hello number 2 Hello number 3 Hello number 4 Hello number 5
Array
int test_scores[25]; /* An array size 25 */ float prices[5] = {3.2, 6.55, 10.49, 1.25, 0.99}; float prices[5] = {3.2, 6.55}; массив не может менять свой размер вызов и изменение #include <stdio.h> int main() { int x[5] = {20, 45, 16, 18, 22}; x[1] = 260; printf("The second element is %d\n", x[1]); /* 260 */ return 0; } #include <stdio.h> int main() { float purchases[3] = {10.99, 14.25, 90.50}; float total = 0; int k; /* total the purchases */ for (k = 0; k < 3; k++) { total += purchases[k]; printf("total = %6.2f\n", total); } printf("Purchases total is %6.2f\n", total); /* Output: Purchases total is 115.74 */ return 0; } int a[2][3] = { {3, 2, 6}, {4, 5, 20} }; #include <stdio.h> int main() { int a[2][3] = { {3, 2, 6}, {4, 5, 20} }; printf("Element 3 in row 2 is %d\n", a[1][2]); /* 20 */ a[1][2] = 25; printf("Element 3 in row 2 is %d\n", a[1][2]); /* 25 */ return 0; } #include <stdio.h> int main() { int a[2][3] = { {3, 2, 6}, {4, 5, 20} }; int k, j; /* display array contents */ for (k = 0; k < 2; k++) { for (j = 0; j < 3; j++) { printf(" %d", a[k][j]); } printf("\n"); } return 0; }
Addres Data (Адрес данных / указатели)
*p - указатель
(*p) - значение указателя
#include <stdio.h> void test(int k); int main() { int i = 0; printf("The address of i is %x\n", &i); test(i); printf("The address of i is %x\n", &i); test(i); return 0; } void test(int k) { printf("The address of k is %x\n", &k); } The address of i is 61fe1c The address of k is 61fdf0 The address of i is 61fe1c The address of k is 61fdf0 #include <stdio.h> int main() { int j = 63; int *p = NULL; p = &j; printf("The address of j is %x\n", &j); printf("p contains address %x\n", p); printf("The value of j is %d\n", j); printf("p is pointing to the value %d\n", *p); } The address of j is 61fe14 p contains address 61fe14 The value of j is 63 p is pointing to the value 63 // Адрес адреса int x = 12; int *p = NULL int **ptr = NULL; p = &x; ptr = &p; // (*p) можно использовать вместо названия переменной #include <stdio.h> int main() { int x = 5; int y; int *p = NULL; p = &x; y = *p + 2; /* y is assigned 7 */ y += *p; /* y is assigned 12 */ *p = y; /* x is assigned 12 */ (*p)++; /* x is incremented to 13 */ printf("p is pointing to the value %d\n", *p); } указатели хорошо служат на массивах #include <stdio.h> int main() { int a[5] = {22, 33, 44, 55, 66}; int *ptr = NULL; int i; ptr = a; for (i = 0; i < 5; i++) { printf("%d ", *(ptr + i)); } } имя массива служит указателем на 0 элемент массива #include <stdio.h> int main() { int a[5] = {22, 33, 44, 55, 66}; int *ptr = NULL; ptr = a; /* point to the first array element */ printf("%d %x\n", *ptr, ptr); /* 22 */ ptr++; printf("%d %x\n", *ptr, ptr); /* 33 */ ptr += 3; printf("%d %x\n", *ptr, ptr); /* 66 */ ptr--; printf("%d %x\n", *ptr, ptr); /* 55 */ ptr -= 2; printf("%d %x\n", *ptr, ptr); /* 33 */ } 22 61fe00 33 61fe04 66 61fe10 55 61fe0c 33 61fe04 #include <stdio.h> void swap (int *num1, int *num2); int main() { int x = 25; int y = 100; printf("x is %d, y is %d\n", x, y); swap(&x, &y); printf("x is %d, y is %d\n", x, y); return 0; } void swap (int *num1, int *num2) { int temp; temp = *num1; *num1 = *num2; *num2 = temp; } в функцию мы не можем передать массив, поэтому передаем массив только через указатель #include <stdio.h> int add_up (int *a, int num_elements); int main() { int orders[5] = {100, 220, 37, 16, 98}; printf("Total orders is %d\n", add_up(orders, 5)); return 0; } int add_up (int *a, int num_elements) { int total = 0; int k; for (k = 0; k < num_elements; k++) { total += a[k]; } return (total); } с функции нельзя вернуть массив, просто возвращаем указатель на него #include <stdio.h> int * get_evens(); int main() { int *a; int k; a = get_evens(); /* get first 5 even numbers */ for (k = 0; k < 5; k++) printf("%d\n", a[k]); return 0; } int * get_evens () { static int nums[5]; int k; int even = 0; for (k = 0; k < 5; k++) { nums[k] = even += 2; // even += 2; nums[k] = even; } return (nums); } 2 4 6 8 10 a[k] === *(a + k);
Строки
Строка в C - это массив символов, который заканчивается символом NULL '\ 0'.
#include <stdio.h> int main() { char str1[6] = "hello"; char str2[ ] = "world"; /* size 6 */ printf("str1 is: %s, str2 is: %s", str1, str2); return 0; } #include <stdio.h> int main() { char str3[6] = {'h', 'e', 'l', 'l', 'o', '\0'}; char str4[ ] = {'h', 'e', 'l', 'l', 'o', '\0'}; /* size 6 */ printf("str3 is: %s, str4 is: %s", str3, str4); return 0; } забудьте включить <string.h>. strlen () - получить длину строки strcat () - объединить две строки strcpy () - копировать одну строку в другую strlwr () - преобразовать строку в нижний регистр Strupr () - преобразовать строку в верхний регистр strrev () - обратная строка strcmp () - сравнить две строки #include <stdio.h> int main() { char first_name[25]; int age; printf("Enter your first name and age: \n"); scanf("%s %d", first_name, &age); // Считывание с клавы printf("\nHi, %s. Your age is %d", first_name, age); return 0; } #include <stdio.h> int main() { char full_name[50]; printf("Enter your full name: "); gets(full_name); // Считывание с клавы printf("\nHi, %s.", full_name); return 0; }
fgets более безопасный приём строки с клавы
fgets(char *str, int num, FILE *stream)
считывает до num-1 символов
из файла stream
и помещает их в массив символов,
на который указывает str
#include <stdio.h> int main() { char full_name[50]; printf("Enter your full name: "); fgets(full_name, 50, stdin); printf("\nHi, %s", full_name); return 0; }
вывод строки
fputs(const char *str, FILE *stream)
записывает содержимое строки,
на которую указывает sir,
в заданный поток.
#include <stdio.h> int main() { char city[40]; printf("Enter your favorite city: "); gets(city); //Ввод строки fputs(city, stdout); // выводит строку printf(" is a fun city."); return 0; } //gg //Enter your favorite city: gg is a fun city. #include <stdio.h> int main() { char city[40]; printf("Enter your favorite city: "); gets(city); puts(city); // Тоже вывод return 0; } //gg2 //Enter your favorite city: gg2
sprintf() - Перевести данные в строку
#include <stdio.h> int main() { char info[100]; char dept[ ] = "HR"; int emp = 75; sprintf(info, "The %s dept has %d employees.", dept, emp); printf("%s\n", info); return 0; }
Пример рандом на си
#include <time.h> #include <stdio.h> #include <conio.h> #include <stdlib.h> int get_rand_int(int min, int max) ; int main() { short a, b, c, d; srand(time(NULL)); // min= 10; max= 90+10-1;=99 a = get_rand_int(10, 99); b = get_rand_int(10, 99); printf("Solve the equation: \n"); printf ("%d", a); if(a < b){ c = a + b; printf(" + "); }else{ c = a - b; printf(" - "); } printf ("%d = ", b); scanf("%d", &d); printf ("%d\n", d); if(c == d){ printf("Right"); }else{ printf("NOT Right"); } return 0; } int get_rand_int(const int min, const int max) { return rand() % (max - min + 1) + min; }
Мини окно для винды
#include <windows.h> int main() { MessageBox(NULL,"Hello, World!","Test",MB_OK); return 0; }
sscanf(Строка, формат данных через пробел, куда эти данные передавать)
для поиска значений в строке. Функция считывает значения из строки и сохраняет их по соответствующим адресам переменных.
#include <stdio.h> int main() { char info[] = "Snoqualmie WA 13190"; char city[50]; char state[50]; int population; sscanf(info, "%s %s %d", city, state, &population); printf("%d people live in %s, %s.", population, city, state); return 0; }
string.h
#include <string.h>

strlen(str) Возвращает длину строки, хранящейся в str, не включая символ NULL.

strcat(str1, str2) Добавляет (объединяет) str2 в конец str1 и возвращает указатель на str1.

strcpy(str1, str2) Копирует str2 в str1. Эта функция полезна для присвоения строке нового значения.
#include <stdio.h> #include <string.h> int main() { char s1[] = "The grey fox"; char s2[] = " jumped."; strcat(s1, s2); printf("%s\n", s1); printf("Length of s1 is %d\n", strlen(s1)); strcpy(s1, s2); printf("s1 is now %s \n", s1); return 0; }
strncat(str1, str2, n) Добавляет (объединяет) первые n символов str2 в конец str1 и возвращает указатель на str1.

strncpy(str1, str2, n) Копирует первые n символов str2 в str1.

strcmp(str1, str2) Возвращает 0, если str1 равно str2, меньше 0, если str1 меньше str2, и больше 0, если str1 больше str2.

strncmp(str1, str2, n) Возвращает 0, когда первые n символов str1 равны первым n символам str2, меньше 0, если str1 меньше str2, и больше 0, когда str1 больше str2.

strchr(str1, c) Возвращает указатель на первое вхождение char c в str1 или NULL, если символ не найден.

strrchr(str1, c) Ищет str1 в обратном порядке и возвращает указатель на позицию char c в str1 или NULL, если символ не найден.

strstr(str1, str2) Возвращает указатель на первое вхождение str2 в str1 или NULL, если str2 не найден.
int atoi(str) Преобразует ASCII в целое число. Преобразует str в эквивалентное значение типа int. 0 возвращается, если первый символ не является числом или числа не встречаются.

double atof(str) Используется для плавающего кода ASCII. Преобразует str в эквивалентное значение типа double. 0.0 возвращается, если первый символ не является числом или числа не встречаются.

long int atol(str) Заменяет ASCII на long int. Преобразует str в эквивалентное длинное целое число. 0 возвращается, если первый символ не является числом или числа не встречаются.
конвертер из строки в число
#include <stdio.h> int main() { char input[10]; int num; printf("Enter a number: "); gets(input); num = atoi(input); printf("You entered %d", num); return 0; }
В atoi() отсутствует обработка ошибок, рекомендуется использовать strtol(строка для преобразования, char*, система счисления)
li2 = strtol(pEnd, &pEnd, 16), // преобразовать часть строки в значение 16-й СС li3 = strtol(pEnd, &pEnd, 2), // преобразовать часть строки в значение 2-й СС
char trip[3][15] = { "suitcase", "passport", "ticket" }; // Массивы #include <stdio.h> int main() { char *trip[] = { "suitcase", "passport", "ticket" }; printf("Please bring the following:\n"); for (int i = 0; i < 3; i++) { printf("%s\n", trip[i]); } return 0; } // Чтобы функции скормить другую функцию, её надо сделать в виде указателя. // Можно скопировать функцию вот так #include <stdio.h> void say_hello(int num_times); /* function */ int main() { void (*funptr)(int); /* function pointer */ funptr = say_hello; /* pointer assignment */ funptr(3); /* function call */ return 0; } void say_hello(int num_times) { int k; for (k = 0; k < num_times; k++) printf("Hello\n"); } // Копирование, если у функции несколько аргументов int sum(int a, int b){ return a + b; } int (*psum)(int,int) = sum; // Пример, где все функции находятся в массиве #include <stdio.h> int add(int num1, int num2); int subtract(int num1, int num2); int multiply(int num1, int num2); int divide(int num1, int num2); int main() { int x, y, choice, result; int (*op[4])(int, int); op[0] = add; op[1] = subtract; op[2] = multiply; op[3] = divide; printf("Enter two integers: "); scanf("%d%d", &x, &y); printf("Enter 0 to add, 1 to subtract, 2 to multiply, or 3 to divide: "); scanf("%d", &choice); result = op[choice](x, y); printf("\n %d", result); return 0; } int add (int x, int y) { return(x + y); } int subtract (int x, int y) { return(x - y); } int multiply (int x, int y) { return(x * y); } int divide (int x, int y) { if (y != 0) return (x / y); else return 0; }
Void
Указатель void используется для ссылки на любой тип адреса в памяти и имеет объявление, которое выглядит так: void * ptr;
Это как одно название переменной может быть разного формата, но неудобно его воспроизводить..
#include <stdio.h> int main() { int x = 33; float y = 12.4; char c = 'a'; void *ptr; ptr = &x; printf("void ptr points to %d\n", *((int *)ptr)); ptr = &y; printf("void ptr points to %f\n", *((float *)ptr)); ptr = &c; printf("void ptr points to %c", *((char *)ptr)); return 0; }
Вот функция, которая принимает число в виде ссылки , умножает его и возвращает
#include <stdio.h> void * square (const void *num); int main() { int x, sq_int; x = 6; sq_int = square(&x); printf("%d squared is %d\n", x, sq_int); return 0; } void * square(const void *num) { static int result; result = (*(int *)num) * (*(int *)num); return(result); }

Длинна массива

Если у вас есть array sizeof(array) возвращает количество байтов, которое занимает массив. Поскольку каждый элемент может занимать более 1 байта пространства, вам нужно разделить результат на размер одного элемента (sizeof(array[0])). Это дает вам количество элементов в массиве.

Сортировка массива

qsort(
  адрес массива, // (void *)arr
  количество элементов в массиве, // num = sizeof(arr)/sizeof(arr[0]); 
  размер одного элемента, // width = sizeof(arr[0]);
  функция определения сортировки // compare
);
#include <stdio.h> #include <stdlib.h> int compare (const void *, const void *); int main() { int arr[5] = {52, 23, 56, 19, 4}; int num, width, i; num = sizeof(arr)/sizeof(arr[0]); // Делим на размер одного элемента printf("sizeof(arr) %d\n ", sizeof(arr)); printf("sizeof(arr[0]) %d\n ", sizeof(arr[0])); width = sizeof(arr[0]); qsort((void *)arr, num, width, compare); // Сортировка for (i = 0; i < 5; i++) printf("%d ", arr[ i ]); return 0; } int compare(const void *elem1, const void *elem2) { if ((*(int *)elem1) == (*(int *)elem2)) return 0; else if ((*(int *)elem1) < (*(int *)elem2)) return -1; else return 1; }

Cтруктуры

struct course { int id; char title[40]; float hours; };
#include <stdio.h> struct student { int age; int grade; char name[40]; }; int main() { /* declare two variables */ struct student s1; struct student s2; s1.age = 19; s1.grade = 9; sprintf(s1.name, "John Bighimer"); s2.age = 22; s2.grade = 10; sprintf(s2.name, "Batman Jokerson"); printf("Student: %s, %d\n", s1.name, s1.age); printf("Student: %s, %d\n", s2.name, s2.age); return 0; } or struct student s1 = {19, 9, "John Birghimer"}; struct student s2 = {22, 10, "Batman Jokerson"}; or struct student s1; // declaring s1 = (struct student){19, 9, "John Birghimer"}; or struct student s1 = { .grade = 9, .age = 19, .name = "John Birghimer"}; or s1.age = 19;
структуры можно передать такому же типу
#include <stdio.h> struct student { int age; int grade; char name[40]; }; int main() { struct student s1 = {19, 9, "Jason"}; struct student s2; printf("Assigning, s2 = s1\n"); s2 = s1; printf("Results, Name: %s, Age: %d, Grade: %d\n", s2.name, s2.age, s2.grade); return 0; }
Пример с таймером, для сравнения скорости работы
#include <stdio.h> #include <time.h> int main(){ clock_t start = clock(); long d = 0.0; for (long i = 0; i < 100000000; i++) { d += i >> 1; } clock_t end = clock(); clock_t elapsed = (end - start) / (CLOCKS_PER_SEC / 1000); printf("%ld\n", d); printf("%lu\n", elapsed); }
#include <stdio.h> #include <string.h> struct course { int id; char title[40]; float hours; }; int main() { struct course cs1 = {341279, "Intro to C++", 12.5}; struct course cs2; cs2.id = 341281; strcpy(cs2.title, "Advanced C++"); cs2.hours = 14.25; printf("%d\t%s\t%4.2f\n", cs1.id, cs1.title, cs1.hours); printf("%d\t%s\t%4.2f\n", cs2.id, cs2.title, cs2.hours); return 0; }
typedef помогает записать структуру проще
#include <stdio.h> #include <string.h> typedef struct { int id; char title[40]; float hours; } course; int main() { course cs1; course cs2; cs1.id = 123456; strcpy(cs1.title, "JavaScript Basics"); cs1.hours = 12.30; cs2.id = 341281; strcpy(cs2.title, "Advanced C++"); cs2.hours = 14.25; printf("%d\t%s\t%4.2f\n", cs1.id, cs1.title, cs1.hours); printf("%d\t%s\t%4.2f\n", cs2.id, cs2.title, cs2.hours); return 0; }
Структуры могут быть вложенные
#include <stdio.h> typedef struct { int x; int y; } point; typedef struct { float radius; point center; } circle; int main() { point p; p.x = 3; p.y = 4; circle c; c.radius = 3.14; c.center = p; c.center.y = 37; circle c = {4.5, {1, 3}}; printf("Circle radius is %.2f, center is at (%d, %d)", c.radius, c.center.x, c.center.y); return 0; }
Так же, как указатели на переменные, могут быть определены указатели на структуры.
struct myStruct * struct_ptr; определяет указатель на структуру myStruct. struct_ptr = & struct_var; сохраняет адрес структурной переменной struct_var в указателе struct_ptr. struct_ptr -> struct_mem; получает доступ к значению члена структуры struct_mem.
еще можно передавать указатели на структуры
#include <stdio.h> #include <string.h> struct student{ char name[50]; int number; int age; }; void showStudentData(struct student *st) { printf("\nStudent:\n"); printf("Name: %s\n", st->name); printf("Number: %d\n", st->number); printf("Age: %d\n", st->age); } int main() { struct student st1; struct student st2; strcpy(st1.name, "Krishna"); st1.number = 5; st1.age = 21; strcpy(st2.name, "Max"); st2.number = 9; st2.age = 15; showStudentData(&st1); showStudentData(&st2); return 0; }
(*st) .age совпадает с st-> age.
Кроме того, когда для имени структуры используется typedef,
тогда указатель объявляется с использованием только имени
typedef вместе с * и именем указателя. (*st) .age
Передавая структуру функции в виде указателя,
можно менять данные структуры.
#include <stdio.h> #include <string.h> typedef struct { int id; char title[40]; float hours; } course; void update_course(course *class); void display_course(course class); int main() { course cs2; update_course(&cs2); display_course(cs2); return 0; } void update_course(course *class) { strcpy(class->title, "C++ Fundamentals"); class->id = 111; class->hours = 12.30; } void display_course(course class) { printf("%d\t%s\t%3.2f\n", class.id, class.title, class.hours); }
В массиве могут храниться элементы любого типа данных, включая структуры.
После объявления массива структур, элемент становится доступным по порядковому номеру.
Затем оператор точки используется для доступа к членам элемента, как в программе:
#include <stdio.h> typedef struct { int h; int w; int l; } box; int main(){ box boxes[3] = {{2, 6, 8}, {4, 6, 6}, {2, 6, 9}}; int k, volume; for (k = 0; k < 3; k++) { volume = boxes[k].h * boxes[k].w * boxes[k].l; printf("box %d volume %d\n", k, volume); } return 0; }
union (союз) это подобие структуры
Союзы используются для управления памятью. Самый большой тип данных члена используется для определения размера разделяемой памяти, а затем все члены используют это одно место. Этот процесс также помогает ограничить фрагментацию памяти.
Как я понял: это хранит все данные в одной области памяти и последняя запись данных перезаписывает всё предыдущее, размер определяется самым большим его свойством (типом).
#include <stdio.h> union val { int int_num; float fl_num; char str[20]; }; int main() { union val test; test.int_num = 42; printf("%d", test.int_num); return 0; }
union , так же как и структуру, можно копировать
#include <stdio.h> union val { int int_num; float fl_num; char str[20]; }; int main() { union val u1; union val u2; u1.int_num = 42; u2 = u1; printf("%d", u2.int_num); return 0; }
Последнее присвоение переопределяет предыдущие назначения, поэтому str сохраняет значение и доступ к int_num и fl_num бессмыслен.
#include <stdio.h> union val { int int_num; float fl_num; char str[20]; }; int main() { union val test; test.int_num = 123; test.fl_num = 98.76; strcpy(test.str, "hello"); printf("%d\n", test.int_num); printf("%f\n", test.fl_num); printf("%s\n", test.str); return 0; }
Объединения часто используются в структурах, потому что в структуре может быть член, чтобы отслеживать, какой член объединения хранит значение. Например, в следующей программе структура транспортного средства использует либо идентификационный номер транспортного средства (VIN), либо назначенный идентификатор, но не оба сразу:
#include <stdio.h> #include <string.h> typedef struct { char make[20]; int model_year; int id_type; /* 0 for id_num, 1 for VIN */ union { int id_num; char VIN[20]; } id; } vehicle; int main() { vehicle car1; strcpy(car1.make, "Ford"); car1.model_year = 2017; car1.id_type = 0; car1.id.id_num = 123098; printf("Car %s, %d, %d", car1.make, car1.model_year, car1.id.id_num); return 0; } #include <stdio.h> #include <string.h> typedef struct { char make[20]; int model_year; int id_type; /* 0 for id_num, 1 for VIN */ union { int id_num; char VIN[20]; } id; } vehicle; int main() { vehicle car1; strcpy(car1.make, "Ford"); car1.model_year = 2017; car1.id_type = 0; car1.id.id_num = 123098; printf("Make: %s\n", car1.make); printf("Model Year: %d\n", car1.model_year); if (car1.id_type == 0) printf("ID: %d\n", car1.id.id_num); else printf("ID: %s\n", car1.id.VIN); return 0; }
Если мы поставим указатель на обьединение, и через указатель поменяем обьединению данные, то в самом обьединении так же поменяются данные
#include <stdio.h> #include <string.h> union val { int int_num; float fl_num; char str[20]; }; int main() { union val info; union val *ptr = NULL; ptr = &info; ptr->int_num = 10; printf("info.int_num is %d", info.int_num); return 0; }
(*ptr).int_num === ptr->int_num
#include <stdio.h> #include <string.h> union id { int id_num; char name[20]; }; void set_id (union id *item); void show_id (union id item); int main() { union id item; set_id(&item); show_id(item); return 0; } void set_id(union id *item) { item->id_num = 42; } void show_id(union id item) { printf("ID is %d", item.id_num); }
#include <stdio.h> union val { int int_num; float fl_num; char str[20]; }; int main() { union val nums[10]; int k; /* create an array of ints */ for (k = 0; k < 10; k++) { nums[k].int_num = k; } /* display array values */ for (k = 0; k < 10; k++) { printf("%d ", nums[k].int_num); } return 0; }
Массив - это структура данных, в которой хранятся значения коллекции одного типа. Массивы объединений позволяют хранить значения разных типов.
#include <stdio.h> union type { int i_val; float f_val; char ch_val; }; int main() { union type arr[3]; arr[0].i_val = 42; arr[1].f_val = 3.14; arr[2].ch_val = 'x'; printf("1st element is %d, 2nd is %f, and the 3rd is %c", arr[0].i_val, arr[1].f_val, arr[2].ch_val); return 0; }

библиотека для управления памятью

#include <stdlib.h>
malloc(bytes) - Возвращает указатель на непрерывный блок памяти размером в байты.
calloc(num_items, item_size) Возвращает указатель на непрерывный блок памяти, который имеет num_items элементов, каждый размером item_size в байтах. Обычно используется для массивов, структур и других производных типов данных. Выделенная память инициализируется 0.
realloc(ptr, bytes) - Изменяет размер памяти, на которую указывает ptr, до размера в байтах. Вновь выделенная память не инициализируется.
free(ptr) Освобождает блок памяти, на который указывает ptr.

malloc(10) - запросить память 10 байт, она отдает указатель на начало, этот адрес надо сохранить в указатель, она должна быть кратна размеру типа.
то, что вернется юзайте, как указатель на массив

int x;
sozeof(x);
#include <stdio.h> #include <stdlib.h> int main() { int *ptr; ptr = malloc(10*sizeof(*ptr)); /* a block of 10 ints */ if (ptr != NULL) { *(ptr+2) = 50; /* assign 50 to third int */ } printf("3rd elem equals to %d", *(ptr + 2)); return 0; }
mallog может послать нахер, поэтому всегда проверяем, не равен ли указатель NULL

free(ptr); правильно освобождать память в той же функции, где ее взяли

calloc(количество структур, sizeof(структура)) выделение памяти для структуры
calloc выделяет блоки памяти в непрерывном блоке памяти для массива элементов структуры. Вы можете переходить от одной структуры к другой с помощью арифметики указателя. После выделения места для структуры необходимо выделить память для строки внутри структуры. Использование указателя для информационного элемента позволяет сохранять строку любой длины. Динамически распределяемые структуры являются основой связанных списков и двоичных деревьев, а также других структур данных.
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int num; char *info; } record; int main() { record *recs; int num_recs = 2; int k; char str[ ] = "This is information"; recs = calloc(num_recs, sizeof(record)); if (recs != NULL) { for (k = 0; k < num_recs; k++) { (recs+k)->num = k; (recs+k)->info = malloc(sizeof(str)); strcpy((recs+k)->info, str); } } for (k = 0; k < num_recs; k++) { printf("%d\t%s\n", (recs+k)->num, (recs+k)->info); } return 0; }
Функция realloc (указатель, количество * sizeof(указатель на данные)) расширяет текущий блок, чтобы включить дополнительную память.
#include <stdio.h> #include <stdlib.h> int main() { int *ptr; ptr = malloc(10*sizeof(*ptr)); /* a block of 10 ints */ if (ptr != NULL) { *(ptr+2) = 50; /* assign 50 to third int */ } ptr = realloc(ptr, 100*sizeof(*ptr)); /* 100 ints */ *(ptr+30) = 75; printf("%d %d", *(ptr+2), *(ptr+30)); return 0; }
strlen При использовании strlen для определения количества байтов, необходимых для строки, не забудьте включить один дополнительный байт для символа NULL '\ 0'. Символ всегда состоит из одного байта, поэтому нет необходимости умножать требования к памяти на sizeof (char).
#include <stdio.h> #include <string.h> int main (void) { char str [11]="0123456789"; printf ("Length string \"%s\" - %d char \n", str, strlen (str) ); return 0; } #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char str20[20]; char *str = NULL; strcpy(str20, "12345"); printf("str20 size: %d\n", sizeof(str20)); printf("str20 length: %d\n", strlen(str20)); str = malloc(strlen(str20)+1); /* make room for \0 */ strcpy(str, str20); printf("%s", str); return 0; }
Динамический массив - как безразмерный
Вся программа написана в main () в демонстрационных целях. Чтобы правильно реализовать динамический массив, подзадачи следует разбить на такие функции, как init_array (), Increase_array (), add_element () и display_array (). Проверка ошибок также была пропущена, чтобы демонстрация была короткой.
#include <stdio.h> #include <stdlib.h> // создали структуру typedef struct { int *elements; int size; int cap; } dyn_array; int main() { dyn_array arr; int i; /* initialize array */ arr.size = 0; arr.elements = calloc(1, sizeof(*arr.elements)); arr.cap = 1; /* room for 1 element */ /* expand by 5 more elements */ arr.elements = realloc(arr.elements, (5 + arr.cap)*sizeof(*arr.elements)); if (arr.elements != NULL) arr.cap += 5; /* increase capacity */ /* add an element and increase size */ if (arr.size < arr.cap) { arr.elements[arr.size] = 50; /* add element to array */ arr.size++; } else printf("Need to expand array."); /* display array elements */ for (i = 0; i < arr.cap; i++) printf("Element %d: %d\n", i, arr.elements[ i ]); return 0; }

Управление указателем файла

В stdio.h есть функции для управления расположением указателя файла в двоичном файле:
ftell(fp) Возвращает значение типа long int, соответствующее позиции указателя файла fp в количестве байтов от начала файла.
fseek(fp, num_bytes, from_pos) Перемещает позицию указателя файла fp на num_bytes байтов относительно позиции from_pos, которая может быть одной из следующих констант:
- SEEK_SET начало файла
- SEEK_CUR текущая позиция
- SEEK_END конец файла
#include <stdio.h> #include <string.h> typedef struct { int id; char name[20]; } item; int main() { FILE *fptr; item first, second, secondf; // Заполнение данных first.id = 10276; strcpy(first.name, "Widget"); second.id = 11786; strcpy(second.name, "Gadget"); // Закидывание в файл fptr = fopen("info.dat", "wb"); fwrite(&first, 1, sizeof(first), fptr); fwrite(&second, 1, sizeof(second), fptr); fclose(fptr); // Читает с файла fptr = fopen("info.dat", "rb"); // Перемещается на второй элемент для чтения fseek(fptr, 1*sizeof(item), SEEK_SET); fread(&secondf, 1, sizeof(item), fptr); // Вывод того, что прочитал printf("%d %s\n", secondf.id, secondf.name); fclose(fptr); return 0; }
Эта программа записала в файл две записи об элементе.
Чтобы прочитать только вторую запись,
fseek() переместила указатель файла на
1 * sizeof(item) байт от начала файла.
Например, если вы хотите переместить указатель на четвертую запись, вы переместитесь к 3 * sizeof (item) с начала файла (SEEK_SET).

Отлавливаем ошибки

Использование exit во избежание сбоя программы является хорошей практикой, поскольку он закрывает все открытые файловые соединения и процессы.
Используйте errno, perror() и strerror()
для выявления ошибок с помощью кодов ошибок.
Вы можете вернуть любое значение с помощью оператора выхода, но обычно 0 для успеха и -1 для неудачи.
Ещё часто используются предопределенные макросы stdlib.h EXIT_SUCCESS и EXIT_FAILURE.
#include <stdio.h> #include <stdlib.h> int main() { int x = 10; int y = 0; if (y != 0) printf("x / y = %d", x/y); else { printf("Divisor is 0. Program exiting."); exit(EXIT_FAILURE); } return 0; }
Некоторые библиотечные функции, такие как fopen(),
устанавливают код ошибки, когда они не выполняются должным образом.
Код ошибки устанавливается в глобальной переменной с именем errno, которая определена в заголовочном файле errno.h. При использовании errno вы должны установить его в 0 перед вызовом библиотечной функции.
Чтобы вывести код ошибки, хранящийся в errno, вы используете fprintf для печати в поток файлов stderr, стандартный вывод ошибок на экран.

Использование stderr является условием и хорошей практикой программирования. Вы можете вывести errno другими способами, но будет легче отслеживать обработку исключений, если вы будете использовать stderr только для сообщений об ошибках.
Чтобы использовать errno, вам нужно объявить его с помощью оператора extern int errno; в верхней части вашей программы (или вы можете включить файл заголовка errno.h).
#include <stdio.h> #include <stdlib.h> extern int errno; int main() { FILE *fptr; errno = 0; fptr = fopen("c:\\nonexistantfile.txt", "r"); if (fptr == NULL) { fprintf(stderr, "Error opening file. Error code: %d\n", errno); exit(EXIT_FAILURE); } fclose(fptr); return 0; }