Скачать презентацию C SELECTED TOPICS COURSE OF LECTURES LECTURE Скачать презентацию C SELECTED TOPICS COURSE OF LECTURES LECTURE

ba8f354f6c147e649bdb042286b1e414.ppt

  • Количество слайдов: 82

C SELECTED TOPICS. COURSE OF LECTURES C SELECTED TOPICS. COURSE OF LECTURES

LECTURE #1 LECTURE #1

Введение Язык Си был разработан в начале 1970 х годов для упрощения переноса операционной Введение Язык Си был разработан в начале 1970 х годов для упрощения переноса операционной системы UNIX на разные архитектуры. За прошедшие почти 40 лет было опубликовано несколько стандартов языка. Наиболее значимые из них: ●K&R C - первое описание языка Си от авторов языка: Кернигана и Ритчи. ●ANSI C - стандарт американского института стандартов ●C 99 - стандарт ISO/IEC 9899: 1999

Компиляция Большинство реализаций языка Си - компиляторы. Компиляция программ происходит в три стадии: обработка Компиляция Большинство реализаций языка Си - компиляторы. Компиляция программ происходит в три стадии: обработка препроцессором ●компиляция в объектный код ●компоновка (сборка) всех модулей в выполняемый файл или разделяемую библиотеку ●

Препроцессор выполняет предварительную обработку текста программы. В его функции входит: ●замена констант на значения Препроцессор выполняет предварительную обработку текста программы. В его функции входит: ●замена констант на значения и разворачивание макросов ●обработка директив условной компиляции ●включение в текст внешних файлов После обработки получается текст, который может быть скомпилирован в объектный файл без использования каких либо внешних файлов. Посмотреть результат обработки препроцессором можно, например, командой gcc -E main. c -o main. out. c (Файл main. out. c будет содержать результат работы препроцессора)

Компиляция В процессе компиляции файл на языке Си преобразуется в объектный файл, содержащий машинный Компиляция В процессе компиляции файл на языке Си преобразуется в объектный файл, содержащий машинный код, таблицу содержащихся в файле символов и таблицу необходимых этому файлу внешних символов.

Компоновка В процессе компоновки один или несколько объектных файлов преобразуются в выполняемый образ. На Компоновка В процессе компоновки один или несколько объектных файлов преобразуются в выполняемый образ. На этом этапе происходит разрешение ссылок на внешние символы.

В Си допустимыми символами являются латинские заглавные и строчные буквы, цифры и следующие знаки В Си допустимыми символами являются латинские заглавные и строчные буквы, цифры и следующие знаки препинания: ● % процент ● Алфавит языка ^ амперсанд ● ! восклицательный знак ● ( ) { } [ ] круглые, фигурные и квадратные скобки ● . точка , запятая ● ; точка с запятой ● ^ крышка ● | вертикальная прямая ● ? вопросительный знак ● : двоеточие ● ● ● ~ тильда + плюс ● ' %%"%% одинарные и двойные кавычки ● ● - минус ● * умножение ● / прямая и обратная дробь ● = равно # решетка ● _ подчеркивание Пробельными символами считаются: пробел, табуляция, перевод строки. Такие символы игнорируются компилятором.

Комментарии Коментарий начинается с /* и заканчивается */. В Си нет вложенных коментариев. Комментарии Коментарий начинается с /* и заканчивается */. В Си нет вложенных коментариев.

Служебные слова Следующие слова являются ключевыми и не рекомендуется использовать их для обозначения имен Служебные слова Следующие слова являются ключевыми и не рекомендуется использовать их для обозначения имен функций и переменных. ● extern ● register ● static ● break ● char ● short ● case ● int ● continue ● long ● default ● float ● double ● else enum ● ● for struct ● goto ● ● if ● return ● switch ● while ● sizeof ● typedef ● ● ● union signed unsigned void volatile

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

Простые типы ●void - Простые типы ●void - "пустой" тип (используется как возвращаемый тип в создания указателей на нетипизированную память) ●char - целое число размерностью 1 байт ●int - целое число процедурах и для С типом int могут употребляться модификаторы sort и long, например: ●short int (или просто short) - целое число меньшей размерности, чем int ●long int (или просто long) - целое число большей размерности, чем int Со всеми вышепреведенными типами кроме void могут употребляться модификаторы signed и unsigned, например: ●signed short int (или просто short) ●unsigned int ●unsigned long int (или просто unsigned long) ●unsigned char

