#2 — Переменные и типы данных в Си
Переменные являются важной частью любого языка программирования. В ходе урока мы познакомимся с написанием переменных, а также изучим различные типы данных. Также мы научимся выводить и получать данные от пользователя.
Видеоурок
Переменные невероятно важны, так как позволяют хранить информацию и использовать её в дальнейшем. Вначале может быть не совсем понятно зачем вообще что-то записывать в переменную, если можно просто оперировать значениями без них. Понимание переменных придет немного позже, когда мы начнем создавать более сложные программы и нам потребуется хранить информацию в каком-либо месте.
Типы переменных в языке Си указываются перед названием переменной. От конкретного типа данных будет зависеть содержимое переменной. Если мы укажем что переменная с типом данных для целых чисел int , то в неё мы не сможем записать строку или число с точкой.
В ходе программы мы можем записывать новые значения в переменную, но тип данных должен оставаться неизменным:
float some_value = 2.95; some_value = 6.9; // Записали новое значение
Рассмотрим все типы данных для создания переменных.
Целые числа
- short — предназначен для хранения целых чисел. Диапазон чисел от -32 768 до 32 767;
- unsigned short — предназначен для хранения целых положительных чисел. Диапазон чисел от 0 до 65 535;
- int — предназначен для хранения целых чисел. Диапазон чисел от -2 147 483 648 до 2 147 483 647;
- unsigned int — предназначен для хранения целых положительных чисел. Диапазон чисел от 0 до 4 294 967 295;
- long — предназначен для хранения целых чисел. Диапазон чисел от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807;
- unsigned long — предназначен для хранения целых положительных чисел. Диапазон чисел от 0 до 18 446 744 073 709 551 615.
Разница между типами заключается только в диапазоне чисел, который можно записать в переменную. Также не используйте большие типы данных по типу long, если число маленькое, так как чем больше диапазон, тем больше памяти требуется компьютеру на конкретную переменную.
Числа с точкой
- float — для создания чисел с плавающей точкой. Диапазон чисел от от -3.4*10 38 до 3.4*10 38 ;
- double — для создания чисел с плавающей точкой. Диапазон чисел от от ±4.9*10 -324 до ±1.8*10 308 .
Прочие типы данных
- bool — логический тип данных. Предназначен для записи истинного (true) или ложного (false) значения;
- char — тип данных для работы с символами. Позволяет поместить в одинарных кавычках какой-либо символ.
Для создания переменной необходимо указать тип данных и назвать её. Также можно сразу же добавить к ней значение:
int a = 0; // Добавление значения сразу float c; // Создание переменной без значения short b, y = 342; // Создание нескольких переменных
Для вызова переменной вы можете обратиться к ней по имени.
Получение данных
Для получения данных от пользователя необходимо воспользоваться функцией scanf() :
scanf("%d", &some_value);
Таким образом введенные пользователем данные будут помещены в переменную с названием «some_value».
Весь код будет доступен после подписки на проект!
Задание к уроку
Необходимо оформить подписку на проект, чтобы получить доступ ко всем домашним заданиям
Большое задание по курсу
Вам необходимо оформить подписку на сайте, чтобы иметь доступ ко всем большим заданиям. В задание входит методика решения, а также готовый проект с ответом к заданию.
PS: подобные задания доступны при подписке от 1 месяца
Создать свой тип данных
Не получается создать свой тип данных
Всем привет! Подскажите почему компилятор ругается на эти три строчки? MyVector2D():x(0),y(0)<>.
Создать свой целочисленный тип данных
Здравствуйте, у меня возник вопрос, можно ли создать например целочисленный тип данных, который.

Как создать свой целочисленный тип данных с пределом от 0 до 500
Доброе утро. Кто может подсказать, как создать персональный тип данных. Задумка вот в чем.
Как создать свой собственный тип на C++?
Здравствуйте. Возник вопрос как создать свой собственный тип на С++ который включат такие типы.
![]()
![]()
5277 / 2364 / 342
Регистрация: 20.02.2013
Сообщений: 5,763
Записей в блоге: 20
IlyaMakyha, нет, так невозможно. Только так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#include class Bignum { std::string digits; // Число }; int main() { Bignum b("@4487612165"); // или b = "@133+@559098"; return 0; }
18413 / 9584 / 2341
Регистрация: 30.01.2014
Сообщений: 16,742
Сообщение от IlyaMakyha 
Возможно ли сделать вот так:
А зачем?
В смысле зачем собачки перед литералами?
Можно же просто
1 2 3
Bignum b(4487612165); b = 133 + 559098;
для этого необходимо будет перегрузить конструктор и оператор присваивания для соответствующих целых типов.
Если же нужно будет задавать целое число, которое не помещается в стандартные типы, то да, в виде строки придется задавать, затем переводить ее во внутреннее представление твоего класса.
![]()
![]()
5277 / 2364 / 342
Регистрация: 20.02.2013
Сообщений: 5,763
Записей в блоге: 20
Сообщение от DrOffset 
перегрузить конструктор и оператор присваивания
Сообщение от DrOffset 
задавать целое число, которое не помещается в стандартные типы, то да, в виде строки придется задавать
DrOffset, опередил меня )))
IlyaMakyha, как-то так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
#include #include class Bignum { std::string digits_; public: Bignum() { digits_ = ""; } explicit Bignum( std::string d ) : digits_( d ) {} explicit Bignum( const char* d ) : digits_( d ) {} Bignum( const Bignum& b ) { digits_ = b.digits_; } Bignum& operator=( const Bignum& b ) { if ( this != &b ) digits_ = b.digits_; return *this; } Bignum& operator=( const std::string& b ) { if ( &digits_ != &b ) digits_ = b; return *this; } friend void operator( std::ostream& os, const Bignum& b ) { os b.digits_ "\n"; } }; int main() { Bignum b( "@4487612165" ); std::cout b; // или b = "@133+@559098"; std::cout b; return 0; }
Любитель чаепитий
3741 / 1798 / 565
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
Сообщение от gru74ik 
1 2 3 4
friend void operator( std::ostream& os, const Bignum& b ) { os b.digits_ "\n"; }
Вроде возвращают os, а не void?
![]()
![]()
5277 / 2364 / 342
Регистрация: 20.02.2013
Сообщений: 5,763
Записей в блоге: 20
GbaLog-, можно как я написал, если цепочки вызовов не планируешь делать.
Добавлено через 3 минуты
GbaLog-, хотя, конечно, каноничный вариант такой:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#include #include class Bignum { std::string digits_; public: Bignum() { digits_ = ""; } explicit Bignum( std::string d ) : digits_( d ) {} explicit Bignum( const char* d ) : digits_( d ) {} Bignum( const Bignum& b ) { digits_ = b.digits_; } Bignum& operator=( const Bignum& b ) { if ( this != &b ) digits_ = b.digits_; return *this; } Bignum& operator=( const std::string& b ) { if ( &digits_ != &b ) digits_ = b; return *this; } friend std::ostream& operator( std::ostream& os, const Bignum& b ) { os b.digits_ "\n"; return os; // Бодхидхарма одобряет } }; int main() { Bignum b( "@4487612165" ); std::cout b; b = "@133+@559098"; Bignum c( "O-LO-LO-666" ); std::cout b c; // дух Дзен с домино и блудницами return 0; }
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь
Как реализовать свой тип данных
Здравсвтуйте,подскажите пожалуйста как реализовать с с++ свой тип данных. Допустим хочу завести.
Свой тип данных для перегрузки функций
Добрый день! Имеется широта и долгота — все FLOAT. Хочу сделать пару функций с одинаковым.

