Добавил:
СПбГУТ * ИКСС * Программная инженерия Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование на языке Си. Билеты и ответы

.pdf
Скачиваний:
317
Добавлен:
10.09.2019
Размер:
761.78 Кб
Скачать

РАСШИРЕННЫЕ ЦЕЛОЧИСЛЕННЫЕ ТИПЫ (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