Константы Целочисленные константы представляются в виде: ● 123 - десятичное число 123 ● 077 Константы Целочисленные константы представляются в виде: ● 123 - десятичное число 123 ● 077 - восьмеричное число 77 (начинаются с 0) ● 0 x. FF - шестнадцатиричное число FF (начинаются с 0 x) ● 123 L - буква L обозначает приведение к типу long ● 123 U - буква U обозначает беззнаковый тип Вещественные: ● 1. 23 e-5 ● 1. 23 e 3 f Буква f в конце означает тип float (по умолчанию вещественные константы имеют тип double)

Строки: ● Строки: ●"Hello, Worldn" ●"x 20" Символы: ●'c' ●'t' ●'\' В строковых и символьных константах обратная косая имеет особое значение - с ее помощью вставляются управляющие символы. ●n - перевод строки ●t - табуляция ●r - возврат каретки ●x<число> - символ с указанным шестнадцатиричным кодом ●<число> - символ с указанным восьмеричным кодом ●\ обратная дробь

Описание переменных Синтаксис: тип идентификатор [ = выражение][, идентификатор [ = выражение]]. . . Описание переменных Синтаксис: тип идентификатор [ = выражение][, идентификатор [ = выражение]]. . . ; int a = 1; int a = 1, b, c = 2; Модификаторы: ●const - неизменяемая переменная ●register - помещать переменную в регистр процессора (игнорируется всеми современными компиляторами) ●volatile - может изменяться внешними процессами () ●static - статическая переменная ●auto - локальная переменная (обычно не используется, т. к. все переменные без модификаторов относятся к группе auto)