Свой тип данных позволяющий хранить числа разрядностью в Доброго времени суток! Возникла потребность иметь программу позволяющую производить.
Создать свой поток данных
Не могу понять, возможно ли как то создать свой поток данных? Знаю есть файловые потоки, cin cout.
Как сконвертировать свой тип в тип double?
Можно ли конвертировать свой тип в тип doble? Если да, то каким способом?
Создать тип данных Многоразрядное число
Создать тип данных Многоразрядное число. Разработать следующие функции: • Equal() – сравнение.
Сложные типы данных в Си
Структура — это объединение нескольких объектов, возможно, различного типа под одним именем, которое является типом структуры. В качестве объектов могут выступать переменные, массивы, указатели и другие структуры.
Структуры позволяют трактовать группу связанных между собой объектов не как множество отдельных элементов, а как единое целое. Структура представляет собой сложный тип данных, составленный из простых типов.
Общая форма объявления структуры:
struct ИмяСтруктуры
тип ИмяЭлемента1;
тип ИмяЭлемента2;
. . .
тип ИмяЭлементаn;
>;
После закрывающей фигурной скобки > в объявлении структуры обязательно ставится точка с запятой.
Пример объявления структуры
struct date
int day; // 4 байта
char *month; // 4 байта
int year; // 4 байта
>;

Поля структуры располагаются в памяти в том порядке, в котором они объявлены:
В указанном примере структура date занимает в памяти 12 байт. Кроме того, указатель *month при инициализации будет началом текстовой строки с названием месяца, размещенной в памяти.
При объявлении структур, их разрешается вкладывать одну в другую.
struct persone
char lastname[20]; // фамилия
char firstname[20]; // имя
struct date bd; // дата рождения
>;
Инициализация полей структуры
Инициализация полей структуры может осуществляться двумя способами:
- присвоение значений элементам структуры в процессе объявления переменной, относящейся к типу структуры;
- присвоение начальных значений элементам структуры с использованием функций ввода-вывода (например, printf() и scanf() ).
В первом способе инициализация осуществляется по следующей форме:
struct ИмяСтруктуры ИмяПеременной=<ЗначениеЭлемента1, ЗначениеЭлемента_2, . . . , ЗначениеЭлементаn>;
ЗначениеЭлемента1,>
struct date bd=<8, "июня" , 1978>;
8,>
Имя элемента структуры является составным. Для обращения к элементу структуры нужно указать имя структуры и имя самого элемента. Они разделяются точкой:
ИмяПеременной.ИмяЭлементаСтруктуры
printf( «%d %s %d» ,bd.day, bd.month, bd.year);
Второй способ инициализации объектов языка Си с использованием функций ввода-вывода.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#define _CRT_SECURE_NO_WARNINGS
#include
#include
struct date int day;
char month[20];
int year;
>;
struct persone char firstname[20];
char lastname[20];
struct date bd;
>;
int main() system( «chcp 1251» );
system( «cls» );
struct persone p;
printf( «Введите имя : » );
scanf( «%s» , p.firstname);
printf( «Введите фамилию : » );
scanf( «%s» , p.lastname);
printf( «Введите дату рождения\nЧисло: » );
scanf( «%d» , &p.bd.day);
printf( «Месяц: » );
scanf( «%s» , p.bd.month);
printf( «Год: » );
scanf( «%d» , &p.bd.year);
printf( «\nВы ввели : %s %s, дата рождения %d %s %d года» ,
p.firstname, p.lastname, p.bd.day, p.bd.month, p.bd.year);
getchar(); getchar();
return 0;
>

