- •Передачу параметров в функцию по значению, а не по ссылке (при этом передача по ссылке эмулируется с помощью указателей);
- •Области действия имён; (область видимости переменной).
- •Достоинства:
- •Представление целых чисел в эвм
- •Основные типы данных, операции над ними.
- •Операции
- •Преобразование типов
- •Особенности операций для вещественных чисел
- •3.1. Операторы и блоки.
- •3.2. Оператор if – else
- •3.3. Конструкция else-if.
- •3.4. Оператор switch
- •3.5. Циклы while и for
- •3.6. Цикл do-while
- •3.7. Операторы break и continue
- •3.8. Оператор goto и метки
- •3.9. Оператор return
- •Инвариант
- •Указатели
- •Массивы
- •Связь между указателями и массивами
- •Представление в эвм
- •Создание указателя на массив
- •Инициализация массивов
- •Операции над указателями
- •Замечание! 2 указателя нельзя суммировать, но можно прибавлять константу. Сравнивать допустимо только с указателями того же типа или с null
- •Метод барьера в линейном поиске
- •Метод барьера при быстрой сортировке массива
- •Сортировка методом вставки. В отсортированной части массива последний элемент – барьер.
- •Процедуры
- •Локальные и глобальные переменные
- •Локальные переменные
- •Глобальные переменные
- •Средний и наихудший случай
- •Дополнительно (то же самое)
- •Анализ эффективности алгоритмов не должен зависеть от:
- •Временная сложность алгоритма
- •Некоторые свойства временной сложности алгоритма (функции f(n) )
- •Характеристики рекурсии
- •Виды рекурсии
- •Когда не нужно применять рекурсию
- •Применение эвристик.
- •Метод ветвей и границ (доп. Из Wikipedia)
- •Алгоритм Неймана.
- •Линейный конгруэнтный метод
- •Выбор параметров, выбор модуля и множителя.
- •Сдвиг на несколько символов: Если не совпадает , то сдвигаем образ вправо до последнего его стоп-символа. Если «стоп-символа» вообще нет в образе, то образ смещается за этот символ.
- •Вопросы на экзамен по информатике:
- •Перевести отрицательное целое число (он любое может назвать) в дополнительный код.
- •Есть ли смысл применять метод барьера в поиске подстроки в строке?
- •Задачи на экзамене:
- •Задача о Ханойских башнях
- •Бинарный поиск элемента в массиве
- •Сумма цифр в числе
- •Число различных элементов в символьном массиве
- •Сгенерировать все перестановки в целочисленном массиве (Билет 1).
- •Функция, возвращающая I и j такие, чтобы сумма эл-тов в I-ой строке равнялась сумме в j-ом столбце.
- •Есть одномерный массив целых чисел и нужно построить функцию, получающую на вход вещественное число X и возвращающую индекс элемента, который ближе всего к этому числу.
- •Функция strcpy (char *s1, char *s2) , билет 12.
- •Реализация strcat(); Билет 7.
- •Билет 5. Функция, выдаёт частное и остаток от деления X на y, нельзя пользоваться / и % .
- •Метод генерации случайной перестановки ( Тасование Фишера-Йетса).(не ок)
Инициализация массивов
Общая форма инициализации массива аналогична инициализации переменной:
тип имя_массива[размер1]...[размер№] = {список_значений};
Пример для одномерного массива В следующем примере массив целых из 10 элементов инициализируется числами от 1 до 10:
int i[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Здесь элементу i[0] присваивается 1, a i[9] — 10.
Так же можно задать массив переменной длины с помощью функции: void f(int dim)
{
char str[dim]; /* символьный массив переменной длины */
/* ... */
} Здесь размер массива str определяется значением переменной dim, которая передается в функцию f() как параметр. Таким образом, при каждом вызове f() создается массив str разной длины.
Операции над указателями
Оператор & — это унарный оператор, возвращающий адрес своего операнда. Например, оператор m = &count; присваивает переменной m адрес переменной count. Адрес — это номер первого байта участка памяти, в котором хранится переменная. Адрес и значение переменной — это совершенно разные понятия. Оператор & можно представить себе как оператор, возвращающий адрес объекта. Оператор * — это унарный оператор, возвращающий значение переменной, расположенной по указанному адресу. Например, если m содержит адрес переменной count, то оператор
q = *m;
присваивает переменной q значение переменной count. Замечание: *(&count)=count и &(*m)=m Присваивание указателей int x = 99; |
int *p1, *p2; |
| оба указателя (p1 и р2) ссылаются на х.
p1 = &x; |
p2 = p1; |
Унарные
операции ++ и –
Е
сли
указатель связан с типом char,
то при выполнении операций ++ -- его
числовое значение изменяется на 1. Если
int
– на 2, float
и long
– на 4. Т.о., при изменении указателя на
1, указатель переходит «к началу»
следующего или предыдущего поля той
длины, которая определяется типом.
Унарные операции ++ -- и * имеют одинаковый приоритет. Сравнивать указатели допустимо только с другими указателями того же типа или с константой NULL, обозначающей значение условного нулевого адреса.
Замечание! 2 указателя нельзя суммировать, но можно прибавлять константу. Сравнивать допустимо только с указателями того же типа или с null
Связь между массивами и указателями Указатели и массивы тесно связаны друг с другом. В языке С существуют два метода обращения к элементу массива: адресная арифметика и индексация массива. Стандартная запись массивов с индексами наглядна и удобна в использовании, однако с помощью адресной арифметики иногда удается сократить время доступа к элементам массива. Имя массива без индекса — это указатель на первый элемент массива. Рассмотрим, например, следующий массив:
char p[10];
Следующие два выражения идентичны:
p
&p[0]
Выражение p == &p[0] принимает значение ИСТИНА, потому что адрес 1-го элемента массива — это то же самое, что и адрес массива.
Как уже указывалось, имя массива без индекса представляет собой указатель. И наоборот, указатель можно индексировать как массив. Рассмотрим следующий фрагмент программы:
int *p, i[10];
p = i;
p[5] = 100; /* в присваивании используется индекс */
*(p+5) = 100; /* в присвоении используется адресная арифметика */
Оба оператора присваивания заносят число 100 в 6-й элемент массива i. Первый из них индексирует указатель p, во втором применяются правила адресной арифметики. В обоих случаях получается один и тот же результат.
Можно также индексировать указатели на многомерные массивы. Например, если а — это указатель на двухмерный массив целых размерностью 10×10, то следующие два выражения эквивалентны:
а &a[0][0] Более того, к элементу (0,4) можно обратиться двумя способами: либо указав индексы массива: а[0][4], либо с помощью указателя: *((int*)а+4). Аналогично для элемента (1,2): а[1][2] или *((int*)а+12). В общем виде для двухмерного массива справедлива следующая формула:
a[j][k] эквивалентно *((базовый_тип*)а+(j*длина_строки)+k) |
Массив указателей
Как и объекты любых других типов, указатели могут быть собраны в массив. В следующем операторе объявлен массив из 10 указателей на объекты типа int:
int *x[10];
Для присвоения, например, адреса переменной var третьему элементу массива указателей, необходимо написать:
x[2] = &var;
В результате этой операции, выражение *x[2] принимает то же значение, что и var.
Для передачи массива указателей в функцию используется тот же метод, что и для любого другого массива: имя массива без индекса записывается как формальный параметр функции. Например, следующая функция может принять массив x в качестве аргумента:
void display_array(int *q[])
{
int t;
for(t=0; t<10; t++)
printf("%d ", *q[t]);
}
Необходимо помнить, что q — это не указатель на целые, а указатель на массив указателей на целые. Поэтому параметр q нужно объявить как массив указателей на целые. Нельзя объявить q просто как указатель на целые, потому что он представляет собой указатель на указатель.
Массивы указателей часто используются при работе со строками. Например, можно написать функцию, выводящую нужную строку с сообщением об ошибке по индексу num:
void syntax_error(int num)
{
static char *err[] = {
"Нельзя открыть файл\n",
"Ошибка при чтении\n",
"Ошибка при записи\n",
"Некачественный носитель\n"
};
printf("%s", err[num]);
}
Массив err содержит указатели на строки с сообщениями об ошибках. Здесь строковые константы в выражении инициализации создают указатели на строки. Аргументом функции printf() служит один из указателей массива err, который в соответствии с индексом num указывает на нужную строку с сообщением об ошибке. Например, если в функцию syntax_error() передается num со значением 2, то выводится сообщение «Ошибка при записи».
Билет 6. Метод барьера.
Задача поиска – наиболее встречающаяся в программировании. Чтобы упростить поиск и избежать проверки конца области, в которой происходит поиск, придуман метод барьеров. Его идея заключается в том, что искомый элемент ставится в конец области поиска, что гарантирует наличие искомого элемента, а также при его не нахождении выход из поиска. По тому, что искомый элемент находится в конце области поиска, можно определить, что элемент не найден.
