23 апреля
Поиск элемента в упорядоченной матрице

В матрице строки и столбцы отсортированы по возрастанию. Нужно найти позиции некоторого элемента, в примере это 100.

\( \begin{matrix} 60 & 64 & 66 & 67 & 71 & 75 & 76 & 77 & 81 & 85 \\ 62 & 70 & 72 & 73 & 77 & 81 & 85 & 89 & 90 & 93 \\ 63 & 71 & 73 & 75 & 79 & 82 & 88 & 93 & 96 & 97 \\ 63 & 81 & 83 & 84 & 86 & 89 & 92 & 96 & 98 & \bf{100} \\ 72 & 84 & 85 & 87 & 89 & 90 & 94 & 97 & 102 & 106 \\ 78 & 85 & 86 & 91 & 94 & 97 & \bf{100} & 101 & 103 & 110 \\ 87 & 90 & 94 & 96 & \bf{100} & 101 & 104 & 108 & 111 & 114 \\ 90 & \bf{100} & 101 & 105 & 106 & 110 & 111 & 113 & 116 & 120 \\ 94 & 103 & 106 & 110 & 111 & 114 & 117 & 121 & 122 & 125 \\ 95 & 111 & 115 & 117 & 119 & 122 & 125 & 127 & 128 & 130 \end{matrix} \)

Число 100 находится в позициях (если считать индексы с нуля): (3, 9), (5, 6), (6, 4) и (7, 1). Как решить такую задачу?

Читать далее →
§ 13. Препроцессор

§ 13.1 Вставка содержимого

Мы уже пользовались разными директивами препроцессора. Даже в самом первом примере была одна. Рассмотрим самое главное (не будем рассматривать диграфы и триграфы).

Директива #include <...> включает содержимое заголовочного файла в ваш файл. Угловые скобки нужны для включения стандартных заголовочных файлов, кавычки — ваших собственных и библиотечных.

#include <stdio.h>  // Стандартные заголовочные файлы.
#include "my_lib.h" // Заголовочные файлы библиотек и проекта.

Читать далее →
§ 12. Побитовые операторы

Побитовые операторы используются для манипуляции отдельными битами числа или всеми сразу. Битовые маски применяются для кодирования параметров устройств и функций, для работы с IP-адресами и так далее.

Побитовый сдвиг влево: все биты сдвигаются влево, самый левый бит теряется, справа приписывается 0. Эквивалентно умножению на 2.

unsigned short a = 1093;        // 00000100 01000101 (1093)
unsigned short result = a << 1; // 00001000 10001010 (2186)

Побитовый сдвиг вправо: все биты сдвигаются вправо, самый правый бит теряется, слева приписывается 0. Эквивалентно делению на 2.

Читать далее →
§ 11. Классы памяти

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

1. Все переменные, которые вы просто объявляете и используете внутри функций, являются автоматическими (стековыми). Можно (но не нужно, потому что оно подразумевается) писать слово auto (в языке C++ с некоторых пор это ключевое слово стали использовать по-новому).

auto int foo = 0;

Примечание. В последних стандартах языка C++ слово auto утратило прежний смысл и теперь означает совсем другое.

Такие переменные хранятся на стеке (его размер небольшой), время жизни ограничено текущим блоком (говоря по-простому, фигурными скобками).

Фигурные скобки можно расставлять не только в конструкциях типа if или for, а в любых местах функции. Тогда переменная, объявленная в таком блоке, также будет ограничена его рамками.

Читать далее →
§ 10. Работа с файлами

§ 10.1 Режимы работы и основы

Чтобы работать с файлами, нужно создать файловый дескриптор (указатель на FILE). С помощью функции fopen() откроем файл, указав путь к нему и режим (не забудем проверить результат на равенство NULL), поработаем с ним и закроем с помощью fclose().

FILE *file = fopen("myfile.txt""w+"); // Открываем файл.
if (file == NULL)
{
    // Ошибка. Принимаем меры.
}
// Работаем с файлом.
fclose(file); // Закрываем файл.

Читать далее →
§ 9. Структуры, битовые поля и объединения

§ 9.1 Структуры

Структура — это общее имя для набора переменных. Если переменная — это тарелка, то структура — это поднос с тарелками.

struct Point
{
    int x;
    int y;
};

Переменные одного типа можно объявлять вместе. Давайте создадим один экземпляр (назовём его point), а затем заполним поля x и y (используя оператор точка .).

struct Point
{
    int x, y;
};
 
int main()
{
    struct Point point;
    point.x = 0;
    point.y = 0;
}

Читать далее →
§ 8. Строки

§ 8.1 Массивы символов

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

#define SIZE 16u
char string1[SIZE] = "Hello, world!"// Необязательная инициализация.
H e l l o ,   w o r l d ! \0

Строку завершает нулевой символ (\0), за ним (если строка занимает не весь буфер) идёт мусор.

Динамические строки создаются по аналогии с массивами.

size_t size = 16u;
char* string2 = malloc(sizeof(char) * size2); // sizeof(char) всегда равно 1.
strcpy(string2, "Hello, world!");

Читать далее →
§ 7. Массивы и указатели

§ 7.1 Указатели

Эти два понятия — массивы и указатели — неразрывно связаны между собой.

Указатель — это переменная для хранения адреса другой переменной. Его объявление содержит тип и знак *. Чтобы узнать адрес переменной, нужно указать знак амперсанд и её имя: &foo. Чтобы работать со значением, записанным по адресу в указателе, воспользуемся операцией, которая называется разыменование указателя: *ptr.

int foo = 1;
int *ptr = &foo;            // Адрес переменной сохраняем в указатель.
printf("%d %d", foo, *ptr); // Прямое и косвенное обращение.

Как будет выглядеть ввод чисел при прямом и косвенном обращении?

scanf("%d", &foo);
scanf("%d", ptr); // ptr уже адрес, знак & не нужен.

Читать далее →
§ 6. Функции

§ 6.1 Объявление, определение, вызов

До этого момента мы только пользовались уже готовыми функциями. Создадим свою. Она будет называться sqr(). В круглых скобках через запятую указываются аргументы функции и их типы. Перед функцией указывается тип возвращаемого значения. Тело (в нашем случае содержащее одно выражение, вычисляющее и возвращающее квадрат числа) помещается в фигурные скобки.

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

#include <stdio.h>
 
int sqr(int x)
{
    return x * x;
}
 
int main()
{
    int result = sqr(5);
    printf("%d", result);
    return 0;
}

Читать далее →
3
2 1
© MMXIMMXX
Светлая тема / тёмная тема