Результат работы
Имя структурной переменной может быть указано при объявлении структуры. В этом случае оно размещается после закрывающей фигурной скобки > . Область видимости такой структурной переменной будет определяться местом описания структуры.
struct complex_type // имя структуры
double real;
double imag;
> number; // имя структурной переменной
Поля приведенной структурной переменной: number.real, number.imag .
Объединения
Объединениями называют сложный тип данных, позволяющий размещать в одном и том же месте оперативной памяти данные различных типов.
Размер оперативной памяти, требуемый для хранения объединений, определяется размером памяти, необходимым для размещения данных того типа, который требует максимального количества байт.
Когда используется элемент меньшей длины, чем наиболее длинный элемент объединения, то этот элемент использует только часть отведенной памяти. Все элементы объединения хранятся в одной и той же области памяти, начиная с одного адреса.
Общая форма объявления объединения
union ИмяОбъединения
тип ИмяОбъекта1;
тип ИмяОбъекта2;
. . .
тип ИмяОбъектаn;
>;

Объединения применяются для следующих целей:
- для инициализации объекта, если в каждый момент времени только один из многих объектов является активным;
- для интерпретации представления одного типа данных в виде другого типа.
Например, удобно использовать объединения, когда необходимо вещественное число типа float представить в виде совокупности байтов
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define _CRT_SECURE_NO_WARNINGS
#include
#include
union types
float f;
unsigned char b[4];
>;
int main()
types value;
printf( «N = » );
scanf( «%f» , &value.f);
printf( «%f = %x %x %x %x» , value.f, value.b[0], value.b[1], value.b[2], value.b[3]);
getchar();
getchar();
return 0;
>

Результат выполнения:
Пример Поменять местами два младших байта во введенном числе
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#define _CRT_SECURE_NO_WARNINGS
#include
#include
int main() char temp;
system( «chcp 1251» );
system( «cls» );
union
unsigned char p[2];
unsigned int t;
> type;
printf( «Введите число : » );
scanf( «%d» , &type.t);
printf( «%d = %x шестн.\n» , type.t, type.t);
// Замена байтов
temp = type.p[0];
type.p[0] = type.p[1];
type.p[1] = temp;
printf( «Поменяли местами байты, получили\n» );
printf( «%d = %x шестн.\n» , type.t, type.t);
getchar(); getchar();
return 0;
>

Результат выполнения
Битовые поля
Используя структуры, можно упаковать целочисленные компоненты еще более плотно, чем это было сделано с использованием массива.
Набор разрядов целого числа можно разбить на битовые поля, каждое из которых выделяется для определенной переменной. При работе с битовыми полями количество битов, выделяемое для хранения каждого поля отделяется от имени двоеточием
тип имя: КоличествоБит
При работе с битовыми полями нужно внимательно следить за тем, чтобы значение переменной не потребовало памяти больше, чем под неё выделено.

Пример Разработать программу, осуществляющую упаковку даты в формат
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#define YEAR0 1980
struct date
unsigned short day : 5;
unsigned short month : 4;
unsigned short year : 7;
>;
int main() struct date today;
system( «chcp 1251» );
system( «cls» );
today.day = 16;
today.month = 12;
today.year = 2013 — YEAR0; //today.year = 33
printf( «\n Сегодня %u.%u.%u \n» , today.day, today.month, today.year + YEAR0);
printf( «\n Размер структуры today : %d байт» , sizeof (today));
printf( «\n Значение элемента today = %hu = %hx шестн.» , today, today);
getchar();
return 0;
>

