МУ_ЛР6_ОП (Методические указания к лабораторным работам), страница 3
Описание файла
Файл "МУ_ЛР6_ОП" внутри архива находится в папке "Методические указания к лабораторным работам". Документ из архива "Методические указания к лабораторным работам", который расположен в категории "". Всё это находится в предмете "программирование на основе классов и шаблонов" из 2 семестр, которые можно найти в файловом архиве МГТУ им. Н.Э.Баумана. Не смотря на прямую связь этого архива с МГТУ им. Н.Э.Баумана, его также можно найти и в других разделах. Архив можно найти в разделе "книги и методические указания", в предмете "программирование на основе классов и шаблонов" в общих файлах.
Онлайн просмотр документа "МУ_ЛР6_ОП"
Текст 3 страницы из документа "МУ_ЛР6_ОП"
day dw = sun; // mon = 6
Можно задать перечисления с произвольными значениями:
enum { Сon1=5 , Сon2=8, Сon3=15 };
printf("Перечисления с произвольными значением: Сon1=%d Сon2=%d Сon3=%d\n" , Сon1 , Сon2, Сon3 );
// Проверка значений перечислений в операторе ветвления
int m = Сon1;
if( m ==Сon1 )
printf("значение: Сon1 , m =%d\n" , m );
else
printf("значение: не Сon1 \n" );
Можно задать перечисления с одним базовым значением:
enum { Сonst1=5 , Сonst2, Сonst3 };
Результат будет таким:
Перечисления с базовым значением: Const1=5 Const2=6 Const3=7
19 Союзы – union - объединения
Объединение — это место в памяти, которое используется для хранения переменных, разных типов. Можно задавать разные имена, одним и тем же полям оперативной памяти. Покажем на примере. Пусть есть объединение ( три разных типа: int , float и сhar *).
// Объединения union
union u_tag {
int ival;
float fval;
char *sval;
} u;
После описания новой переменной () и выполнения операций по занесению данных получим следующий результат:
u_tag U1; // u_tag – это почти новый тип данных!!!!
U1.ival = 5;
printf("Поле объединения в целом формате: u.ival=%d\n" , U1.ival );
U1.fval = 0.5f;
printf("Поле объединения в действительном формате: u.ival=%5.2f\n" , U1.fval );
printf("Поле объединения в целом формате: u.ival=%d\n" , U1.ival );
U1.sval = new char[] = "Строка";
printf("Поле объединения в символьном формате: u.ival=%s\n" , U1.sval );
Результат будет таким:
Поле объединения в целом формате: u.ival=5
Поле объединения в действительном формате: u.ival= 0.50
Поле объединения в целом формате: u.ival=1056964608
Поле объединения в символьном формате: u.ival=Строка
20 Примеры программы с использованием структур
Вторая часть задания, помимо первой связанной с изучением теоретического раздела заключается в том, чтобы испытать в проекте СИ уже отлаженные программы и фрагменты программ. Возможно, что, осваивая теоретическую часть работы, вы уже на компьютере проверили выполнение фрагментов текста и применения различных операторов ветвления (из раздела 3), тогда вам будет проще продемонстрировать их работу преподавателю. В дополнение к примерам, расположенным выше нужно испытать и изучить примеры расположенные ниже. Эти действия нужно сделать в отладчике.
Для этого нужно создать пустой проект в MS VS (Test_LR2), как описано выше, скопировать через буфер обмена в него текст данных примеров, отладить его и выполнить.
21 Примеры, описанные в теоретической части ЛР
Нужно внимательно изучить и проверить работу всех примеров из теоретической части ЛР. Эти примеры расположены выше. Все примеры можно скопировать в свой проект. Все эти задания выполняются обязательно, они не требуют дополнительной отладки и легко (через буфер обмена -Clipboard) переносятся в программу. Все фрагменты должны демонстрироваться преподавателю. В частности, в первой части, там представлены следующие примеры:
-
Описание простой структур Student, Complex, Date, Person.
-
Демонстрация примеров инициализации структур.
-
Работа со структурами через указатели и квалифицированные ссылки.
-
Многоуровневая квалификация полей в структурах.
-
Использование указателей для доступа к полям структур.
-
Демонстрация передачи структур в функцию и указателей на структуры.
-
Использование массивов структур.
-
Показать использование вложенных структур и доступа к полям.
-
Показать определение размера структуры.
-
Пример использования динамических структур и динамических строк в них.
-
Показать использование перечислений.
-
Показать использование объединений.
Кроме этого ниже представлены примеры, которые могут быть полезными, в том числе и при выполнении контрольных заданий. Их тоже нужно изучить и проверить.
22 Копирование и обмен статических структур
Если в структурных переменных все поля статические (фиксированный размер), то можно копировать структуру в целом. Отметим, что при копировании и обмене парметры для структур должны задаваться указателями. Пусть есть структура следующего вида:
struct Person { // Структура для примеров
char Name[20]; // Фамилия
int Kurs; // Курс
float Stipen; // Стипендия
};
…
/// Функции для структуры Person
void PersonPrint( Person P)
{
printf( "Имя - %s Курс - %d Стипендия - %6.2f р. \n" ,P.Name, P.Kurs , P.Stipen );
};
// Функции копирования и обмена структур
// Копирование структур персон
void CopyPerson( Person * P1 , Person * P2)
{
P1->Kurs = P2->Kurs;
P1->Stipen = P2->Stipen;
strcpy( P1->Name , P2->Name);
};
// Обмен статических структур
void SwapPerson( Person * P1 , Person * P2)
{
Person Temp;
CopyPerson( &Temp , P1);
CopyPerson( P1 , P2);
CopyPerson( P2 , &Temp);
};
…
// Прототипы функций в главной программе, если нужно
void PersonPrint( Person P);
void CopyPerson( Person * P1 , Person * P2);
void SwapPerson( Person * P1 , Person * P2);
…
// Вызов функций из главной программы
// Печать структуры
Person Stud ;//
// Заполнение структуры вручную
strcpy (Stud.Name , "Петров");
Stud.Kurs = 2;
Stud.Stipen = 2000.00f ;
// печать
PersonPrint ( Stud );
// Инициализация структуры
Person StudNew= {"Аксенова" , 10 , 50000.0f} ;//
PersonPrint ( StudNew );
//////////////////////
// Копирование и обмен
Person S11= {"Аксенова" , 10 , 50000.0f} ;//
Person S21= {"Большаков" , 11 , 60000.0f} ;
Person S31;
//
printf("Copy функцией: \n");
// Копирование
CopyPerson( &S31 , &S21);
PersonPrint ( S31 );
PersonPrint ( S21);//
Для копирования структур без динамики можно использовать функции RTL (memcpy):
// Копирование структур средствами RTL
printf("Непосредственно в ОП - memcpy: \n");
Person Stud1 = { "Сидоров" , 1 , 100.00f};
Person Stud2 = { "" , 0 , 0.00f};
PersonPrint ( Stud1 );
PersonPrint ( Stud2 );
// Stud2 = Stud1; // Это возможности С++
memcpy ( &Stud2 , &Stud1 , sizeof (Person) ) ; // Так можно если нет указателей
PersonPrint ( Stud2 );
//
printf("Swap: \n");
PersonPrint ( S11 );
PersonPrint ( S21);
// Замена
SwapPerson( &S11 , &S21);
PersonPrint ( S11 );
PersonPrint ( S21);
//
Результат вызова функций имеет вид:
Имя - Петров Курс - 2 Стипендия - 2000.00 р.
Имя - Аксенова Курс - 10 Стипендия - 50000.00 р.
Copy функцией:
Имя - Большаков Курс - 11 Стипендия - 60000.00 р.
Имя - Большаков Курс - 11 Стипендия - 60000.00 р.
Непосредственно в ОП - memcpy:
Имя - Сидоров Курс - 1 Стипендия - 100.00 р.
Имя - Курс - 0 Стипендия - 0.00 р.
Имя - Сидоров Курс - 1 Стипендия - 100.00 р.
Swap:
Имя - Аксенова Курс - 10 Стипендия - 50000.00 р.
Имя - Большаков Курс - 11 Стипендия - 60000.00 р.
Имя - Большаков Курс - 11 Стипендия - 60000.00 р.
Имя - Аксенова Курс - 10 Стипендия - 50000.00 р.
23 Функция Swap для структур с динамикой строк
Рассмотрим простую структуру с динамическими строками. При инициализации структуры нужно выделять динамическую память под имя и фамилию. У нас предусмотрена функция печати структуры (StudentPrint) и обмена структур с учетом динамики (SwapStudent).
//
struct Student { // Структура с динамическими строками
char * pName; // Динамические строка
char * pFam; // Динамические строк
int Kurs;
float Stipen;
};
// Функция печати
void StudentPrint( Student S)
{
printf( "Фамилия - %s Имя - %s Курс - %d Стипендия - %6.2f р. \n" ,S.pFam,S.pName,
S.Kurs , S.Stipen );
};
// Функция обмена
void SwapStudent( Student * pA , Student * pB )
{ // 1) Temp = a , 2) a = b , 3) b = Temp => Обычный обмен!!!
Student Temp;
//1)
Temp.Kurs = pA->Kurs;
Temp.Stipen = pA->Stipen;
Temp.pName = (char *) malloc ( strlen(pA->pName) + 1);
Temp.pFam = (char *) malloc ( strlen(pA->pFam) + 1);
strcpy ( Temp.pName , pA->pName);
strcpy ( Temp.pFam , pA->pFam);
free ( pA->pName);
free ( pA->pFam);
//2)
pA->Kurs = pB->Kurs;
pA->Stipen = pB->Stipen;
pA->pName = (char *) malloc ( strlen(pB->pName) + 1);
pA->pFam = (char *) malloc ( strlen(pB->pFam) + 1);
strcpy ( pA->pName , pB->pName);
strcpy ( pA->pFam , pB->pFam);
free ( pB->pName);
free ( pB->pFam);
//3)
pB->Kurs = Temp.Kurs;
pB->Stipen = Temp.Stipen;
pB->pName = (char *) malloc ( strlen(Temp.pName) + 1);
pB->pFam = (char *) malloc ( strlen(Temp.pFam) + 1);
strcpy ( pB->pName , Temp.pName);
strcpy ( pB->pFam , Temp.pFam);
free ( Temp.pName);
free ( Temp.pFam);
};
Прототипы функций в главной программе:
void StudentPrint( Student S);
void SwapStudent( Student * pA , Student * pB );
Текст в главной программе: инициализация, распечатка, обмен и новая распечатка:
// Новая структура Student с динамическими строками (фамилия и имя)
Student Ivanov;
// Заполнение
Ivanov.Kurs = 5;
Ivanov.Stipen = 5000.00f ;
Ivanov.pFam = (char *) malloc (strlen ("Иванов") + 1) ; // Инициализация
Ivanov.pName = (char *) malloc ( strlen ("Иван") + 1 ) ;
strcpy ( Ivanov.pFam , "Иванов" );
strcpy ( Ivanov.pName , "Иван" );
StudentPrint( Ivanov);
// Неявное выделение динамической памяти
Student Sidorov = { "Сидор" , "Сидоров" , 3 , 2000.0f};
StudentPrint( Sidorov);
// Если изменить имя для структуры Sidorov
//strcpy ( Sidorov.pName , "Иван" ); // и это ошибка, так как pName указывает на строку - константу
// Нужно выделить динамическую память для того, чтобы работали указатели!!
Sidorov.pName =(char *) malloc (strlen ("Петр") + 1);
strcpy ( Sidorov.pName , "Петр" );
Sidorov.pFam =(char *) malloc (strlen ("Петров") + 1);
strcpy ( Sidorov.pFam , "Петров" );
StudentPrint( Sidorov);
//SWAP для структуры Student
StudentPrint( Sidorov);
StudentPrint( Ivanov);
SwapStudent( &Sidorov , &Ivanov ); // Обмен динамических структур
StudentPrint( Sidorov);
StudentPrint( Ivanov);
// Освободить динамическую память под строки
free (Ivanov.pFam);
free (Ivanov.pName);
free (Sidorov.pFam);
free (Sidorov.pName);
//
Результат вызова функций имеет вид:
Фамилия - Иванов Имя - Иван Курс - 5 Стипендия - 5000.00 р.
Фамилия - Сидоров Имя - Сидор Курс - 3 Стипендия - 2000.00 р.
Фамилия - Петров Имя - Петр Курс - 3 Стипендия - 2000.00 р.
Фамилия - Петров Имя - Петр Курс - 3 Стипендия - 2000.00 р.
Фамилия - Иванов Имя - Иван Курс - 5 Стипендия - 5000.00 р.
24 Заполнение Rand числовых (целых и вещественных) полей массива структур
// Заполнение массива структур случайными числами
const int Rzm = 6;
Student Potok[ Rzm ];
// Для запуска новой последовательности случайных чисел
srand( (unsigned) time( NULL ) );
//srand( (unsigned) NULL ); // Если NULL то при новом запуске программы последовательность //повторяется
for (int i = 0 ; i < Rzm ; i++ )
{ // Локальные буфера
char Buf[20];
char Num[5];
char Buf2[20];
char Num2[5];
//
strcpy(Buf , "Stud № - "); // Фамилия
strcpy(Buf2 , "Num - "); // Имя
int k = ( i < Rzm/2 ) ? 1 : 2 ; // Курс для целого – условное выражение
float St = 1000.0f * 10.0f * rand() / RAND_MAX ; // Стипендия 0 - 10000 Для вещественных
int n = (rand()*99)/ RAND_MAX ; // 0 - 99 – номер добавка для фамилии
strcat(Buf , itoa (n + 1 ,Num, 10 ));
n = (rand()*30)/ RAND_MAX ; // 0 - 30 - номер добавка для имени
strcat(Buf2 , itoa (n + 1 ,Num, 10 ));
strcat(Buf , " ");