Программирование на языке Си. Билеты и ответы
.pdfРАСШИРЕННЫЕ ЦЕЛОЧИСЛЕННЫЕ ТИПЫ (C99). Заголовочный файл <stdint.h>.
Тип со знаком |
Тип без знака |
Описание |
|
intmax_t |
uintmax_t |
Целочисленный тип, поддерживающий |
|
максимальное целочисленное значение. |
|||
|
|
||
int<bits>_t |
uint<bits>_t |
Целочисленный тип, имеющий определенный |
|
<bits> = 8,16,32,64 |
<bits> = 8,16,32,64 |
размер. |
|
examples: |
examples: |
8, 16, 32 или 64 бита. |
|
int8_t, int64_t |
uint8_t, uint64_t |
Не все системы поддерживают. |
|
int_least<bits>_t |
uint_least<bits>_t |
Целочисленный тип, имеющий заданный |
|
<bits> = 8,16,32,64 |
<bits> = 8,16,32,64 |
||
минимальный размер. |
|||
example: |
example: |
||
Минимум 8, 16, 32 или 64 бит. |
|||
int_least8_t |
uint_least8_t |
||
|
|||
int_fast<bits>_t |
uint_fast<bits>_t |
Целочисленный тип, который является |
|
<bits> = 8,16,32,64 |
<bits> = 8,16,32,64 |
||
наиболее быстрым при использовании. |
|||
example: |
example: |
||
Минимум 8, 16, 32 или 64 бит. |
|||
int_fast8_t |
uint_fast8_t |
||
|
|||
intptr_t |
uintptr_t |
Предназначен для хранения указателей. |
ПОЛЬЗОВАТЕЛЬСКИЕ ТИПЫ ДАННЫХ ЯЗЫКА СИ
ПСЕВДОНИМЫ TYPEDEF.
Объявление: typedef <type> <new_type_name>;
Обычно, к псевдонимам typedef добавляют окончание «_t». Указывая, таким образом, что это типы, а не переменные.
Пример работы с псевдонимом typedef
#include <stdio.h>
typedef int integer; /// теперь integer то же, что и int typedef double real; /// теперь real то же, что и double typedef real fnum_t; /// теперь fnum_t то же, что и real int main()
{
integer a = 0; /// аналогично инструкции int a = 0;
real b = 100.0; /// аналогично инструкции double b = 100.0; fnum_t k = 10; /// аналогично инструкции double k = 10; scanf("%d", &a); /// Вводим число типа int
scanf("%lf", &b); /// Вводим число типа double k *= a;
printf("%d | %lf | %lf\n", a, b, k); /// Выводим числа return 0;
}
Используются для:
Сокращения длинных объявлений;
Повышения наглядности;
Кроссплатформенности.
ПЕРЕЧИСЛЕНИЯ ENUM.
Объявление: enum <name> {<value1>, <value2>, …};
В языке СИ выделен отдельный тип перечисление (enum), задающий набор всех возможных целочисленных значений переменной этого типа.
По умолчанию, первое поле принимает численное значение 0, следующее 1, следующее 2 и т.д.
|
Примеры работы с перечислением |
|||
|
|
|
#include <stdio.h> |
|
#include <stdio.h> |
|
enum gender {male, female}; |
||
enum winter {december = 31, january = 31, february = 28}; |
int main() |
|||
int main() |
|
{ |
|
|
{ |
|
|
enum gender John, Mary; |
|
enum winter february2016 = february + 1; |
|
John = male; /// int: 0 |
||
printf("%d\n", february2016); /// 29 |
|
John = 4; /// int: 4 |
||
printf("%d\n", december); /// 31 |
|
Mary = female; /// int: 1 |
||
/// december = 30; — ошибка |
|
printf("%d\n", John); /// 4 |
||
return 0; |
|
printf("%d\n", Mary); /// 1 |
||
} |
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
||
|
Стоит обратить внимание на следующее |
|
||
|
enum types { |
enum types { |
||
|
s, /// 0 |
s, /// 0 |
||
|
num, /// 1 |
num, /// 1 |
||
|
exp = 0, /// 0 |
exp = 5, /// 5 |
||
|
op, /// 1 |
op, /// 6 |
||
|
und /// 2 |
und /// 7 |
||
}; |
}; |
|
|
Используются для:
Улучшения типизации;
Повышения наглядности;
Хранения ID ошибок.
СТРУКТУРЫ STRUCT.
Структура — это совокупность переменных, объединенных одним именем, предоставляющая общепринятый способ совместного хранения информации. Объявление структуры приводит к образованию шаблона, используемого для создания объектов структуры. Переменные, образующие структуру, называются членами структуры. (Члены структуры также часто называются элементами или полями.)
Объявление: struct <struct_name> {<any_type>: <val_name1>; <any_type>: <val_name2>, …};
Пример работы со структурами
#include <stdio.h> /// Для ввода-вывода #include <string.h> /// Для работы со строками
#include <locale.h> /// Для правильного отображения русских букв
struct book { /// Создание структуры book, занимающей 58 байт (в зависимости от машины) char title[25]; /// Поле "название книги" (1 байт * 25 символов = 25 байт)
char author[25]; /// Поле "автор книги" (1 байт * 25 символов = 25 байт) int pages; /// Поле "количество страниц" (2 байта)
int year; /// Поле "год" (2 байта)
float price; /// Поле "стоимость" (4 байта)
};
void book_clear_info(struct book *any_book) { /// Функция удаление информации о книге strcpy(any_book->title, " "); /// Удаление информации о названии книги strcpy(any_book->author, " "); /// Удаление информации об авторе книги any_book->pages = 0; /// Удаление информации о количестве страниц
any_book->year = 0; /// Удаление информации о годе издания any_book->price = 0; /// Удаление информации о стоимости
}
int main()
{
int i; /// Счетчик цикла, не более
setlocale(LC_ALL, "Russian"); /// Для правильного отображения русских букв struct book history; /// Создаем книгу по истории
strcpy(history.title, "История России"); /// Название нашей книги: "История России" strcpy(history.author, "Иванов"); /// Автор нашей книги — Иванов
history.pages = 300; /// Количество страниц history.year = 2018; /// Год
history.price = 500.25; /// Стоимость for (i = 0; i <= 1; i++) {
printf("Title: %s | Author: %s\n", history.title, history.author);
printf("Pages: %d | Year: %d | Price: %f\n", history.pages, history.year, history.price); book_clear_info(&history); /// Очистка информации о книге
}
return 0;
}
Используются для:
Создания связанных списков;
Создания графов, деревьев;
Создания хэш-таблиц ("словарей"; «ключ: значение»).
ОБЪЕДИНЕНИЯ UNION.
Объединения — это объект, позволяющий нескольким переменным различных типов занимать один участок памяти. Объединение интерпретирует одно и то же значение в соответствии с разными типами.
Объявление: union <union_name> {<any_type> <val_name1>; <any_type> <val_name2>, …};
Пример работы с объединениями
#include <stdio.h> /// Для ввода-вывода
union float_char { /// Создание объединения float_char, занимающего именно 4 байта, а не 8 float f; /// 4 байт
unsigned char c[4]; /// 1 байт * 4 символа = 4 байт
};
int main()
{
union float_char value; /// Создаем value.f = 21545.00; /// Записываем число
printf("Float number: %f\n", value.f); /// Выводим число
printf("In bytes: %x %x %x %x\n", value.c[0], value.c[1], value.c[2], value.c[3]);
/// Выводим байты числа в шестнадцатеричном формате return 0;
}
Используются для:
Экономии памяти (особенно во встроенных системах);
Исследования значений отдельных байтов многобайтных величин;
Интерпретации данных, расположенных в некоторой области памяти.
БИТОВЫЕ ПОЛЯ.
Позволяют получать доступ до отдельных битов или групп битов. Доступ до отдельных битов можно осуществлять и с помощью битовых операций, но использование битовых полей часто упрощает работу.
Объявление: struct <struct_name> {<type> <name>: <number_of_bits>; <type> <name>:
<number_of_bits>, …};
Пример работы с битовыми полями
#include <stdio.h> /// Для ввода-вывода struct smth {
unsigned int v1 : 1; /// количество значений: 2^1 — либо 0, либо 1 unsigned int v2 : 2; /// количество значений: 2^2 — от 0 до 3 signed int v3 : 3; /// количество значений: 2^3 — от –4 до 3
};
int main()
{
struct smth new_smth; new_smth.v1 = 1;
printf("%d\n", new_smth.v1); /// 1 new_smth.v1 = 2;
printf("%d\n", new_smth.v1); /// 0 new_smth.v2 = 3;
printf("%d\n", new_smth.v2); /// 3 new_smth.v2 = 5;
printf("%d\n", new_smth.v2); /// 1 new_smth.v3 = -4;
printf("%d\n", new_smth.v3); /// –4 new_smth.v3 = 4;
printf("%d\n", new_smth.v3); /// –4 return 0;
}
Используются в следующих случаях:
Если ограничено место для хранения информации (можно сохранить несколько логических переменных в одном байте);
Когда интерфейсы устройств передают закодированную в байтах информацию;
Когда некоторым процедурам кодирования необходимо получить доступ к отдельным битам в байте.
ЗАДАЧА: НАПИСАТЬ ФУНКЦИЮ, ВОЗВРАЩАЮЩУЮ ЧИСЛО ЭЛЕМЕНТОВ ОДНОМЕРНОГО МАССИВА, КРАТНЫХ 2. ПРОДЕМОНСТРИРОВАТЬ ЕЁ ИСПОЛЬЗОВАНИЕ В ПРОГРАММЕ.
СИ
#include <stdio.h>
///Функция, возвращающая число элементов одномерного массива, кратных 2
///arr — массив, n — количество элементов в массиве
///Сложность алгоритма: T(n) = O(n)
int bilet3(int *arr, int n){ int i, k = 0;
for (i = 0; i < n; i++) /// От начала к концу
if ((arr[i] % 2) == 0) /// Если очередной элемент массива делится нацело на 2, то k++; /// Увеличиваем счетчик
return k; /// Возвращаем количество элементов, кратных 2
}
int main()
{
int arr[] = {-1, 3, 4, -5, -6}; /// Массив с 5-тью элементами
printf("%d\n", bilet3(arr, 5)); /// Вызов функции и вывод результата на экран: 2 return 0;
}
БИЛЕТ №4.
ТЕОРЕТИЧЕСКИЙ ВОПРОС: ОРГАНИЗАЦИЯ ВВОДА-ВЫВОДА В СИ И С++ (ФОРМАТИРОВАННЫЙ ВВОД-ВЫВОД).
Функции стандартного ввода–вывода описаны в файле stdio.h.
SCANF. ФОРМАТИРОВАННЫЙ ВВОД
int scanf(char *format, <список ввода>)
Первый параметр является символьной строкой, которая задает спецификации формата. Остальные параметры
— перечисление адресов переменных, в которые вводятся данные. В этом списке перед именами всех переменных, кроме тех, которые вводятся по спецификации типа %s, должен стоять символ &.
%[flags][width][.prec]type
PRINTF. ФОРМАТИРОВАННЫЙ ВЫВОД
int printf(char *format, <список вывода>)
Первый параметр является символьной строкой, которая выводится в поток вывода (на экран). В ней могут встречаться спецификаторы формата. Остальные параметры — перечисление переменных и выражений, значения которых выводятся. Каждая спецификация формата имеет вид (параметры в квадратных скобках необязательны):
%[flags][width][.prec]type
Как только в строке встречается спецификатор формата, он замещается значением очередной переменной из списка.
СПЕЦИФИКАТОРЫ ФОРМАТА
|
[flags] |
[width] |
[.prec] |
type |
|
|
|
|
Целое число |
d или i (целое десятичное число) |
|
|
|
|
o |
||
|
|
|
— количество |
||
|
+ или <пусто> |
|
(8-ричное целое без знака) |
||
% |
Целое число |
знаков после точки |
|||
(выравнивание по |
u (целое десятичное без знака) |
||||
|
— общая ширина поля. |
(при работе с |
|||
|
левому краю) |
x (16-ричное целое без знака) |
|||
|
|
вещественными |
|||
|
|
|
f |
||
|
|
|
числами) |
||
|
|
|
(вещественное) |
||
|
|
|
|
|
|
|
|
e |
|
|
|
|
(экспоненциальная запись) |
|
|
|
|
g |
|
|
|
|
(f или e) |
|
|
|
|
a |
|
|
|
|
(16-ричное вещественное) |
|
- |
|
|
c |
|
|
|
(символ) |
|
|
(выравнивание по |
|
|
|
|
|
|
s |
|
|
правому краю) |
|
|
|
|
|
|
(строка) |
|
|
|
|
|
|
|
|
|
|
p |
|
|
|
|
(адрес указателя) |
|
|
|
|
%% |
|
|
|
|
(символ %) |
Пример использования спецификаторов формата
#include <stdio.h> int main()
{
int a, b, c, d; float e, f, g; char ch = "X";
char str[] = "Goodbye, world";
scanf("%4d", &a); /// 5555777 (dec) —> 5555 (dec)
///пользователь ввел 7 символов, из них считались 4 символа
///остальные 3 символа направляются к следующему scanf: scanf("%o", &b); /// —> 777 (oct) —> 511 (dec) scanf("%x", &c); /// 666 (hex) —> 1638 (dec) printf("DEC: %d %d %d\n", a, b, c); /// 5555 511 1638 printf("OCT: %o %o %o\n", a, b, c); /// 12663 777 3146 printf("HEX: %x %x %x\n", a, b, c); /// 15b3 1ff 666