Слайд 2
Определение структурных переменных
Определим структурную переменную kn1:
book kn1;
// book - тип переменной; kn1 — имя
переменной;
book *uk_book;
//*uk_book - указатель на структуру book
Определение структурной переменной без предварительного объявления типа:
struct book
{
int а; float b;
} z1, z2;
//z1, z2 - две переменных типа struct;
Слайд 3
Принадлежность к внешнему типу определяется местом объявления структурной
переменной, а не типа.
book kn1={"Ивaнов H.И.","физика", 2009, 175}; //инициализация
Для
доступа к элементам структуры используются составные имена: <имя переменной>.<имя элемента>
book kn1;
kn1.author //имя символьного массива[20] – адрес
kn1.name //имя символьного массива[60]
kn1.year, kn.price //имена переменных типа int
&kn1.price //адрес
Эти имена могут быть использованы так же, как и обычные имена переменных этого же типа, например:
kn1.author[6] = 'а';
scanf("%d",&kn1.price);
kn1.year =2013 ;
* (kn1. author+1) = 'p' ;
gets(kn1.name);
Слайд 4
Массивы структур
kniga kns[3]; // массив из трех структур
kns[0].author
//указатель на массив;
kns[1].year //третий элемент второй структуры;
kns[2].name[0] //первый символ
названия.
Номер элемента массива всегда указывается после имени.
Слайд 5
Вложенные структуры
Элементом структуры может быть другая структура, например
Книга
Автор
Название
Год
Цена
Отчество
Имя
Фамилия
struct
book1
{
author avt; /*Вложенная структура */
char name[60];
int year,
price;
};
struct author
{
char fam[15];
char im[10] ;
char ot[15];
};
Слайд 6
Указатели на структуры
Использование указателей на структуры удобно по
трем причинам:
так же, как и указатели на массивы, они
проще в использовании, чем сами массивы;
во многих способах представления данных используются структуры, содержащие указатели на другие структуры;
указатель на структуру удобно передавать в функцию.
Слайд 7
Определение переменной и инициализация
/ * инициализация */
book1 kn09
= { {"Иван","Иванович","Иванов“}, "физика", 2009, 175 };
Доступ: kn09.avt.fam[1]='p';
//Иванов
author avt1;
author *ukavt;
book1 *ukknig; /* объявление двух указателей на структуры */
Все операции с указателями, используемые для обычных переменных, можно применять и к структурным переменным, например
ukavt=&avt1;
ukknig=&kn09;
Имя структуры - это не адрес!
book1 kni[100]; //массив структур
ukknig=kni; ukknig=&kni[0];
ukknig=kni+1; ukknig=&kni[1];
Прибавление "1" к указателю увеличивает ero значение (адрес) на число байтов, которое занимает соответствующий тип.
ukknig++; ukknig=&kni[2]; *ukknig=kni[2];
Слайд 8
Операции над структурами
Присваивание: struct book
kn1,kn2; kn2=kn1;
Сравнение структур - сравниваются поля.
Доступ к элементу структуры выполняется при помощи указателя:
struct avtor *ukavt, avt1;
//ukavt - указатель на структуру,
//avt1 - переменная структурного типа
ukavt=&avt1; //указатель ссылается на avt1
avt1.im [0] ='B';
Слайд 9
С помощью указателя ukavt можно получить доступ к
элементу одним из двух способов:
Операция присоединения
ukavt=&avt1; ukavt->im[0]= 'а';
Структурный
указатель, за которым следует операция ->, работает так же, как имя структуры с последующей операцией «точка». Нельзя записать ukavt. im [ 0 ] т.к. ukavt - не является именем структуры.
ukavt - указатель,
ukavt->im [ 0 ] - элемент структуры, на которую настроен указатель (элемент имеет тип char).
Составное имя
(*ukavt ).im[0]= ‘Е';
Круглые скобки необходимы, т.к. операция "." имеет более высокий приоритет, чем "*".
Содержимое по адресу ukavt:
ukavt=&avt1; *ukavt=*(&avt1);
//т.е. *ukavt=avt1;
Слайд 10
Передача информации о структурах в функцию
Структуру можно использовать
в качестве формального параметра функции.
Можно передавать в качестве
фактического параметра элемент структуры или его адрес.
#include
struct pr
{
int a;
float b;
};
int ab (int a, float *b)
{*b=2.5*(float)a;
return (2*a);
}
int main()
{ int c; pr pr1;
scanf ("%d", &pr1.a);
/* адрес элемента */
c=ab(pr1.a, &(pr1.b));
printf("result= %d b=%10.5f\n",c,pr1.b);
return 0;
}
Слайд 11
Можно использовать адрес структуры в качестве фактического
параметра.
Объявим шаблон и переменные одновременно в задаче определения остатка
от деления целых чисел.
struct sab
{ int a,b; } pr1 = {23,3};
int ab1(sab *prim) //т.е. prim - указатель на структуру рr1
{
return (prim->a%prim->b); //остаток от деления
}
int main()
{
printf("Result=%d", ab1(&pr1) ) ;
return 0;
}
Слайд 12
Можно использовать имя массива структур в качестве фактического
параметра (то есть адрес первого элемента массива).
#include
/*найдём сумму
всех элементов всех структур*/
struct pr
{
int a; float b;
};
//глобальная
int main()
{ //в массиве 10 структур
int i;
float ab2(pr *prim); /*прототип функции*/
pr pr2[10];
puts("Input twenty numbers");
for(i=0; i<10; i++)
scanf("%d %f",&pr2[i].a, &pr2[i] .b);
printf( "sum=%f", ab2 (pr2) ) ;
/* рr2 — имя массива структур, адрес первой структуры. */
return 0;
}
float ab2(struct pr *prim)
{
int i;
float sum=0;
for(i=0; i<10; i++, prim++)
sum+=prim->a+prim->b;
return (sum);
}
Слайд 13
Текстовые файлы
Текстовый файл - последовательность символов
(кодов), разделенная на строки.
EOF – специальный символ для проверки
и обозначения конца файла. Определен в заголовочном файле stdio.h; ввод с клавиатуры этого символа соответствует нажатию клавиш CTRL+Z.
Возможны следующие операции:
int ch;
ch = EOF; //присваивание
if (ch == EOF) //проверка конца файла
Слайд 14
Обычно объявляется указатель на файлы, который используется в
функциях ввода/вывода, например:
FILE *fl;
Стандартные указатели на файлы определены в
FILE *stdin,*stdout ;
stdin - стандартный входной файл;
stdout - стандартный выходной файл.
Открытие файла. При открытии указывается способ использования файла (считывание, запись, добавление). Функция открытия файла fopen () :
FILE *fopen(char *filename, char *type);
Функция fopen () возвращает указатель на файл (если нельзя открыть, то NULL).
Функция fopen () имеет два аргумента:
filename – имя открываемого файла (может содержать путь);
type - способ использования (строка):
"r" – чтение;
"w" - запись ;
"a" – дополнение.
Слайд 15
FILE *fl ;
fl = fopen("prog1.res", "w");
Здесь prog1.res
- имя файла.
Закрытие файла осуществляется функцией fclose(), аргумент которой
- указатель на файл:
int fclose(FILE *fl);
fclose (fl) ;
При нормальном закрытии файла функция возвращает 0, в противном случае возвращает EOF .
Функция fcloseall () осуществляет закрытие всех потоков, освобождает буферы ввода/вывода, куда данные записываются перед их пересылкой в файл на диск. Буферы используются для ускорения обмена ОЗУ с дисками.
void rewind (FILE *fl) – устанавливает указатель в начало файла.
Слайд 16
Функции ввода и вывода
int fgetc(FILE *fl) ; -
чтение одного символа из файла fl. Возвращает код введенного
символа. Если достигнут конец файла или произошла ошибка, то вернет EOF.
int fputc(int c, FILE *fl); - вывод символа с кодом c в файл fl.
Форматный ввод/вывод
int fscanf(FILE *fl, "форматы", <список аргументов>);
int fprintf (FILE *fl, "форматы", <список аргументов>);
Обе функции возвращают количество успешно обработанных аргументов, при ошибке возвращается EOF.
Слайд 17
Ввод строки
char *fgets(char *str, int n, FILE *fl);
Функция
fgets () считывает из файла fl в строку str
символы до тех пор, пока не будет выполнено одно из условий:
начнется новая строка, т.е. встретится символ ‘\n’;
будет достигнут конец файла (EOF);
условия 1 и 2 не выполнены, но прочитано n-1 символов.
После считывания строка дополняется нуль символом '\0'. Если при чтении встретился символ конца строки, то он переносится в строку str и нуль-символ записывается за ним. Если считывание прошло успешно, то возвращается адрес строки str, в противном случае - NULL.
Напомним, функция gets () заменяет символ '\n' на '\0'. Считывание символов осуществляется из стандартного входного потока stdin. Если входной поток прерывается символом перехода на новую строку '\n‘, то он отбрасывается и не попадает в строку str.
Слайд 18
Пример: Символы переписываются функцией puts () в стандартный
выходной поток stdout, строка str дополняется символом конца строки
'\n'.
char str[10];
FILE *fl;
fl=fopen(“f1.txt”,“r”); //fl:
fgets(str,3,fl); //str:
puts(str);
fgets(str,10,fl); //str:
puts(str);