Приоритеты и ассоциативность операций ●() [] ->. (скобки, индекс массива, получение поля из структуры Приоритеты и ассоциативность операций ●() [] ->. (скобки, индекс массива, получение поля из структуры и получение поля из структуры с разыменованием указателя) ●Унарные (справа налево): ! ~* & sizeof (type) ++ -- (Логическое и битовое отрицание, смена знака, разыменование, взятие указателя, размер, инкремент и декремент) ●Бинарные арифметические: * / % (умножение, деление, остаток) ●Бинарные арифметические + - (сложение и вычитание) ●Сдвиг: << >> (побитовый сдвиг) ●Сравнение: < <= > >= ●Сравнение: == != ●Битовая: & (и) ●Битовая: ^ (исключающее или) ●Битовая: | (или) ●Логическая: && (и) ●Логическая: || (или) ●Тернарная (справа налево): ? : (условие ? выражение 1 : выражение 2) ●Операции с присваиванием (справа налево): = += -= *= /= &= |= ^= <<= >>=

Операторы в Си разделяются символом точка с запятой. Для объединения операторов в блок используются Операторы в Си разделяются символом точка с запятой. Для объединения операторов в блок используются фигурные скобки.

Присваивание Синтаксис: левое значение = правое значение a = 2; b = (a + Присваивание Синтаксис: левое значение = правое значение a = 2; b = (a + 2)*3;

Приведение типа Для преобразования типа можно использовать его имя в круглых скобках перед выражением: Приведение типа Для преобразования типа можно использовать его имя в круглых скобках перед выражением: double x = 1. 3; int a = (int)(x+0. 5); /* правильное округление положительного вещественного */

Операция “запятая” Через запятую можно указать несколько выражений. Результатом операции запятая всегда будет значение Операция “запятая” Через запятую можно указать несколько выражений. Результатом операции запятая всегда будет значение правого выражения. int a = 1, 2; /* a == 2 */

if Условный оператор имеет две формы: if (условие) оператор1 else оператор2 if(1 < 2) if Условный оператор имеет две формы: if (условие) оператор1 else оператор2 if(1 < 2) { // операторы } else { // операторы }

while и do-while Циклы while и do-while Циклы "пока" с пред и постусловием. while(условие) оператор do оператор while(условие)

for Цикл for Цикл "для" for(действие до цикла; условие выполнения цикла; действие в конце каждой итерации) оператор for(i = 0; i < 10; i = i + 1) printf("%d", i);

goto Оператор перехода к метке. Синтаксис: label 1: . . goto label 1; goto Оператор перехода к метке. Синтаксис: label 1: . . goto label 1;

switch Оператор выбора позволяет выполнять различные операторы в зависимости от значения выражения. Синтаксис: switch(выражение) switch Оператор выбора позволяет выполнять различные операторы в зависимости от значения выражения. Синтаксис: switch(выражение) { case значение 1: case значение 2: операторы break; case значение 3: операторы break; default: операторы break; }

break, continue Оператор break прекращает выполнение цикла или оператора выбора. Оператор continue вызывает досрочное break, continue Оператор break прекращает выполнение цикла или оператора выбора. Оператор continue вызывает досрочное завершение итерации.

Описание функций Синтаксис: тип идентификатор(список параметров) блок операторов Если в качестве последнего параметра указано Описание функций Синтаксис: тип идентификатор(список параметров) блок операторов Если в качестве последнего параметра указано троеточие, функция может принимать произвольное количество параметров. При этом у функции должен быть хотя бы один обязательный параметр. int add(int a, int b) { return a + b; } int print(char *format, . . . ) { /*. . . */ }

Программа на языке Си должна содержать как минимум 1 функцию с именем main. int Программа на языке Си должна содержать как минимум 1 функцию с именем main. int main(int argc, char *argv[]) { return 0; } Выполнение программы начинается именно с этой функции. В качестве параметров она принимает массив аргуметнов, переданных в командной строке и возвращает целое значение, содержащее код ошибки (0 означает, что ошибки нет) int main(int argc, char *argv[]) { if(argc < 4) { /* слишком мало аргументов */ return 1; } /*. . . */ return 0; }

LECTURE #2 LECTURE #2

Массивы Синтаксис: тип имя-переменной[размер массива] ●тип имя-переменной[] ●тип *имя-переменной ● Индексы массива всегда начинаются Массивы Синтаксис: тип имя-переменной[размер массива] ●тип имя-переменной[] ●тип *имя-переменной ● Индексы массива всегда начинаются с 0. Например: int a[10]; /* массив из 10 элементов от 0 до 9 */ a[5] = 3; /* присвоить 6 му (с индексом 5) элементу значение 3 */

Важно запомнить, что: ●язык Си обычно не предоставляет средств контроля выхода индекса за пределы Важно запомнить, что: ●язык Си обычно не предоставляет средств контроля выхода индекса за пределы массива. ●использование имени массива без операции взятия его элемента означает использование указателя на 1 й элемент массива.

Составные типы Структура: struct [имя-структуры] { список полей } Например: struct list_item { int Составные типы Структура: struct [имя-структуры] { список полей } Например: struct list_item { int value; struct list_item *next; };

Объединение: union [имя] { список полей } Перечисление: enum [имя] { список значений } Объединение: union [имя] { список полей } Перечисление: enum [имя] { список значений }

Например: struct multivalue { enum { VALUE_INT, VALUE_CHAR, VALUE_DOUBLE } type; union { int Например: struct multivalue { enum { VALUE_INT, VALUE_CHAR, VALUE_DOUBLE } type; union { int ival; char cval; double dval; } value; };

Определение типа при помощи typedef: typedef <описание типа> <имя типа> Например: typedef struct list_item Определение типа при помощи typedef: typedef <описание типа> <имя типа> Например: typedef struct list_item { int value; struct list_item *next; } list_item_t; После такого описания типа можно вводить переменные двумя способами: ●struct list_item *var 1; ●list_item_t *var 2;

LECTURE #3 LECTURE #3

Указатели Операция взятия указателя: &<выражение> Операция разыменования указателя: *<выражение> Тип-указатель: тип* Например: int a Указатели Операция взятия указателя: &<выражение> Операция разыменования указателя: *<выражение> Тип-указатель: тип* Например: int a = 5; int *ptr_to_a = &a; *ptr_to_a = 1; printf("%dn", a); /* напечатает 1 */

Адрессная арифметика С указателями допустимы операции сложения с целым и вычитания одного указателя из Адрессная арифметика С указателями допустимы операции сложения с целым и вычитания одного указателя из другого: Например: int a[10]; int *ptr = &a[0]; *(ptr+1) = 3; /* поместить 3 во 2 й элемент массива */ int diff = &a[5] - ptr; /* 5 элементов разницы */

Важно запомнить, что: ●операции сложения и вычитания учитывают размер типа, на который ссылается указатель. Важно запомнить, что: ●операции сложения и вычитания учитывают размер типа, на который ссылается указатель. Например, ptr+1 в предыдущем примере увеличивает ptr на размер типа int (обычно 4 байта) ●эти операции не применимы к типу void*, т. к. невозможно узнать размер значения, на которое он ссылается.

массивы указателей и указатель на массив char *array_of_ptrs[]; /* массив указателей на char */ массивы указателей и указатель на массив char *array_of_ptrs[]; /* массив указателей на char */ char (*ptr_to_array)[]; /* указатель на массив char */ Указатель на функцию: тип (*имя)(параметры) Например: char* (*ptr_to_func)(char, int); /* описывает указатель на функцию с 2 мя параметрами типа char и int и возвращающую значение типа char* */

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

Подключение файлов Синтаксис: #include <файл> #include Подключение файлов Синтаксис: #include <файл> #include "файл" Если файл указан в угловых скобках, он ищется в директориях системы/компилятора. Иначе в текущей директории.

LECTURE #4 LECTURE #4

Константы Синтаксис: #define ИМЯ ЗНАЧЕНИЕ #define ИМЯ(параметры) ЗНАЧЕНИЕ Например, #define DEBUG #define PI 3. Константы Синтаксис: #define ИМЯ ЗНАЧЕНИЕ #define ИМЯ(параметры) ЗНАЧЕНИЕ Например, #define DEBUG #define PI 3. 14159 #define ADD(A, B) ((A)+(B)) #define PRINT(A) printf(A) #define FIELD(B, A) ((B)->m_## A) #ifdef DEBUG float a = PI; float b = ADD(a, 5); PRINT(("%fn", b));

Обратите внимание на двойные скобки в PRINT(( Обратите внимание на двойные скобки в PRINT(("%fn", b)) для передачи списка параметров и на операцию ## в определении FIELD, которая соединяет строки. Например использование FIELD(m, next) будет раскрыто препроцессором как ((m)->m_next).

Условная компиляция Синтаксис: #ifdef ИМЯ текст-1 #endif #ifdef ИМЯ текст-1 #else текст-2 #endif Оставляет Условная компиляция Синтаксис: #ifdef ИМЯ текст-1 #endif #ifdef ИМЯ текст-1 #else текст-2 #endif Оставляет текст-1 если константа ИМЯ определена при помощи #define и текст-2 в противном случае.

Организация модулей Компиляция программы на Си происходит в три этапа: - обработка текста препроцессором Организация модулей Компиляция программы на Си происходит в три этапа: - обработка текста препроцессором - компиляция каждого файла с исходным текстом - сборка скомпилированных файлов в один (компоновка) Препроцессор позволяет не усложнять язык Си средствами работы с модулями и их подключением. Обычно реализация модуля находится в файле с расширением. c, а прототипы, константы, описания типов, которые могут потребоваться для других модулей - в файлах с расширением. h. Таким образом, если модуль А использует функции модуля Б, то достаточно подключить файл Б. h при помощи директивы #include и после обработки получится файл, пригодный для компиляции, т. к. содержимое Б. h c прототипом функций будет подставлено вместо #include. Обычно определения модуля А. с выносятся в одноимённый hфайл, однако ничто не запрещает объединить определения модулей a. c и b. c в файл my-headers. h или разделить описания модуля a. c на файлы a 1. h и a 2. h.

LECTURE #5 LECTURE #5

Основные функции ввода-вывода scanf int scanf(const char *format, . . . ) Выполняет чтение Основные функции ввода-вывода scanf int scanf(const char *format, . . . ) Выполняет чтение данных со стандартного потока ввода (по умолчанию клавиатура). int sscanf(const char *buffer, const char *format, . . . ) Выполняет чтение данных из переменной buffer. int fscanf(FILE *stream, const char *format, . . . ) Выполняет чтение данных из файла stream. Возвращает количество прочитанных элементов.

Параметр format - строка по которой функция будет интерпретировать остальные аргументы. ● Модификаторы ● Параметр format - строка по которой функция будет интерпретировать остальные аргументы. ● Модификаторы ● h - short (для форматов d, i, o, u, x, X, n) ● hh - char ● j - intmax_t ● l - long для форматов d, i, o, u, x, X, n; double для e, f, g; wchar_t для c и s ● L - long для форматов d, i, o, u, x, X, n; long double для e, f, g; wchar_t для c и s ● q - эквивалент L ● t - ptrdiff_t (для форматов d, i, o, u, x, X, n) ● z - size_t (для форматов d, i, o, u, x, X, n) ●

* Формат параметра *%-% * d - int * D - эквивалент ld * * Формат параметра *%-% * d - int * D - эквивалент ld * i - int (возможно в восьмеричной форме 0. . . или шестнадцатиричной 0 x. . . ) * o - восьмеричный unsigned int * u - unsigned int * x - шестнадцатиричный unsigned int * X - шестнадцатиричный unsigned int с большими буквами A-F * f - float * e - эквивалент f * g - эквивалент f * E - эквивалент f * a - эквивалент f * s - строка непробельных символов * c - char * [ - произвольное число перечисленных символов, например: %[^]0 -9 -] - все кроме ] цифр и -. * p - void* * n - int (количество разобраных символов)

printf int printf(const char *format, . . . ) Печатает форматированные аргументы на стандартный printf int printf(const char *format, . . . ) Печатает форматированные аргументы на стандартный вывод (консоль). int snprintf(char *buffer, size_t bufsize, const char *format, . . . ) Заполняет форматированными аргументами buffer размером bufsize. int fprintf(FILE *stream, const char *format, . . . ) Выводит форматированные аргументы в файл stream. Возвращает количество напечатанных символов.

* Флаги * # - альтернативная форма * для формата o - добавляет 0 * Флаги * # - альтернативная форма * для формата o - добавляет 0 вначало * для x и X - добавляет 0 x и 0 X вначало * a, A, f, F, e, E, g, G - всегда печатать точку * g, G - оставить ненужные нули * 0 - заполнять 0 до нужной длины * - - выравнивать по левому краю * + - всегда указывать знак числа * пробел - ставить пробел вместо знака + для положительных чисел * Ширина поля - количество символов для поля * Точность - после точки для вещественных чисел можно указать сколько символов из ширины поля выделить для вещественной части

* Размер * h - char * hh - short * l - long * Размер * h - char * hh - short * l - long или wchar_t * ll - long * L - long double * j - intmax_t * z - size_t * t - ptrdiff_t

* Тип * d, i - int * o, u, x, X - unsigned * Тип * d, i - int * o, u, x, X - unsigned int (напечатает в восьмеричной, десятичной или шестнадцатиричной форме) * e, E - вещественное число в нормальной записи * f, F - вещественное число в обычной записи * g, G - вещественное число в автоформате * a, A - вещественное в шестандцатиричном виде * c - char * s - заканчивающаяся нулевым символом строка char или wchar_t * p - void* * n - количество напечатанных символов (не требует соответствующего параметра после строки формата) * m - системное сообщение об ошибке (не требует соответствующего параметра после строки формата) *%-%

Например: #include <stdio. h> main() { int val, count; sscanf( Например: #include main() { int val, count; sscanf("123123", "%d%n", &val, &count); printf("Значение = %dn. Количество символов=%dn", val, count); }

Файлы Перед тем как выполнять чтение или запись файла, необходимо его открыть, а по Файлы Перед тем как выполнять чтение или запись файла, необходимо его открыть, а по окончании работы закрыть. Существует специальный тип переменных - файловые переменные. Операция открытия файла возвращает переменную данного типа, по которой операции чтения записи идентифицируют файл. - Открытие файла: нужно указать имя файла и режим в котором его нужно открыть (для чтения, для записи, как текст или как двоичные данные). Возвращает файловую переменную. - Операции чтения/записи: нужно указать файловую переменную, полученную при открытии и данные для записи или переменную, в которую необходимо прочитать данные - Закрытие файла: нужно передать файловую переменную.

fopen FILE *fopen(const char *path, const char *mode) Открывает файл path в режиме mode. fopen FILE *fopen(const char *path, const char *mode) Открывает файл path в режиме mode. Режим представлен как строка символов. Допустимы комбинации следующих значений: * r - для чтения * r+ - для чтения и записи. Указатель установлен в начало файла. * w - для записи. Очищает файл. * w+ - для чтения и записи. Очищает файл. * a - добавить в конец файла (для записи). Указатель установлен в конец файла. * a+ - для чтения и записи. Указатель чтения установлен в начало файла, записи - в конец. * b - открыть файл как двоичный, а не текстовой. Возвращает файловую переменную или NULL в случае ошибки.

fclose int fclose(FILE *fp) Закрыть файл. fprintf int fprintf(FILE *stream, const char *format, . fclose int fclose(FILE *fp) Закрыть файл. fprintf int fprintf(FILE *stream, const char *format, . . . ) Записать форматированные в текст данные в файл stream. (работает аналогично printf) fscanf int fscanf(FILE *stream, const char *format, . . . ) Читает данные из текстового файла stream. (работает аналогично scanf)

fwrite size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) Записать двоичные данные fwrite size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) Записать двоичные данные в файл. * ptr - указатель на переменную, которую нужно записать * size - размер элемента * nmemb - количество элементов (1 - если не массив или кол-во элементов в массиве) * stream - файловая переменная Возвращает количество записанных элементов. Например: int a = 1, b[2] = { 2, 3 }; r = fwrite(&a, sizeof(a), 1, f); /* вернет 1 в случае успешной записи */ r = fwrite(b, sizeof(int), 2, f); /* вернет 2 в случае успешной записи */

fread size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) Читать двоичные данные из fread size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) Читать двоичные данные из файла. * ptr - указатель на переменную, в которую нужно поместить прочитанные данные * size - размер элемента * nmemb - количество элементов (1 - если не массив или кол-во элементов в массиве) * stream - файловая переменная Возвращает количество прочитанных элементов Например: /*. . . */ int a, b[2]; r = fread(&a, sizeof(a), 1, f); /* вернет 1 в случае успешного прочтения */ r = fread(b, sizeof(int), 2, f); /* вернет 2 в случае успешного прочтения */

feof int feof(FILE *stream) Проверить конец файла. Возвращает 0 если файл stream еще не feof int feof(FILE *stream) Проверить конец файла. Возвращает 0 если файл stream еще не закончился.

Пример #include <stdio. h> int main() { FILE *binfile; FILE *txtfile; /* Запись текста Пример #include int main() { FILE *binfile; FILE *txtfile; /* Запись текста */ txtfile = fopen("test. txt", "w"); if(txtfile != NULL) { int a = 5; fprintf(txtfile, "%dn", a); fclose(txtfile); } else { perror("Не могу открыть файл test. txt для записи"); } /* Запись двоичных данных */ binfile = fopen("test. dat", "wb"); if(binfile != NULL) { int a = 5; fwrite(&a, sizeof(a), 1, binfile); fclose(binfile); } else { perror("Не могу открыть файл test. dat для записи"); }

/* * Чтение текста */ txtfile = fopen( /* * Чтение текста */ txtfile = fopen("test. txt", "r"); if(txtfile != NULL) { int a; fscanf(txtfile, "%d", &a); printf("a(txtfile) = %dn", a); fclose(txtfile); } else { perror("Не могу открыть файл test. txt для чтения"); } /* * Чтение двоичных данных */ binfile = fopen("test. dat", "rb"); if(binfile != NULL) { int a; fread(&a, sizeof(a), 1, binfile); printf("a(binfile) = %dn", a); fclose(binfile); } else { perror("Не могу открыть файл test. dat для чтения"); } return 0; }

LECTURE #6 LECTURE #6

Функции с переменным числом аргументов При помощи. . . можно определить функцию с переменным Функции с переменным числом аргументов При помощи. . . можно определить функцию с переменным числом аргументов. Троеточие всегда должно находиться в конце списка параметров. Например: int func(int count, . . . ); Для обработки переменного числа параметров существуют следующие средства: - тип va_list хранит информацию о состоянии извлечения аргументов функции из стека - функция va_start(va_list, последний именованный параметр) инициализирует процесс извлечения аргументов из стека, принимая первым аргументом переменную типа va_list, а вторым - последний именованный параметр. - макрос va_arg(va_list, тип) возвращает очередной параметр. Второй параметр - определение типа ожидаемого аргумента. - va_end(ap) завершает выборку аргументов из стека

* Параметр stub не используется, но необходим, т. к. для обработки переменного * числа * Параметр stub не используется, но необходим, т. к. для обработки переменного * числа параметров нужно отталкиваться от именованного параметра с известным * типом. (этот параметр не должен быть массивом, функциональным типом или * регистровым параметром) */ int print_strings(char stub, . . . ) { int count = 0; va_list ap; va_start(ap, stub); while(1) { char *s = va_arg(ap, char*); if(s == NULL) { break; } printf("%sn", s); count++; } va_end(ap); return count;

Строковые функции * char *strcpy(char *dest, const char *src); - копирование строки * char Строковые функции * char *strcpy(char *dest, const char *src); - копирование строки * char *strncpy(char *dest, const char *src, size_t n); - копирование строки с указанием максимального размера * char *strcat(char *dest, const char *src); - соединение строк * char *strncat(char *dest, const char *src, size_t n); - соединение строк с указанием максимального размера * int strcmp(const char *s 1, const char *s 2); - сравнение строк * int strncmp(const char *s 1, const char *s 2, size_t n); - сравнение строк с указанием максимального размера * int toupper(int c); - преобразование символа к верхнему регистру * int tolower(int c); - преобразование символа к нижнему регистру * char *strchr(const char *s, int c); - поиск первого вхождения символа * char *strrchr(const char *s, int c); - поиск последнего вхождения символа * char *strstr(const char *haystack, const char *needle); - поиск подстроки

* int isalnum(int c); - является ли символ цифрой или буквой * int isalpha(int * int isalnum(int c); - является ли символ цифрой или буквой * int isalpha(int c); - является ли символ буквой * int isascii(int c); - принадлежит ли символ к набору ASCII * int isblank(int c); - является ли символ непечатаемым * int iscntrl(int c); - является ли символ управляющим * int isdigit(int c); - является ли символ цифрой * int isgraph(int c); - является ли символ печатаемым * int islower(int c); - является ли символ строчной буквой * int isprint(int c); - является ли символ печатаемым или пробелом * int ispunct(int c); - является ли символ печатаемым, но не буквой или цифрой * int isspace(int c); - является ли символ пробельным * int isupper(int c); - является ли символ заглавной буквой * int isxdigit(int c); - является ли символ шестнадцатиричной цифрой

Функции работы с памятью * void *calloc(size_t nmemb, size_t size); - выделяет память * Функции работы с памятью * void *calloc(size_t nmemb, size_t size); - выделяет память * void *malloc(size_t size); - выделяет память * void free(void *ptr); - освобождает память * void *realloc(void *ptr, size_t size); - выделяет блок памяти нового размера и копирует в него содержимое старого блока, старый блок удаляется * void *memcpy(void *dest, const void *src, size_t n); - копирование * void *memmove(void *dest, const void *src, size_t n); - копирование с учетом возможного наложения * int memcmp(const void *s 1, const void *s 2, size_t n); - сравнение * void *memset(void *s, int c, size_t n); - заполнение памяти указанным значением

Функции работы с файлами * int printf(const char *format, . . . ); - Функции работы с файлами * int printf(const char *format, . . . ); - форматированная печать * int fprintf(FILE *stream, const char *format, . . . ); - форматированная печать в файл * int sprintf(char *str, const char *format, . . . ); - форматированная печать в буффер * int snprintf(char *str, size_t size, const char *format, . . . ); - форматированная печать в буффер с указанием размера буффера * int vprintf(const char *format, va_list ap); - форматированная печать списка аргументов * int vfprintf(FILE *stream, const char *format, va_list ap); - форматированная печать списка аргументов в файл * int vsprintf(char *str, const char *format, va_list ap); - форматированная печать списка аргументов в буффер * int vsnprintf(char *str, size_t size, const char *format, va_list ap); - форматированная печать списка аргументов в буффер с указанием размера буффера * FILE *fopen(const char *path, const char *mode); - открыть файл * FILE *freopen(const char *path, const char *mode, FILE *stream); - открыть файл и привязать его к файловой переменной stream * int fclose(FILE *fp); - закрыть файл

* void clearerr(FILE *stream); - очистить информацию об ошибке * int feof(FILE *stream); - * void clearerr(FILE *stream); - очистить информацию об ошибке * int feof(FILE *stream); - проверить конец файла * int ferror(FILE *stream); - получить последнюю ошибку с файлом * int fileno(FILE *stream); - получить системный файловый идентификатор * FILE *stdin; - стандартный ввод * FILE *stdout; - стандартный вывод * FILE *stderr; - стандартный вывод ошибок * int fflush(FILE *stream); - сбросить все данные на носитель * int fpurge(FILE *stream); - очистить все внутренние буфферы * size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); - читать из файла * size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream); записывать в файл

* int fseek(FILE *stream, long offset, int whence); - перемещение указателя файла * long * int fseek(FILE *stream, long offset, int whence); - перемещение указателя файла * long ftell(FILE *stream); - получить текущую позицию в файле * void rewind(FILE *stream); - перейти к началу файла * int fgetpos(FILE *stream, fpos_t *pos); - получить текущую позицию в файле * int fsetpos(FILE *stream, fpos_t *pos); - перемещение указателя файла * int fseeko(FILE *stream, off_t offset, int whence); - перемещение указателя файла * off_t ftello(FILE *stream); - получить текущую позицию в файле * char *tempnam(const char *dir, const char *pfx); - получить имя для временного файла * FILE *tmpfile(void); - создать и открыть временный файл * char *tmpnam(char *s); - получить имя для временного файла

* int fgetc(FILE *stream); - прочитать символ * char *fgets(char *s, int size, FILE * int fgetc(FILE *stream); - прочитать символ * char *fgets(char *s, int size, FILE *stream); - прочитать строку * int getc(FILE *stream); - прочитать символ * int getchar(void); - прочитать символ с stdin * char *gets(char *s); - прочитать строку с stdin * int ungetc(int c, FILE *stream); - положить символ обратно * int fputc(int c, FILE *stream); - записать символ * int fputs(const char *s, FILE *stream); - записать строку * int putc(int c, FILE *stream); - записать символ * int putchar(int c); - записать символ в stdout * int puts(const char *s); - записать строку в stdout

LECTURE #7 LECTURE #7

Функции работы с сетью * int socket(int domain, int type, int protocol); - создать Функции работы с сетью * int socket(int domain, int type, int protocol); - создать сокет * int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); - ассоциировать сокет с адресом * int listen(int sockfd, int backlog); - задать размер очереди для входящих соединений * int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); - соединиться с удаленной стороной * int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); - принять соединение * int shutdown(int s, int how); - завершить работу с сокетом * int close(int fd); - закрыть сокет * ssize_t recv(int s, void *buf, size_t len, int flags); - принять данные * ssize_t recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen); - принять данные и узнать адрес с которого они были посланы * ssize_t recvmsg(int s, struct msghdr *msg, int flags); - принять данные * ssize_t send(int s, const void *buf, size_t len, int flags); - послать данные * ssize_t sendto(int s, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); - послать данные на указанный адрес * ssize_t sendmsg(int s, const struct msghdr *msg, int flags); - послать данные

* ssize_t read(int fd, void *buf, size_t count); - принять данные * ssize_t write(int * ssize_t read(int fd, void *buf, size_t count); - принять данные * ssize_t write(int fd, const void *buf, size_t count); - послать данные * int getsockname(int s, struct sockaddr *name, socklen_t *namelen); получить имя сокета * int getpeername(int s, struct sockaddr *name, socklen_t *namelen); получить имя удаленной стороны * int fcntl(int fd, int cmd, . . . /* arg */ ); - управляющие функции * int ioctl(int d, int request, . . . ); - управляющие функции * int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); - получить информацию об адресе * void freeaddrinfo(struct addrinfo *res); - освободить структуру с информацией об адресе * int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags); - получить информацию об имени