Результат выполнения
Массивы структур
Работа с массивами структур аналогична работе со статическими массивами других типов данных.
Пример Библиотека из 3 книг
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include
#include
struct book
char title[15];
char author[15];
int value;
>;
int main()
struct book libry[3];
int i;
system( «chcp 1251» );
system( «cls» );
for (i = 0; i printf( «Введите название %d книги : » , i + 1);
gets_s(libry[i].title);
printf( «Введите автора %d книги : » , i + 1);
gets_s(libry[i].author);
printf( «Введите цену %d книги : » , i + 1);
scanf_s( «%d» , &libry[i].value);
getchar();
>
for (i = 0; i printf( «\n %d. %s » , i + 1, libry[i].author);
printf( «%s %d» , libry[i].title, libry[i].value);
>
getchar();
return 0;
>

Результат выполнения
Указатели на структуры
Доступ к элементам структуры или объединения можно осуществить с помощью указателей. Для этого необходимо инициализировать указатель адресом структуры или объединения.
Для организации работы с массивом можно использовать указатель. При этом обращение к полям структуры через указатель будет выглядеть как:
указатель->поле
или
(*указатель).поле
указатель — указатель на структуру или объединение;
поле — поле структуры или объединения;
Динамическое выделение памяти для структур
Динамически выделять память под массив структур необходимо в том случае, если заранее неизвестен размер массива. Для определения размера структуры в байтах используется операция sizeof (ИмяСтруктуры) .
Пример Библиотека из 3 книг
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include
#include
#include
struct book
char title[15];
char author[15];
int value;
>;
int main()
struct book *lib;
int i;
system( «chcp 1251» );
system( «cls» );
lib = ( struct book*)malloc(3 * sizeof ( struct book));
for (i = 0; i printf( «Введите название %d книги : » , i + 1);
gets_s((lib + i)->title);
printf( «Введите автора %d книги : » , i + 1);
gets_s((lib + i)->author);
printf( «Введите цену %d книги : » , i + 1);
scanf_s( «%d» , &(lib + i)->value);
getchar();
>
for (i = 0; i printf( «\n %d. %s » , i + 1, (lib + i)->author);
printf( «%s %d» , (lib + i)->title, (lib + i)->value);
>
getchar();
return 0;
>
Результат выполнения аналогичен предыдущему решению.
Комментариев к записи: 44
Здравствуйте, Елена! Можем ли мы как-то, например через указатель, перемещаться по элементам структуры. К примеру, у меня есть структура с флагами битовых полей, в которые я заношу биты при считывании строки, и я хочу вывести на экран все ненулевые значения флагов, которые были внесены. Тупо писать if (flag.a) printf . if (flag.b) printf. . я не хочу, а хочу сделать в цикле по количеству флагов и перемещаясь от текущего к последующему, уже выводить его если он был внесён. Я могу по ним как то ходить типа как через указатель по элементам массива? Или в структуре так нельзя сделать?
К сожалению, я не знаю способа перебора битовых полей. Поскольку допустимо, чтобы поля были разного размера, как и элементы структуры, способ их перебора по индексу не предусмотрен.
Подскажите пожалуйста, можно ли определить тип данных элемента структуры? Пытаюсь автоматизировать обработку структуры как массива данных различных типов.
sizeof поможет определить размер поля данных структуры, но не тип. Тип должен быть известен на этапе формирования структуры. При обращении к полям структуры мы знаем их тип.
а как же «Для определения типа переменной в C++ существует функция typeid().name() из библиотеки typeinfo» представьте ситуацию, когда вы на некую структуру натравливаете обработчик, на выходе которого имеете количество и тип элементов этой структуры. Следующим шагом будут определенные действия над элементами в зависимости от их типа. Т.е. вы сможете безболезненно добавлять или убирать элементы из структуры, не нарушая работы системы в целом
подскажите, как сформировать пакет данных, состоящий из однобайтовых числе и двухбайтовых. информация будет отсылаться по юарту, но пока встал на этой проблеме.
Сформировать в виде последовательности байтов. При расшифровке посылки ориентироваться по меткам, какие в последовательности данные за что отвечают. Например, первый байт посылки это однобайтное значение, второй и третий байты отвечают за двухбайтное. Порядок передачи и восстановления байтов 2-байтных значений естественно сохраняем.
Здравствуйте, имею такой вопрос по поводу структур в Си. Допустим, я инициализирую поля структуры при её объявлении. Но не все возможные поля, а лишь некоторые. Например:
struct date
int day; // 4 байта
char *month; // 4 байта
int year; // 4 байта
>;
Какие данные будут находится в не затрагиваемом при инициализации поле month? NULL или мусор из стека?
Елена Вставская
При частичной инициализации пропущенные значения заполняются нулями
Благодарю Вас за ответ.
Здравствуйте!Подскажите пожалуйста, как сделать поиск по фамилиям, Я так понимаю нужно сравнить фамилию(Записанную ранее пользователем) с фамилией введенной с клавиатуры, и вывести все фамилии схожей с той который веел пользователь return strcmp(((struct book*)a)->familia, ((struct book*)b)->familia); это сравнение со всеми фамилиями, а как сравнить с той который ввел пользователь я не пойму
Елена Вставская
Ввести в строку (массив char) и передать как аргумент в функцию сравнения
Здравствуйте! Спасибо Вам за статью. Мне непонятен доступ к элементам структуры когда одним из элементов является массив. Например есть структура
struct book <
char massiv[20];
int b [5];
char c;
>;
struct book lolik;
массиву massiv необходимо присвоить значение:
Почему так нельзя делать? а так можно
Елена Вставская
Мы можем проинициализировать поля структуры только при ее объявлении. Дальше уже идут операции присваивания. Причем инициализация должна быть выполнена для всех полей одновременно. Нельзя проинициализировать часть полей (причем из середины). Можно сделать так:
struct book lolik = < "" , <5, 3, 8, 0, 1>, 0 >;
5,>
Здравствуйте. Подскажите, как при задании массива структур правильно инициализировать поля каждой структуры? Массив статический. Если можно, хотелось бы увидеть какие-нибудь примеры.
Елена Вставская
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Добрый вечер! Подскажите, пожалуйста, как вывести несколько департаментов, если количество сотрудников одинаковое и не вывести ничего, если не удовлетворяет заданию? Заранее спасибо! Задание: найти самый маленький отдел, созданный не позднее заданной даты Вроде все работает, но не понимаю, как написать условие (возможно, if, else), чтобы при одинаковом кол-ве сотрудников вывел оба департамента и чтобы не вывел ничего, если не удовлетворяет условию, связанным с годом? P.S. Структура задана в заголовочном файле ЗАГОЛОВОЧНЫЙ ФАЙЛ (department.h):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# if ndef department_h
#define department_h
#include
struct Office
char title[50];
struct int amount; // количество сотрудников
char lastname[50]; // фамилия начальника
> inc;
struct int year;
int month;
> date;
#include
#include
#include //подключаем библиотеку математики
#include //подключаем библиотеку языков
#include
#include «department.h»
#define N 0
void display( struct Office* a, int i) //вывод одного отдела с помощью цикла
printf( «Название: %s\nКоличество сотрудников: %d\nФамилия начальника: %s\nДата создания: %d.%d\n\n» ,
a[i].title, a[i].inc.amount, a[i].inc.lastname, a[i].date.year, a[i].date.month);
>
void create( struct Office* a, int * pn) //функция ввода с клавиутары данных и вывод их на консоль
printf( «Введите количество отделов ( < 20): " );
scanf_s( «%d%*c» , pn); //%*c применяется для удаления enter и считывания fgets дальше (чтобы они работали и воспринимались программой)
printf( «\n» );
for ( int i = 0; i < *pn; i++)
printf( «Название: » );
fgets(a[i].title, 50, stdin);
a[i].title[strlen(a[i].title) — 1] = 0;
printf( «Количество сотрудников: » );
scanf_s( «%d%*c» , &a[i].inc.amount);
printf( «Фамилия начальника: » );
fgets(a[i].inc.lastname, 50, stdin);
a[i].inc.lastname[strlen(a[i].inc.lastname) — 1] = 0;
printf( «Дата создания: » );
scanf_s( «%d%d%*c» , &a[i].date.year, &a[i].date.month);
puts( «» );
>
>
int small( struct Office* a, int n, int year, int month)
<
int i = 0, index = 0, min = 0;
while ((a[i].date.year > year) || (a[i].date.month > month) && (a[i].date.year == year)) //сравниваем дату создания с датой, введенной нами
i++;
>
index = i;
min = a[i].inc.amount;
int main()
setlocale(LC_ALL, «Rus» ); //включение локализации
setlocale(LC_NUMERIC, «Eng» ); //использование «.» в дробных значениях
int n = 0, year = 0, month = 0;
# if N == 1
struct Office A[] =
< "Прикладная математика", 118, "Белов" , 2055, 7,
«Электронная инженерия», 120, «Львов» , 2020, 5,
«Компьютерная инженерия», 119, «Старых» , 2022, 9,
«Мировая политика», 130, «Иванов» , 2014, 8,
«Экономика», 130, «Петров» , 2018, 7,
«Информатика», 135, «Сидоров» , 2010, 5,
«Политика», 180, «Быстров» , 2100, 4,
«Медиа», 200, «Молодцов» , 2055, 5>;
n = sizeof (A) / sizeof (A[0]); //размер (в байтах) всего массива, то есть сумма всех элементов/ размер (в байтах) одной структуры (50)
for ( int i = 0; i < n; i++)
display(A, i);
# else
struct Office A[19];
create(A, &n);
for ( int i = 0; i < n; i++)
display(A, i);
printf( «Введите дату создания: » );
scanf_s( «%d%d%*c» , &year, &month);
printf( «\n» );
n = small(A, n, year, month);
display(A, n);
return 0;
>
Здравствуйте, можете подсказать, что делает данный код
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void MySort(List *list) <
if (list == NULL || list->head == NULL ) <
fprintf(stderr, «Список пуст\n» );
return ;
>
char preNext = ‘ ‘;
while (list->head->data == ‘ ‘ || list->head->data == ‘\t’) printf( «CHAR ‘%c’\n» , list->head->data);
if (!DelHead(list)) printf( «ERR» );
return ;
>
>
printf( «фиксированная буква ‘%c’\n» , list->head->data);
char c = list->head->data;
Item *myNext = list->head->next;
while (myNext->data != ‘ ‘) myNext = myNext->next;
if (myNext == NULL ) return ;
>
while (myNext->next != NULL ) if ( (myNext->data == ‘ ‘ || myNext->data == ‘\t’) && myNext->next->data == c && (preNext == ‘ ‘ || preNext == ‘\t’)) do myNext = myNext->next;
if (myNext == NULL ) return ;
> while ( myNext->data != ‘ ‘ && myNext->data != ‘\t’);
> else preNext = DelNext(list, myNext);
>
>
>
А в особенности строка(если не сложно, можете прочитать слева направо):
if ( (myNext->data == ‘ ‘ || myNext->data == ‘\t’) && myNext->next->data == c && (preNext == ‘ ‘ || preNext == ‘\t’))
Елена Вставская
Сложно сказать без отладчика, код не полный. Например, непонятно, что делает функция DelNext() и что она возвращает. Отсюда и интересующая Вас строка. Переменной prevNext присваивается то, что вернула функция DelNext()
Подскажите, пожалуйста, как сначала вывести тех, у кого доходы меньше двух минимальных зарплат, а потом всех остальных в порядке уменьшения среднего балла.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include
#include
#include
#include
struct spisok
char FIO[70];
char group[7];
int AvMark;
int Income;
>;
int main() struct spisok dorm[3];
int i, minwage = 500;
for (i = 0; i < 3; i++) printf( "Enter FIO %d : " , i + 1);
gets_s(dorm[i].FIO);
printf( «Enter group %d : » , i + 1);
gets_s(dorm[i].group);
printf( «Enter AvMark %d : » , i + 1);
scanf_s( «%d» , &dorm[i].AvMark);
printf( «Enter Income %d : » , i + 1);
scanf_s( «%d» , &dorm[i].Income);
printf( «\n» );
getchar();
>
for (i = 0; i < 3; i++) printf( "\n%s " , dorm[i].FIO);
printf( «\nGroup: » );
printf( «%s » , dorm[i].group);
printf( «\nAverage mark: » );
printf( «%d» , dorm[i].AvMark);
printf( «\nIncome: » );
printf( «%d» , dorm[i].Income);
>
getchar();
return 0;
>
Елена Вставская
Отсортировать всех. Выводить пока доход меньше введённого значения (мин.з.п. и т.п.). Перевести строку, запомнить номер элемента. Вывести элементы с конца массива до текущего.
Елена, добрый день! У Вас опечатка? struct тип_структуры не тип, а имя_структуры? С уважением Ирина
Елена Вставская
Спасибо, поправила
здравствуйте, можете помочь написать программу в С+, в которой будет реализована функция, выводящая информацию об N студентах в алфавитном порядке Функция должна принимать на вход указатель на массив структур размером N. Структура должна содержать поля: Фамилия , Имя, Отчество, дата рождения, факультет Функция должна выводить на экран информацию о всех студентах, отсортировав их по фамилии Информацию о студентах принимать вводом из консоли, вывод в консоль.
Елена Вставская
Помочь могу, написать за Вас — нет
Подскажите пожалуйста почему if второе условие не выполняет. Заранее спасибо.Вот если что задание. Створити структуру та зробити необхідні розрахунки. Поля структури:Прізвище, вік, освіта, посада. Вивести дані про працівників старших 30-ти років, які не мають вищої освіти.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include
#include
#define n 3
typedef struct char Prizv[20],Osvita[30],Posada[30];
int Vik;>Pracxivniki;
int main()clrscr();
Pracxivniki p[n];
int i;
for (i=0;i
scanf( «%s» ,p[i].Prizv);
printf( «Vik: » );
scanf( «%d» ,&(p[i].Vik));
printf( «Osvita: » );
scanf( «%s» ,p[i].Osvita);
printf( «Posada: » );
scanf( «%s» ,p[i].Posada);>
printf( «Dani pro pracxivnikiv starsche 30 bez vischoi osviti\n» );
char rt[]= «Vischa» ;
for (i=0;i
printf( » Vik: %d» ,p[i].Vik);
printf( » Osvita: %s» ,p[i].Osvita);
printf( » Posada: %s\n» ,p[i].Posada);>>
getch();
return 0;>
Елена Вставская
Потому что две строки лежат по разным адресам, и сравнивать эти адреса бессмысленно. Строки нужно сравнивать посимвольно — или в цикле, или, например, с помощью функции strcmp
Посмотрите пожалуйста задание и мой код не пойму как исправить ошибки. Створити структуру даних згідно варіанту, створена програма повинна передбачати введення даних з клавіатури, задання кількості записів, перегляд структури. 12. «Чоловік»: прізвище; ім’я; батькові; стать; національність; зріст; вага; дата народження (рік, місяць, число); номер телефону; домашню адресу (поштовий індекс, країна, область, район, місто, вулиця, будинок, квартира).
#include
#include
#include
typedef struct int Rik, Mis, Chislo;>Datanarod;
typedef struct char Poind[10], Kraina[20], Oblast[20], Raion[20], Misto[20], Vul[20], Bud[10], Kvart[10];>Domadres;
typedef struct char Prizv[20], Imia[20], Batko[20], Stat[10], Nacxion[20];
int Zrist, Vaga;
struct Datanarod;
char Nomertel[10];
struct Domadres;>Cholovik;
int main()Cholovik *p;
int n,i;
printf( «Vvedit kilkist zapisiv\t» );
scanf( «%d» ,&n);
p=(Cholovik*) malloc (n* sizeof (Cholovik));
if (p== NULL ) printf( «Nestacha pamiati\n» );
return -1;>
for (i=0;i
scanf( «%s» ,&p[i].Prizv);
printf( «\nImia:\t» );
scanf( «%s» ,&p[i].Imia);
printf( «\nPo batkovi:\t» );
scanf( «%s» ,&p[i].Batko);
printf( «\nStat:\t» );
scanf( «%s» ,&p[i].Stat);
printf( «\nNacxionalnist:\t» );
scanf( «%s» ,&p[i].Nacxion);
printf( «\nZrist:\t» );
scanf( «%d» ,&p[i].Zrist);
printf( «\nVaga:\t» );
scanf( «%d» ,&p[i].Vaga);
printf( «\nData narodzhennia(rik,misiacx,den):\t» );
scanf( «%d%d%d» ,&p[i].Datanarod.Rik,&p[i].Datanarod.Mis,&p[i].Datanarod.Chislo);
printf( «\nNomer telefona:\t» );
scanf( «%s» ,&p[i].Nomertel);
printf( «\nDomaschnia adresa(poshtovyj indekc, derhava, krajina, oblact, rajon, misto, vulitsja, budynok, kvartyra):\t» );
scanf( «%s%s%s%s%s%s%s%s%s» ,&p[i].Domadres.Poind,&p[i].Domadres.Kraina,&p[i].Domadres.Oblast,&p[i].Domadres.Raion,&p[i].Domadres.Misto,&p[i].Domadres.Vul,&p[i].Domadres.Bud,&p[i].Domadres.Kvart);
int k;
printf( «Dlia prosmotra strukturi nazhmite 1, a dlia vihoda nazhmite lubuyu klavishu\t» );
scanf( «%d» ,&k);
if (k==1) for (i=0;i
printf( «\nImia:\t%s» ,p[i].Imia);
printf( «\nPo batkovi:\t%s» ,p[i].Batko);
printf( «\nStat:\t%s» ,p[i].Stat);
printf( «\nNacxionalnist:\t%s» ,p[i].Nacxion);
printf( «\nZrist:\t%d» ,p[i].Zrist);
printf( «\nVaga:\t%d» ,p[i].Vaga);
printf( «\nData narodzhennia(rik,misiacx,den):\t%d%d%d» ,p[i].Datanarod.Rik,p[i].Datanarod.Mis,p[i].Datanarod.Chislo);
printf( «\nNomer telefona:\t%s» ,p[i].Nomertel);
printf( «\nDomaschnia adresa(poshtovyj indekc, derhava, krajina, oblact, rajon, misto, vulitsja, budynok, kvartyra):\t%s%s%s%s%s%s%s%s%s» ,
p[i].Domadres.Poind,p[i].Domadres.Kraina,p[i].Domadres.Oblast,p[i].Domadres.Raion,p[i].Domadres.Misto,p[i].Domadres.Vul,p[i].Domadres.Bud,p[i].Domadres.Kvart);>
else < return 1;>>
free(p);
return 0;>
Елена Вставская
Основная ошибка в том, что нельзя typedef указывать членом структуры. Это теперь тип, а не объект. И если мы объявили новый тип с помощью typedef, то struct тут уже излишне.
1
2
3
4
5
6
7
8
9
10
11
typedef struct <
char Prizv[20], Imia[20], Batko[20], Stat[10], Nacxion[20];
int Zrist, Vaga;
Datanarod Dn;
char Nomertel[10];
Domadres Da;
>Cholovik;[\code]
Ну, и есть несколько других мелких ошибок. В частности, строчка
[code]printf( «\nDomaschnia adresa(poshtovyj indekc, derhava, krajina, oblact, rajon, misto, vulitsja, budynok, kvartyra):\t» );
scanf( «%s%s%s%s%s%s%s%s» , p[i].Da.Poind, p[i].Da.Kraina, p[i].Da.Oblast, p[i].Da.Raion, p[i].Da.Misto, p[i].Da.Vul, p[i].Da.Bud, p[i].Da.Kvart);
Poind это уже указатель, поэтому перед p[i].Da.Poind амперсанд не ставится. Нужно проверить количество форматов для ввода и количество вводимых полей — они должны совпадать. Сейчас printf запрашивает 9 полей, а scanf вводит 8.
Доброе время суток, не могли бы Вы помочь разобраться в структуре, а именно возникла проблема с частью «void seach_a_table(char* FileName)». Заранее спасибо.
#include
#include
#include
#include
struct price //прайс
<
char nsr[30]; //название товара
char nfr[30]; //название магазина
int nr; //стоимость
>;
void in_table( char * FileName)
<
FILE *ou = fopen(FileName, «a+» );
struct price item;
rewind(stdin);
printf( «Введите:\n» );
printf( «Название товара: » );
gets(item.nsr);
rewind(stdin);
printf( «Название магазина: » );
gets(item.nfr);
printf( «Стоимость: » );
scanf( «%d» , &item.nr);
fwrite(&item, sizeof ( struct price), 1, ou);
fclose(ou);
printf( «\nДанные записаны в файл.\n» );
>
void pnt_item( struct price item)
printf( «Название магазина: %s\n» , item.nfr);
printf( «Название товара: %s\n» , item.nsr);
printf( «Стоимость: %d\n» , item.nr);
>
void seach_a_table( char * FileName)
FILE *in = fopen(FileName, «r» );
struct price item;
char * nfr;
printf( «Введите название магазина: » );
scanf( «%s» , &nfr);
while (fread(&item, sizeof ( struct price), 1, in))
:
:
:
fclose(in);
if (k == 0)
printf( «магазин %s не найден.\n\n» , nfr);
>
int main()
<
system( «chcp 1251» );
system( «cls» );
char * fn = «PriceList.dat» ;
char key;
do system( «cls» );
printf( «1 — Ввод информации в прайс\n» );
printf( «2 — Вывод информации из прайса\n» );
printf( «3 — Поиск товара в магазине\n» );
printf( «0 — Выход\n» );
key = getch();
system( «cls» );
switch (key)
case ‘1’: in_table(fn); break ;
case ‘2’: print_table(fn); break ;
case ‘3’: seach_a_table(fn); break ;
>
system( «pause» );
> while (key != ‘0’);
Структурный тип данных
Примером структуры может послужить любой объект, для которого описывается ряд его характеристик, имеющих значение в данной программе. Например, для книг это может быть название, автор, количество страниц; для окружности — координаты центра, диаметр, цвет. На языке программирования C объявление вышеупомянутых структурных типов данных может выглядеть так:
struct book char title[50]; char author[30]; int pages; >; struct circle int x, y; float dia; char color[10]; >;
В данном случае мы как бы создаем новый тип данных, но еще не объявляем переменных этих типов. Обратите внимание на точку с запятой в конце объявлений.
Чаще переменные структур объявляются так:
struct circle a, b, c; struct book mybook;
Здесь объявляются три структуры типа circle и одна структура типа book. Можно объявлять типы структур и их переменные по-иному, но мы для избежания путаницы рассматривать другие способы не будем.
Каждая переменная типа circle содержит четыре элемента (или поля) — x, y, dia, color. Можно сказать, что они представляют собой вложенные переменные. Причем эти переменные разных типов. Таким образом переменная-структура позволяет объединить под одним именем ряд разнородных данных. Обычно это нужно для удобства обработки данных. Если нельзя было бы создавать структуры, то пришлось бы создавать множество независимых переменных или ряд массивов, явной взаимосвязи между которыми не было бы. Структуры же позволяют объединять взаимосвязанные данные. Это конечно еще не объектно-ориентированное программирование, но уже взгляд в его сторону.
Объявив переменную структурного типа, мы можем получить доступ к каждому ее элементу для присваивания, изменения или получения значения:
a.x = 10; a.dia = 2.35; printf("%.2f ", a.dia);
Значение элементов структуры можно сразу определять при объявлении переменной, что похоже на инициализацию массивов:
struct book lang_c = {"Language C", "Ritchi", 99};
Значение переменной-структуры можно присвоить переменной того же типа:
struct book { char *title, *author; int pages; }; struct book old, new; old.title = "GNU/Linux"; old.author = "people"; old.pages = 20213; new = old; new.pages += 2000; printf("%d, %d\n", old.pages, new.pages);
В четвертой строке кода данные переменной old присваиваются new. В итоге вторая структура содержит копию данных первой. То, что можно выполнять присваивание по отдельным полям должно быть понятно.
Структуры и функции
Структуры-переменные можно передавать в функции в качестве параметров и возвращать их оттуда. Структуры передаются по значению, как обычные переменные, а не по ссылке, как массивы.
Рассмотрим программу, в которой одна функция возвращает структуру, а другая — принимает ее в качестве параметра:
#include #include struct circle { int x, y; float dia; char color[10]; }; struct circle new_circle(); void cross (struct circle); int main () { struct circle a; a = new_circle(); cross(a); } struct circle new_circle() { struct circle new; printf("Координаты: "); scanf("%d%d", &new.x, &new.y); printf("Диаметр: "); scanf("%f", &new.dia); printf("Цвет: "); scanf("%s", new.color); return new; } void cross (struct circle c) { double hyp; hyp = sqrt((double) c.x * c.x + (double) c.y * c.y); printf("Расстояние: %.2lf\n", hyp); if (hyp c.dia / 2) puts("Пересекает"); else puts("Не пересекает"); }
Примечание. При компиляции программы в GNU/Linux команда выглядит так: gcc program.c -lm . Это связано с использованием библиотеки с математическими функциями.
- Объявляется структура circle как глобальный тип данных. Таким образом любая, а не только main() , функция может создавать переменные этого типа.
- Функция new_circle() возвращает структуру, а функция cross() принимает структуру по значению. Следует отметить, что можно создавать функции, которые как принимают (возможно, несколько структур) так и возвращают структуру.
- В функции new_circle() создается переменная new типа struct circle, поля которой заполняются пользователем. Функция возвращает значение переменной new в функцию main() , где это значение присваивается переменной a, которая также принадлежит типу sctruct circle.
- Функция cross() определяет, пересекает ли круг начало координат. В ее теле вычисляется расстояние от центра круга до начала координат. Это расстояние является гипотенузой прямоугольного треугольника, длина катетов которого равна значениям x и у. Далее, если гипотенуза меньше радиуса, то круг пересекает начало координат, т.е. точку (0, 0).
- В функции main() при вызове cross() данные, содержащиеся в переменной a, копируются и присваиваются переменной c.
Указатели и структуры
В отличие от массивов, структуры передаются в функции по значению. Это не всегда рационально, т.к. структуры могут быть достаточно большого размера, и копирование таких участков памяти может замедлять работу программы. Поэтому часто структуры в функцию передают по ссылке, при этом можно использовать как указатель, так и операцию получения адреса.
// переменная-структура struct book new; // указатель на структуру struct book *pnew; // передаем адрес reader(&new); pnew = &new; // передаем указатель reader(pnew);
Тогда функция reader() должна иметь примерно такое объявление:
void reader(struct book *pb);
Возникает вопрос, как при использовании указателей обращаться к элементам структур? Во первых надо получить саму структуру, т.е. если pnew указатель, то сама структура будет *pnew . Далее можно уже обращаться к полям через точку: *pnew.title . Однако это выражение не верно, т.к. приоритет операции «точка» (обращение к полю) выше операции «звездочка» (получить значение по адресу). Таким образом приведенная запись сначала пытается получить значение поля title у указателя pnew, но у pnew нет такого поля. Проблема решается с помощью скобок, которые изменяют порядок выполнения операций: (*pnew).title . В таком случае сначала извлекается значение по адресу pnew, это значение является структурой. Затем происходит обращение к полю структуры.
В языке программирования C записи типа (*pnew).title часто заменяют на такие: pnew->title , что позволяет синтаксис языка. Когда в программе вы видите стрелку (тире и скобка) всегда помните, то, что написано до стрелки, — это указатель на структуру, а не переменная-структура.
Пример кода с использованием указателей:
#include struct circle { int x, y; float dia; }; void inversion (struct circle *); int main () { struct circle cir, *pc = ○ pc->x = 10; pc->y = 7; pc->dia = 6; inversion(pc); printf("x = %d, y = %d\n", cir.x, cir.y); } void inversion(struct circle *p) { p->x = -p->x; p->y = -p->y; }
Массивы структур
Обычно создание в программе одной переменной структурного типа не имеет особого смысла. Чаще структурами пользуются, когда необходимо описать множество похожих объектов, имеющих разные значения признаков. Значения каждого объекта следует объединить вместе (в структуру) и тем самым отделить от значений других объектов. Например, описание ряда книг или множества людей. Таким образом мы можем организовать массив, где каждый элемент представляет собой отдельную структуру, а все элементы принадлежат одному и тому же структурному типу.
Напишем программу для учета персональных компьютеров в организации. Каждая структура будет описывать определенные модели и содержать поле, в котором будет указано количество таких объектов. Поэтому при объявлении структурного типа данных следует описать такие поля как тип компьютера, модель процессора, количество.
Программа будет предоставлять возможность получать информацию о всех моделях и изменять количество компьютеров указанной пользователем модели. В программе будут определены две функции (помимо main() ): для вывода всей информации и для изменения количества компьютеров.
#include #define N 5 struct computer { char *type; char *proc; int qty; }; void viewer (struct computer *); void changer (struct computer *); int main () { struct computer comps[N]= { "Desktop", "earlier then P4", 10, "Desktop", "P4", 30 , "Desktop", "Core", 20 , "Desktop", "AMD", 2 , "Notebook", "Core", 1 }; viewer(comps); changer(comps); viewer(comps); } void viewer (struct computer *comp) { int i; for (i=0; i N; i++, comp++) printf("%2d) %-8s - %-15s: %3d\n", i+1, comp->type, comp->proc, comp->qty); } void changer (struct computer *comp) { int i, differ; printf("Введите номер модели: "); scanf("%d", &i); i--; printf( "На сколько уменьшить или увеличить: "); scanf("%d", &differ); (comp+i)->qty += differ; }
- Массив структур инициализируется при его объявлении.
- Функции viewer() и changer() принимают указатели на структуру computer.
- В теле viewer() указатель инкрементируется в заголовке цикла; таким образом указывая на следующий элемент массива, т.е. на следующую структуру.
- В выражении (comp+i)->qty скобки необходимы, т.к оператор -> имеет более высокий приоритет. Скобки позволяют сначала получить указатель на i-ый элемент массива, а потом обратиться к его полю.
- Декрементирование i в функции changer() связано с тем, что индексация начинается с нуля, а номера элементов массива, которые пользователь видит на экране, с единицы.
- Для того, чтобы уменьшить количество компьютеров, при запросе надо ввести отрицательное число.
Пример результата работы программы:

Придумайте свою программу, в которой бы использовался массив структур, или перепишите приведенную выше программу и дополните ее функцией, которая позволяет добавлять в массив новый элемент-структуру.
Курс с решением части задач:
pdf-версия