
Лаб по С и С++ / Лаб_C_№10_№11
.docЛабораторная работа по структурам.
Изучить материал и продемонстрировать умение работать со структурами в том числе:
-
описать шаблон структуры (в том числе вложенные структуры, структуры, содержащие объединение);
-
уметь объявить структурную переменную, массив структур, указатель на структуру, массив указателей на структуру;
-
уметь обращаться к полям структуры через имя структуры, указатель на структуру, элемент массива структур;
-
максимально просто копировать поля одной структуры в другую (пример 1);
-
Научаться максимально быстро записывать и считывать из файла данные
-
уметь передать структуру в функцию через параметры функции и, возможно, передать структуру в качестве результата;
ПРИ НАПИСАНИИ ПРОГРАММЫ
-
Взять за основу программу консольного приложения .
-
Исходить из принципа модульного программирования:
-
отдельные функции должны быть написаны в соответствии с основными принципами построения функции (каждая функция решает только одну задачу, исходные данные передаются через параметры, результат всегда передается в вызывающую функцию);
-
разбить весь текст на раздел описаний и раздел реализаций. Раздел описаний (файл с расширением *.h) содержит заголовочные файлы, макроопределения, описания внешних переменных, прототипы собственных функций. Раздел реализаций (один или несколько файлов с расширением *.с) содержит тексты самих функций.
-
Сборку программы производить с помощью файла проекта
-
Написать по тексту комментарии, особенно в файле описаний.
ПРИ ЗАЩИТЕ РАБОТЫ
1. Уметь выполнить программу.
2. Изложить узловые моменты и особенности алгоритма.
3. Дать объяснение любому оператору программы по требованию преподавателя.
1. Работа с файлами в C ( работает и в C++ )..
#include <iostream.h> #include <stdio.h> void main( void ) { FILE *file; char* file_name = "file.txt"; char load_string[50] = "none"; file = fopen( file_name, "w" ); fputs( "string", file ); fclose( file ); file = fopen( file_name, "r" ); if( file != 0 ) { fgets( load_string, 50 , file ); cout << "load_string = " << load_string << endl; } else { cout << "File not found !!!" << endl; } fclose(file); }
Описание функций работы с файлами находятся в библиотеке stdio.h Сначала надо создать указатель на переменную типа FILE ( FILE* file; ). Открытие файла производится вызовом функции fopen ( file = fopen( file_name, "w" ); )
Первый параметр этой функции - имя файла, второй - указывает в каком режиме должен быть открыт файл. "w" - открыть для записи, "r" - открыть для чтения, "a" - дополнение файла( это наиболее используемые режимы, хотя есть и другие ). Запись и считывание данных из файла осуществляется следующими функциями : fputc, fputs, fgetc, fgets, fprintf, fscanf( описание этих функций смотрите в stdio.h). Закрытие файла осуществляется вызовом функции fclose ( fclose( file ); ). (* см. ниже*)
СТРУКТУРЫ
Успех программы часто зависит от удачного выбора способа представления данных. С помощью структур возможно моделировать сложные объекты, возникающие при решении задач. Структуры представляют средство для доступа к записям, которые содержат поля одного или нескольких типов.
Для использования структуры необходимо:
1. установить шаблон для структуры
2. объявить переменную, соответствующую этому шаблону
3. осуществить доступ к компонентам структуры.
Шаблон структуры
Шаблон - это схема, описывающая содержание структуры. Установка структурного шаблона телефонный справочник:
struct sprav
char fio[20];
long num;
;
Данный шаблон описывает структуру с именем типа структуры sprav, состоящую из двух компонентов: строки fio и целой пе-
ременной num типа long.
Имя типа структуры sprav необязательно и используется для ссылки на эту структуру.
Компоненты структуры - данные любого типа, включая и другие структуры. Имя внутри структуры может быть таким же, как имя объекта вне структуры.
Если шаблон описан внутри функции - он доступен только этой функции, если шаблон описан вне функции - он доступен любой функции программы.
Установка шаблона не вызывает никаких действий в программе.
Структурные переменные
Объявление структурных переменных приводит к выделению памяти для компонент структуры, куда можно записать данные или
откуда можно прочитать их.
Для объявления структурных переменных имеются несколько способов.
1. Установить структурный шаблон: struct sprav
char fio[20];
long num;
;
Объявить простую переменную, массив структур, указатель на структуру:
struct sprav tel1, tel2[5], *tel3;
2. Установить структурный шаблон с помощью макроопределения: #define SPRAV struct sprav
SPRAV
char fio[20];
long num;
;
Объявить переменные:
SPRAV sp1, sp2[6], *sp3;
3. Объявить переменные одновременно с установкой шаблона (если на данную структуру вы больше не ссылаетесь):
struct
char fio[20];
long num;
tel1, tel2[3], *tel3;
4. Ввести новый тип данных (TEL)-структура определенного вида: typedef struct
char fio[20];
long num;
TEL;
Объявить переменные нового типа:
TEL tel1, tel2[6], *tel3;
Если программа достаточно объемна, представляется более удобным четвертый способ.
Инициализация структуры
Инициализировать можно только внешние или статические структуры.
static struct
char fio[20];
long num;
tel[2]=
"Иванов Ф.А.", 456756,
"Петров В.П.", 632345
;
Доступ к компонентам структуры
Доступ к компонентам структуры продемонстрируем с помощью примеров.
Пример 1.
/* Обращение к элементам структуры через имя переменной */
#include <stdio.h>
#include <conio.h>
void main(void)
struct
char fio[20]; /* фамилия */
long num; /* телефон */
tel1, tel2;
clrscr();
puts("введите фио абонента-");
gets(tel1.fio);
puts("введите его номер-");
scanf("%ld",&tel1.num);
tel2=tel1; /* нельзя так же сравнивать структуры */
puts("Введено:");
printf("Фамилия :%s номер: %ld\n",tel2.fio,tel2.num);
Пример 2.
/* Динамическое выделение памяти для структуры */
/* Обращение к элементам структуры через указатель */
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
struct sprav
char fio[20];
long num;
;
void main(void)
struct sprav *tel1, *tel2;
clrscr();
/* Выделение памяти для структуры */
tel1=(struct sprav *)malloc(sizeof(struct sprav));
tel2=(struct sprav *)malloc(sizeof(struct sprav));
puts("введите фио абонента-");
gets(tel1->fio);
puts("введите его номер-");
scanf("%ld",&tel1->num);
*tel2= *tel1;
puts("Введено:");
printf("Фамилия :%s номер: %ld\n",(*tel2).fio,(*tel2).num);
Массив структур
Пример 3.
/* Массив структур. Обращение к элементам структуры через */
/* имя элемента массива */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define SPRAV struct sprav
void main(void)
SPRAV
char fio[20];
long num;
;
SPRAV tel[5]; /* массив структур - 5 элементов */
char fio_tek[20];
int i;
clrscr();
/* ввод данных в массив структур */
for(i=0; i<5; i++)
puts("введите фио абонента-");
gets(tel[i].fio);
puts("введите его номер-");
scanf("%ld",&tel[i].num);
getchar();
puts("Выбор телефона по фамилии");
gets(fio_tek);
/* поиск структуры по фамилии абонента */
for(i=0; i<5; i++)
if(!strcmp(fio_tek,tel[i].fio)) break;
if(i!=5) /* цикл закончен по break */
printf("номер абонента %s равен %ld\n",fio_tek, \
tel[i].num);
else /* цикл выполнился полностью */
puts("Абонент не найден");
Пример 4.
/* Массив структур. Память выделяется динамически. */
/* Обращение к элементам структуры через указатель */
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <alloc.h>
typedef struct
char fio[20];
long num;
TEL;
void main(void)
TEL *tel;
char fio_tek[20];
int i;
clrscr();
/* Выделение памяти для массива - 3 элемента */
tel=(TEL *)malloc(sizeof(TEL)*3);
for(i=0; i<3; i++)
puts("введите фио абонента-");
gets((tel+i)->fio);
puts("введите его номер-");
scanf("%ld",&(tel+i)->num);
getchar();
puts("Выбор телефона по фамилии");
gets(fio_tek);
for(i=0; i<5; i++,tel++)
if(!strcmp(fio_tek,tel->fio)) break;
if(i!=5)
printf("номер абонента %s равен %ld\n",fio_tek, \
tel->num);
else
puts("Абонент не найден");
Передача структуры в функцию
Непосредственный доступ к компонентам структуры - плохой стиль программирования. Все операции, которые разрешены применительно к структуре, должны быть при этом реализованы в виде отдельных функций.
Не все компиляторы языка Си позволяют передавать структуры в функцию по значению, поэтому в примерах передача структуры идет через указатель.
Пример 5.
/* Передача структуры в функцию через указатель на структуру */ /* Определение комплексного числа через структуру и действия */ /* над комплексными числами ( ввод, вывод, вычисление суммы) */ #include <stdio.h>
typedef struct float a; /* действительная часть */
float b; /* мнимая часть */
COMPLEX;
void vvod(COMPLEX *,float,float);
void sum(COMPLEX *,COMPLEX *,COMPLEX *);
void out(COMPLEX *);
void main(void)
COMPLEX x,y,z;
vvod(&x,2.5,6.7);
vvod(&y,6.89,8.45);
puts("Введены числа:");
out(&x);
out(&y);
sum(&x,&y,&z);
puts("Сумма комплексных чисел равна:");
out(&z);
/* Вывод комплексного числа */
void out( COMPLEX *p)
printf("(%.2f,%.2f)\n", (*p).a,(*p).b);
return;
/* Вычисление суммы двух комплексных чисел */
void sum(COMPLEX *p1,COMPLEX *p2,COMPLEX *p3)
(*p3).a=(*p1).a+(*p2).a;
(*p3).b=(*p1).b+(*p2).b;
return;
/* Ввод значений для элементов структуры */
void vvod(COMPLEX *p,float a, float b)
p->a=a;
p->b=b;
return;
Вложенные структуры
Структура, являющаяся компонентом другой структуры, называется вложенной.
Пример 6.
/* Даны четыре точки - центры четырех окружностей.
Заполнить структуру окружность, если все окружности проходят через начало координат.
*/
#include<conio.h>
#include<stdio.h>
#include<math.h>
#include<stdlib.h>
struct POINT
float x;
float y;
;
struct CIRCLE
struct POINT point; /* вложенная структура */ double r;
circle[2], *p;
void main (void)
int i,j;
float a,b,c,d;
clrscr();
gotoxy(17,1);
cputs("ВВЕДИТЕ КООРДИНАТЫ ТОЧЕК :\r\n");
for(i=0;i<2;i++)
cprintf ("\n\n ВВЕДИТЕ X: ");
cprintf ("X[%d]= ",i+1); cscanf("%f",&circle[i].point.x);
cprintf ("\n ВВЕДИТЕ Y: ");
cprintf ("Y[%d]= ",i+1);
cscanf ("%f",&circle[i].point.y);
p=circle;
gotoxy(17,12);
cputs("РЕЗУЛЬТАТ:\r\n\n");
for(i=0;i<2;i++)
a=p->point.x;
b=p->point.y;
c=sqrt(a*a+b*b);
p->r=c;
cprintf("\nРАДИУС : %lf ЦЕНТР (%f,%f)\r\n",p->r,a,b); p++;
ФУНКЦИИ ВВОДА И ВЫВОДА ВЕРХНЕГО УРОВНЯ
Функции ввода и вывода в стандартной библиотеке Си позволяют читать данные с клавиатуры, диска или порта ввода-вывода и выводить результат на терминал, диск или порт ввода-вывода.
Функции ввода/вывода делятся на группы:
1. ввод/вывод верхнего уровня
2. ввод/вывод системного уровня
3. ввод/вывод для консольного терминала
4. ввод/вывод через порт.
Для пользователя файл, открытый на верхнем уровне, представляется как последовательность считываемых или записываемых байтов. Чтобы отразить эту особенность, используется понятие "поток" (stream).
Функции ввода/вывода работают с буферизацией. Обмен информацией происходит не между программой и файлом, а между программой и буфером, расположенным в оперативной памяти.
Буферизация ускоряет работу программы из-за уменьшения количества обращений к внешним устройствам.
Чтобы получить доступ к файлу, необходимо связать его с соответствующей структурой типа FILE, объявленной в stdio.h и содержащей разнообразную информацию о файле. Эта операция называется открытием файла и осуществляется с помощью функции fopen, которая в качестве результата возвращает указатель на структуру FILE - указатель файла. Указатель файла в дальнейшем используется функциями для ввода/вывода информации в файл.
Указатель файла позиционируется в соответствии с открытием потока: если поток открыт для чтения - на начало файла, если для дозаписи - на конец файла. Указатель файла изменяется в соответствии с операцией записи или чтения.
После окончания ввода/вывода поток необходимо закрыть с помощью функции fclose или fcloseall, после чего указатель файла можно использовать для последующего открытия файла.
Потоки бывают текстовые или двоичные (по умолчанию - текстовые). При вводе текстового потока система Турбо Си преобразует символы возврат коретки и перевод строки в символ перевода строки, а при выводе текстового потока в среду операционной системы происходит обратное преобразование.
При вводе/выводе двоичного потока никаких преобразований не происходит.
При выполнении любой программы автоматически открываются пять стандартных потоков, имеющих следующие указатели файлов: stdin - поток ввода, stdout - поток вывода, stderr - поток вывода для сообщений об ошибках ( для вывода в поток stderr используется функция perror ), stdaux - последовательный порт и stdprn - устройство печати. Первые три потока по умолчанию связываются с консольным терминалом. Имена указателей стандартных потоков ввода/вывода могут указываться в функциях ввода/вывода.
Для переопределения стандартных потоков используется функция freopen.
Прототипы функций ввода/вывода описаны в stdio.h, и там же объявлен ряд макроопределений, в том числе NULL - нулевой байт, EOF - символ конца файла, BUFSIZ - размер буфера.
Далее приводятся описания прототипов функций с кратким пояснением.
Доступ к файлу
FILE * fopen(char *pathname, char *type);
функция открывает файл (имя задает первый аргумент) для
(второй аргумент):
"r" - чтения существующего файла
"w" - записи (перезаписи) файла
"a" - записи (дозаписи) файла
"r+" - чтения и записи существующего файла
"w+" - чтения и записи (перезаписи) файла
"a+" - чтения и записи (дозаписи) файла.
В конец строки записывается t - текстовый режим или b - двоичный режим. Например: "rt" , "w+b".
Возврат при ошибке: NULL.
Закрытие потока
int fclose(FILE *stream);
int fcloseall(void);
Возврат при ошибке: EOF.
Конец файла
int feof(FILE *stream);
Возврат: 0 - не конец файла, иначе - конец файла.
Данные в файле могут быть организованы как:
1. непрерывный поток символов
2. последовательность строк переменной длины
3. форматированные поля, разделенные определенным символом
4. последовательность записей фиксированной длины.
В соответствии с этим разделим функции ввода/вывода верхнего уровня на группы.
Ввод/вывод символа
int getchar(void); - ввод из stdin
int putchar(int); - вывод в stdout
int fgetc(FILE *stream); - ввод из потока
int fputc(int c, FILE *stream); - вывод в поток
int getc(FILE *stream); - ввод из потока
int putc(int c,FILE *stream); - вывод в поток
int ungetc(char c, FILE *stream); - возврат введенного символа в поток.
Возврат при ошибке: EOF.
Построчный ввод/вывод
char * fgets(char *s,int n, FILE *stream); - cтрока из входного потока помещается в s (не более n-1 символа).
char * gets(char *s); - строка из stdin помещается в s.Возврат при ошибке: NULL.
int fputs(char *s, FILE *stream); - cтрока помещается в вы ходной поток.
int puts(char *s); - cтрока помещается в stdout.
Возврат при ошибке: EOF.
Форматный ввод/вывод
int fprintf(FILE *stream,<строка формата>,<список имен>); форматный вывод в поток.
int fscanf(FILE *stream,<строка формата>,<список адресов>); форматный ввод из потока.
int printf(<строка формата>,<список имен>); форматный вывод в stdout.
int scanf(<строка формата>,<список адресов>); форматный ввод из stdin. Ввод/вывод записей
int fread(void *bufer, int size, int count, FILE *stream); функция читает count элементов длины size из входного потока и помещает в bufer.
int fwrite(char *bufer, int size, int count, FILE *stream); функция дописывает count элементов длины size из области bufer в поток. Как правило, эти функции используются для ввода/вывода массивов и структур.
Внутреннее преобразование данных
int sprintf(char *s,<строка формата>,<список имен> ); вывод данных в строку.
int sscanf(char *s,<строка формата>,<список адресов>); ввод из строки по адресам.
Возврат при ошибке: EOF.
Прямой доступ к файлу
int fseek(FILE *stream, long offset, int origin); - функция перемещает указатель файла на offset позиций относительно начала файла, если origin равно 0, текущей позиции, если origin равно 1, конца файла, если origin равно 2. Если значение offset положительно - движение вперед, иначедвижение назад. Возврат при ошибке: не нуль.
Текущая позиция в файле
long ftell(FILE *stream); - возвращает номер текущей позиции от начала файла.
Пример 1.
/* создание копии autoexec.bat в autoexec.bak */
#include<stdio.h>
void main (void)
{
/* указатели входного и выходного потоков */
FILE *in, *out;
/* открытие входного потока */
if((in=fopen("\\autoexec.bat","rt"))==NULL)
{
fprintf(stderr, "cannot open input file\n");
exit(1);
}
/* открытие выходного потока */
if((out=fopen("autoexec.bak","wt"))==NULL)
{
fprintf(stderr, "cannot open output file\n");
exit(1);
}
/* символ из входного потока записать в выходной */
while(!feof(in))
fputc(fgetc(in), out);
/* закрытие потоков */
fclose(in);
fclose(out);
}
Пример 2.
/* внутреннее преобразование данных - из строки в float */
#include<stdio.h>
void main (void)
{
char s[20];
float chislo;
puts("\nввод числа");
gets(s);
sscanf(s,"%f",&chislo);
printf("полученное число %f\n", chislo);
}
Пример 3.
/* прямой доступ к файлу - печать 21-го символа из ес.bat */
/* в результате печатается n */
#include<stdio.h>
void main (void)
{
FILE *in, *out;
if((in=fopen("ec.bat","rt"))==NULL)
{
fprintf(stderr, "cannot open input file\n");
exit(1);
}
/* сместить указатель файла на 20 позиций от начала файла */
fseek(in,20L,0);
fprintf(stdout,"21-ый символ равен %c\n", fgetc(in));
}
/* содержимое ec.bat */
rrrrrrrrrrrrrrrrrrrdnyyyy
ЗАДАНИЕ
Условия выбора варианта
подгруппа |
1 |
2 |
3 |
4 |
№ машины |
№ варианта |
№ варианта |
№ варианта |
№ варианта |
1 |
1 |
11 |
6 |
10 |
2 |
2 |
12 |
7 |
9 |
3 |
3 |
13 |
8 |
8 |
4 |
4 |
14 |
9 |
7 |
5 |
5 |
15 |
10 |
6 |
6 |
6 |
1 |
11 |
5 |
7 |
7 |
2 |
12 |
4 |
8 |
8 |
3 |
13 |
3 |
9 |
9 |
4 |
14 |
2 |
10** |
10 |
5 |
15 |
1 |
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - книги.
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - ценная бумага
-
. Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - товар.
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - сотрудник учреждения
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - игрушка.
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - ученик
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - автомобиль.
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - пассажир
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - банк
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - осадки
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - дневная температура
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - сессия
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - ценная бумага
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - телефонный справочник
-
Определить шаблон структуры на заданную тему, состоящий из полей различного типа.. Количество структур, если не оговорено особо, в пределе 10 необходимо создать массив типа структура, заполнение данных в массив, поиск, удаление и редактирование. Структура - квартира