Функции работы с процессами * pid_t fork(void); - создание нового процесса * int execve(const Функции работы с процессами * pid_t fork(void); - создание нового процесса * int execve(const char *filename, char *const argv[], char *const envp[]); выполнение файла * pid_t wait(int *status); - ждать завершения дочернего процесса * pid_t waitpid(pid_t pid, int *status, int options); - ждать завершения указанного дочернего процесса * int pipe(int pipefd[2]); - создать пару связанных дескрипторов вводавывода * FILE *popen(const char *command, const char *type); - запустить программу и перенаправить ее потоки ввода-вывода * int pclose(FILE *stream); - завершить программу, запущенную popen * int system(const char *command); - выполнить команду

LECTURE #8 LECTURE #8

POSIX-потоки ●pthread_create ●pthread_detach ●pthread_exit ●pthread_join pthread_mutex_init ●pthread_mutex_destroy ●pthread_mutex_lock ●pthread_mutex_timedlock ●pthread_mutex_trylock ●pthread_mutex_unlock ● POSIX-потоки ●pthread_create ●pthread_detach ●pthread_exit ●pthread_join pthread_mutex_init ●pthread_mutex_destroy ●pthread_mutex_lock ●pthread_mutex_timedlock ●pthread_mutex_trylock ●pthread_mutex_unlock ●

pthread_cond_init ●pthread_cond_destroy ●pthread_cond_signal ●pthread_cond_broadcast ●pthread_cond_wait ●pthread_cond_timedwait ● pthread_cond_init ●pthread_cond_destroy ●pthread_cond_signal ●pthread_cond_broadcast ●pthread_cond_wait ●pthread_cond_timedwait ●

References 1. * Брайан Керниган, Деннис Ритчи Язык программирования C. 2 -е издание, переработанное References 1. * Брайан Керниган, Деннис Ритчи Язык программирования C. 2 -е издание, переработанное и дополненное, 2009. 2. * P. J. Plauger The standard C library 3. * Barr M. , Massa A. Programming embedded systems with C and GNU Development tools, O'Reilly Media, 2006 Copyright © 2011 DSR Corporation 82