Программирование на языке C в Microsoft Visual Studio 2010

Структуры – производные типы данных языка С

Разбить на страницы
Показывать лекцию целиком

Теоретическая часть

Структура – это совокупность нескольких переменных, часто различных типов [13.1]. В структурах совокупность переменных объединяют под одним именем. Переменные, из которых состоит структура, называются ее членами. Члены структуры еще называются элементами или полями [13.2].

С помощью структур удобно размещать в смежных полях связанные между собой элементы информации. В структуре могут быть собраны различные объекты – переменные, массивы, указатели, другие структуры и т.д., которые для удобства работы с ними сгруппированы под одним именем. Если в массиве собраны переменные одного типа (например, float ), то в структуре могут быть переменные различных типов. Объявление структуры создает шаблон, который можно использовать для создания ее объектов (то есть экземпляров этой структуры) [13.2]. При объявлении структуры определяется агрегатный тип данных, но не переменная

Определение структуры состоит из двух шагов:

  • объявление шаблона структуры (задание нового типа данных, определенного пользователем);
  • определение переменных типа объявленного шаблона [13.3].
  • Имена шаблонов должны быть уникальными в пределах их области определения, для того чтобы компилятор мог различать типы шаблонов. Задание шаблона осуществляется с помощью ключевого слова struct, за которым следует имя шаблона структуры и списка элементов, заключенных в фигурные скобки [13.3]. Имена элементов в одном шаблоне также должны быть уникальными. Задание только шаблона не влечет резервирования памяти компилятором. Шаблон предоставляет компилятору необходимую информацию об элементах структурной переменной для резервирования места в оперативной памяти и организации доступа к ней при определении структурной переменной и использовании ее отдельных элементов [13.3].

    Рассмотрим шаблон структуры для определения имени и фамилии работника (служащего – employee), его возраста, почасовой оплаты:

    struct employee {
    char Name [20+1];     // Имя 
    char Surname [20+1];  // Фамилия
    int age;              // возраст
    double hourlysalary;  // почасовой оклад
    };

    Как видно, шаблон структуры struct employee состоит из символьных массивов типа char, целого числа типа int и числа с плавающей точкой и двойной точности типа double. Описания элементов производится в фигурных скобках, после закрывающей скобки обязательно должна быть точка с запятой.

    Определение структуры начинается с ключевого слова struct. Идентификатор employee является именем-этикеткой (tag name), дескриптором. Имя-этикетка employee именует структуру и используется совместно с ключевым словом struct для объявления переменных структурного типа [13.4].

    Переменные структуры объявляются так же, как и переменные других типов. На основе вышеприведенного шаблона сделаем несколько объявлений новых структурных переменных:

    struct employee new_ employee, * employeePtr, stack[120];

    В приведенном объявлении new_employee – переменная типа struct employee, *employeePtr – указатель на struct employee, emstack[120] – массив из 120 элементов типа struct employee.

    Объявленные структурные переменные new_employee, *employeePtr, stack[102] могут быть объединены с определением структуры, а именно:

    struct employee {
    char Name [20+1];       // Имя 
    char Surname [20+1];    // Фамилия
    int age;                // возраст
    double hourlysalary;    // почасовой оклад
    }  new_employee, *employeePtr, stack[120];

    Имя-этикетка (tag name) не является для структуры обязательным. Если определение структуры не содержит имя-этикетку, то переменные для этой структуры могут быть объявлены только в определении структуры, но не отдельным объявлением [13.1].

    При создании структур часто используется ключевое слово typedef (оператор). Оно предоставляет программисту средство для создания синонимов (или псевдонимов) для ранее определенных типов данных. Часто используют typedef для того, чтобы дать укороченное имя структурному типу [13.4]. Например, оператор вида

    typedef struct card Card;

    определяет новый тип с именем Card как синоним типа struct card.

    Ключевое слово typedef может быть использовано в определении типа структуры без имени-этикетки. Например:

    typedef  struct  {
    char *Name;          // Имя 
    char *Surname;       // Фамилия
    int age;             // возраст
    double hourlysalary; // почасовой оклад
    }  Man;

    создает тип Man без использования отдельного оператора typedef.

    В приведенном примере под символьные указатели необходимо предусмотреть выделение памяти.

    Созданный тип Man можно использовать для объявления структурных переменных типа struct employee, например:

    Man stack[120];

    Примечание. Использование typedef помогает сделать программу более переносимой.

    Синтаксис инициализации структур аналогичен инициализации массивов. Например, выполним инициализацию структуры:

    struct employee {
    char Name [20+1];      // Имя 
    char Surname [20+1];   // Фамилия
    int age;               // возраст
    double hourlysalary;   // почасовой оклад
    }   new_employee;

    Возможный вариант инициализации:

    struct employee {
    char Name [20];       // Имя 
    char Surname [20];    // Фамилия
    int age;              // возраст
    double hourlysalary;  // почасовой оклад
    }   new_employee =  { "Peter", "Smith", 25, 6.78 };

    При инициализации структуры структурные элементы (инициализаторы) должны соответствовать заданному типу и отделяться друг от друга запятыми.

    Доступ к элементам (компонентам, полям) структуры осуществляется двумя способами:

  • с помощью оператора связывающей точки (оператора точки) "." при непосредственной работе со структурой;
  • при использовании указателей на структуры с помощью стрелки "–>".
  • Общий формат доступа к элементам структуры имеет следующий вид:

    имя_переменной_структуры.имя_поля;
    имя_указателя_на_структуру–>имя_поля;
    (*имя_указателя_на_структуру).имя_поля;

    Например, для вышеприведенной инициализации можно изменить почасовой оклад с помощью оператора точки и указателя на структуру:

    new_employee.hourlysalary = 21.0;
    employeePtr –> hourlysalary = 21.0;

    Следует обратить внимание, что new_employee – это имя всего объекта-структуры, а hourlysalary – имя элемента этой структуры. Аналогично и в случае указателя *employeePtr на структуру.

    В случае изменения полей структуры следует выделить случай со строками, например:

    strcpy(new_employee.name, "Stephen");

    При этом должен быть предусмотрен заголовочный файл <string.h>. для функции strcpy().

    Когда объявлен массив структур, например, stack[120], то это означает, что создано 120 наборов переменных, каждый из которых организован также, как определено в структуре с дескриптором employee.

    Чтобы получить доступ к определенной структуре stack[120], следует указать имя массива с индексом, который пробегает значения от 0 до 119. Например, для пятой структуры можно сделать изменения в почасовом окладе:

    stack[4].hourlysalary = 121.5;

    Как и в других массивах переменных языка С, в массивах структур индексирование начинается с нуля [13.2]. Членами структуры могут быть также массивами или структурами. Когда структура является членом другой структуры, она называется вложенной [13.2].

    Рассмотрим следующий пример:

    struct X = {
    int A[7][8]; 
    float b;
    char ch;
    struct employee Emp2;
    } Y;

    Тогда инициализация элементов двухмерного массива А может быть такой:

    Y.A[2][5] = 99;

    Инициализация вложенной структуры может быть такой:

    Y.Emp2.hourlysalary = 12.75;

    В соответствии со стандартом С89 структуры могут быть вложенными вплоть до 15-го уровня. Стандарт С99 допускает уровень вложенности до 63-го включительно [13.2].

    Практическая часть

    Пример 1. Напишите программу структурного описания каталога одной книги.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #define N 40
    struct  book  { // Определение структуры
    	char title[N+1];    // Название книги
    	char author[N+1];   // Автор
    	int year;           // Год издания
    	int page;           // Количество страниц
    	float price;        // Цена в у.е.
    } Library;
    
    int main (void)
     {
    // Инициализация полей структуры
    Library.year = 2007;
    Library.page = 496;
    Library.price = 12.78F;
    strcpy_s(Library.title, N, "Programming in C");
    strcpy_s(Library.author, N, "Stephen G. Kochan");
    
    // Вывод на консоль
    printf("\n\t Title: %s\n", Library.title);
    printf("\t Author: %s\n", Library.author);
    printf("\t Year: %d\n", Library.year );
    printf("\t Number of pages: %d p.\n", Library.page );
    printf("\t Price: %1.2f y.e.\n", Library.price);
    
    	printf("\n\n Press any key: ");
    	_getch();
    	return 0; 
    }

    В программе использованы функции strcpy_s() вместо стандартных функций strcpy(), что позволило избавиться от предупреждений в системе Visual Studio 2008. В случае применения функций strcpy(), их формат записи был бы следующим:

    strcpy(Library.title, "Programming in C");
    strcpy(Library.author, "Stephen G. Kochan");

    Результат выполнения программы показан на рис 13.1.

    (рис 13.1) Пример инициализированных полей структуры

    Задание 1

  • Совместите объявление и инициализацию структуры. После инициализации структуры выполните изменение ее полей с последующим выводом на консоль.
  • Примените оператор typedef.
  • Поля структуры title и author определите с помощью указателей.
  • Произведите инициализацию структуры после ввода значений полей с клавиатуры.
  • Выполните вывод полей структуры в текстовый файл compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
  • Пример 2. Напишите программу анализа средней успеваемости четырех студентов по четырем предметам за сессию на основе структурного типа данных.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    
    #define N 4 // Число студентов
    #define CH 30 // Число символов для фамилии или имени
    
    // Определение структуры
    struct {
    char *name;// Имя студента
    char *surname; // Фамилия студента
    int M;   // Отметка по математическому анализу
    int A;   // Отметка по алгебре
    int H;   // Отметка по истории
    int In;  // Отметка по информатике
    } student[N];
    
    int main (void)  {
    float mark;
     int i;
    
     // Выделение памяти для символьных указателей
     for (i = 0; i < N; ++i) {
    student[i].name = (char *) malloc(CH*sizeof(char));
    student[i].surname = (char *) malloc(CH*sizeof(char));
     }
     
    printf("\n");
    for (i = 0; i < N; ++i) {
    	printf("\t Enter a name of %d student \n\t: ", i+1);
    gets_s(student[i].name, CH);
    
    printf("\t Enter a surname of %d student \n\t: ", i+1);
    gets_s(student[i].surname, CH);
    
    printf("\t Enter marks in 4 subjects for %d student (through a blank) \n\t: ", i+1);
    
    scanf_s("%i%i%i%i", (student[i].M),(student[i].A),(student[i].H),(student[i].In));
    _flushall();
    }
    
    puts("\n=====================================================================================");
    printf("\t Statement of Achievement students:\n");
    
    puts("======================================================================================\n");
    for (i = 0; i < N; ++i)
     {
    printf("\t %s \t %s:\n\t Mathematical analyses, Algebra, History, Informatics\n \
    \n\t\t %d\t\t %3d\t \
    %3d\t %5d\n----------------------------------------------\n", \
    student[i].name, student[i].surname, \
    student[i].M,student[i].A,student[i].H,student[i].In); }
    
    mark = 0.0F; // F – спецификатор для типа float 
    
    for (i = 0; i < N; ++i)
    {
    mark += (student[i].M + student[i].A + student[i].H + student[i].In); 
    }
    
    // Средняя оценка группы из 4 (N)студентов
    printf("\n\t The average mark groups of %d students: %1.4f", N, mark/(4*N));
    // 4*N - общее количество оценок
    
       printf("\n\n Press any key: ");
       _getch();
       return 0; 
    }

    В программе использован массив структур – переменная student[N]. Для определения имени и фамилии предварительно выделяется память для символьных указателей с помощью функций malloc(), для которых включен заголовок #include <stdlib.h>.

    Шаблон структуры задан без имени-этикетки (без тегового имени).

    Возможный результат выполнения программы показан на рис 13.2.

    (рис 13.2) Пример инициализированных полей структуры

    Задание 2

  • Выполните усреднение оценок для каждого студента.
  • Предусмотрите ввод названий предметов (математический анализ, алгебра и т.д.) и определите их в виде инициализаторов структуры.
  • Увеличьте число студентов до семи и произведите запись результатов в текстовый файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
  • В шаблоне структуры задайте теговое имя. Проанализируйте работу программы.
  • Примените оператор typedef для определения структурного типа данных
  • Расположите фамилии (с именем) студентов в порядке возрастания их среднего балла за сессию.
  • Пример 3. Напишите программу создания карточки служащего с помощью структурного типа данных и указателя на структуру. Предусмотрите инициализацию полей структуры и изменения этих полей.

    Для решения примера воспользуемся структурой, рассмотренной в теоретической части данной лабораторной работы:

    struct employee {
    char Name [20+1];         // Имя 
    char Surname [20+1];      // Фамилия
    int age;                  // возраст
    double hourlysalary;      // почасовой оклад
    }   employee_new, *PTR;  // *PTR – указатель на структуру

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #include <locale.h>
    // Предполагаемое число символов в имени или фамилии
    #define n 20 
    
    int main (void)
     {
    
    // Определение структуры
    struct emloyee {
    char name[n+1];          // имя 
    char surname[n+1];       // фамилия
    int age;               // возраст
    double hourlysalary;   // почасовой оклад в у.е.
    } emloyee_new, *PTR;   // *PTR - указатель на структуру
    
    // Для поддержки русских шрифтов
    setlocale( LC_ALL, ".1251");// кодовая страница Windows – 1251
    PTR = emloyee_new; //В указатель помещается адрес employee_new 
    // Инициализация полей структуры
    strcpy_s(PTR -> name, n, "Владимир");
    strcpy_s(PTR -> surname, n, "Викулов");
    PTR -> age = 25;
    PTR -> hourlysalary = 6.78;
    
    // Вывод на консоль
    puts("\n=============== Поля структуры ====================");
    printf("\n Имя: %s\n Фамилия: %s\n возраст: %d лет\n почасовой оклад: %1.2f y.e.\n", \
    PTR -> name, PTR -> surname, PTR -> age, PTR -> hourlysalary);
    
    puts("\n==================================================\n");
    printf("\n\n Нажмите любую клавишу (Press any key): ");
    _getch();
    return 0;
    }

    В программе инициализация полей структуры выполнена с помощью оператора стрелка "–>". С подключением заголовочного файла <locale.h> и определением прототипа функции setlocale(LC_ALL,".1251") производится поддержка русских шрифтов.

    Результат выполнения программы показан на рис 13.3.

    (рис 13.3) Пример вывода полей структуры на консоль

    Задание 3

  • В программу добавьте нумерацию полей структуры, например: 1) имя: и т.д.
  • В программу введите свое имя и фамилию, возраст и размер получаемой стипендии (если нет, то нуль). Значения новых полей выведите на консоль и в текстовый файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
  • Инициализацию полей структуры выполните с помощью указателя.
  • Выполните предварительную инициализацию структуры, а затем смените значения полей.
  • Тип данных double замените на тип float
  • Пример 4. Напишите программу информационной карточки студенческой группы с данными о студентах, применив вложенные структуры.

    Как известно, если членом структуры является другая структура, то она называется вложенной.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    
    #define N 20
    
    int main (void)
      {
    struct stud {    // шаблон структуры
    char name[N+1];    // имя студента
    char surname[N+1]; // фамилия студента
    int age;         // возраст - полных лет
    double av_mark;  // средняя успеваемость
    	}; 
    
    struct group {      // шаблон структуры
    int number;         // номер группы
    int quantity;       // количество студентов в группе
    struct stud student;// вложенная структура
    } ACOUY;            // ACOUY - структурная переменная
    
    // Инициализация полей структуры
    ACOUY.number = 3;
    ACOUY.quantity = 21;
    strcpy_s(ACOUY.student.name, N, "Peter");
    strcpy_s(ACOUY.student.surname, N, "Bobrov");
    ACOUY.student.age = 20;
    ACOUY.student.av_mark = 4.25;
    
    // Вывод на консоль
    puts("\n========= Varient field of structure ===============");
    printf("\n Group Number: %d,\n The number of students in the group: %d,\n\
     Name: %s,\n Surname: %s,\n Age: %d,\n Average mark: %1.2f", \
      ACOUY.number, ACOUY.quantity, ACOUY.student.name, ACOUY.student.surname, \
      ACOUY.student.age, ACOUY.student.av_mark);
    puts("\n\n================================================\n");
    
        printf("\n Press any key: ");
        _getch();
        return 0;
     }

    Результат выполнения программы показан на рис 13.4.

    (рис 13.4) Пример информационной карточки студенческой группы

    Задание 4

  • Инициализацию структуры выполните с клавиатуры.
  • Предусмотрите массив структур ACOUY[N], где N – количество групп (например, N = 3 ).
  • Введите данные своей студенческой группы и предусмотрите вывод на консоль данных о себе.
  • Примените оператор typedef и указатель на структуру.
  • Пример 5. Напишите программу составления карточки на студента с динамическим распределением памяти для имени и фамилии на основе структурного типа данных [13.5].

    Для динамического распределения памяти применим функцию malloc() и символьные указатели в качестве инициализаторов структуры.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <locale.h>
    
    const int MAX = 80; // Предполагаемое число символов
    
    int main (void) {
    	char *NAME, *SURNAME;
    
    struct stud {    // шаблон структуры
    char *name;    // указатель вместо массива символов имени студента
    char *surname; // указатель вместо массива символов фамилии студента
    int age;         // возраст - полных лет
    float av_mark;  // средняя успеваемость
    int letters;     // число символов в имени и фамилии
    	} TABLE, *PTR; 
    
    PTR = TABLE; // инициализация указателя на структуру
    NAME = (char *)malloc(MAX);
    printf("\n Enter a name of the student: ");
    gets_s(NAME, MAX);
    
    SURNAME = (char *)malloc(MAX);
    printf(" Enter a surname of the student: ");
    gets_s(SURNAME, MAX);
    
    // Распределение памяти для хранения "структурного" имени 
    PTR->name = (char *)malloc(strlen(NAME)+1);
    // Копирование имени в распределенную память
    strcpy_s(PTR->name, strlen(NAME)+1, NAME);
    
    // Распределение памяти для хранения "структурной" фамилии
    PTR->surname = (char *)malloc(strlen(SURNAME)+1);
    // Копирование фамилии в распределенную память
    strcpy_s(PTR->surname, strlen(SURNAME)+1, SURNAME);
    
    printf(" Enter the age of the student: ");
    scanf_s("%d", TABLE.age);
    
    printf(" Enter an average mark of the student: ");
    scanf_s("%f", TABLE.av_mark);
    
    TABLE.letters = strlen(PTR->name) + strlen(PTR->surname);
    // Для вывода чисел с десятичной запятой
    setlocale(LC_NUMERIC, ".1251"); 
    puts("\n======== Varient field of structure ===============");
    printf("\n Name: %s\n Surname: %s\n Age: %d\n Average mark: %1.2f\n\
     The name and surname of student have: %d letters", \
    PTR->name, PTR->surname, PTR->age, PTR->av_mark, PTR->letters);
    puts("\n\n================================================\n");
    
    // Освобождение памяти
    free(NAME);
    free(SURNAME);
    free(PTR->name);
    free(PTR->surname);
    
       printf("\n Press any key: ");
       _getch(); return 0;
      }

    В программе сначала выделяется память для имени и фамилии, для которых использованы указатели *NAME, *SURNAME. После того как имя и фамилия введены с клавиатуры, рассчитывается количество символов плюс символ окончания строки '\0', которые используются для выделения памяти для структурных переменных.

    Возможный результат выполнения программы показан на рис 13.5.

    (рис 13.5) Пример динамического создания карточки студента

    Задание 5

  • С клавиатуры введите данные о себе (буквами русского алфавита), выведите информацию на консоль и в текстовый файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
  • Поменяйте операторы стрелка на операторы точка, и наоборот.
  • Вместо функций malloc() примените функции calloc().
  • Вместо указателей *NAME, *SURNAME примените массивы символов
  • Предусмотрите нумерацию полей структуры, например, 1) Name: Peter и т.д.
  • Пример 6. Напишите программу записи структуры в двоичный файл и чтения ее из двоичного файла.

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

    Для динамического распределения памяти применим функцию malloc() и символьные указатели в качестве инициализаторов структуры.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    
    #define MAX  80 // Предполагаемое число символов
    
    // шаблон структуры
    struct stud 
    {  
    char name[MAX+1];    // массив символов имени студента
    char surname[MAX+1]; // массив символов фамилии студента
    char ACOUY[MAX+1];    // специальность
    int age;         // возраст - полных лет
    float av_mark;  // средняя успеваемость
    };
    
    int main (void)
     {
    char NAME[MAX+1], SURNAME[MAX+1], SPEC[MAX+1];
    FILE *fid;
    
    // условная инициализация переменной структуры и 
    // определение указателя на структуру
    struct stud TABLE = {"--", "--", "--", 0, 0.0}, *PTR;
    PTR = TABLE; // инициализация указателя на структуру
    
    printf("\n Enter a name of student: ");
    gets_s(NAME, MAX);
    printf(" Enter a surname of student: ");
    gets_s(SURNAME, MAX);
    printf(" Enter a speciality: ");
    gets_s(SPEC, MAX);
    
    // Занесение имени в структуру
    strcpy_s(PTR->name, strlen(NAME)+1, NAME);
    // Занесение фамилии в структуру
    strcpy_s(PTR->surname, strlen(SURNAME)+1, SURNAME);
    // Занесение названия специальности в структуру
    strcpy_s(PTR->ACOUY, strlen(SPEC)+1, SPEC);
    
    printf("Enter the age of the student: ");
    scanf_s("%d", TABLE.age);
    printf(" Enter the average mark student: ");
    scanf_s("%f", TABLE.av_mark);
    
    puts("\n======= Varient field of structure ============");
    printf("\n Name: %s\n Surname: %s\n \
    Specialisation: %s\n Age: %d\n Average mark: %0.2f\n ", \
    PTR->name, PTR->surname, PTR->ACOUY, PTR->age, PTR->av_mark );
    puts("\n================================================\n");
    if ( fopen_s(fid, "D:\\data12.dat", "wb") )
    {printf("\n File could not be opened\n");
    printf("\n Press any key: ");
    _getch(); return 0; }
    //Пакетная запись в двоичный файл
    fwrite(PTR, sizeof(struct stud), 1, fid);
    fclose(fid);
      
    //if ( fopen_s(fid, "D:\\data12.dat", "rb") )
    //{printf("\n File could not be opened\n");
    //printf("\n Press any key: ");
    //_getch(); return 0; }
    // Чтение из двоичного файла
    //fread(PTR, sizeof(struct stud), 1, fid);
    //puts("\n===== Variants of fields of structure =====");
    //printf("\n Name: %s\n Surname: %s\n \
    //Specialisation: %s\n Age: %d\n Average mark: %1.2f\n ", \
    
    //PTR->name, PTR->surname, PTR->ACOUY, PTR->age, PTR->av_mark );
    //puts("\n===============================================\n");
    //fclose(fid);
       printf("\n\n Press any key: ");
       _getch();
       return 0; 
    }

    Форматы записи в двоичный файл и чтения из двоичного файла:

    fwrite(PTR, sizeof(struct stud), 1, fid);
    fread(PTR, sizeof(struct stud), 1, fid);

    В функции fwrite() первый параметр PTR определяет собой содержимое структуры (данных в других случаях), которое по указателю *fid на файл записывается в файл. Второй параметр sizeof(struct stud) определяет собой размер в байтах. Третий параметр 1 – это количество блоков, которое будет записываться в файл. При этом второй и третий параметры перемножаются, поэтому их можно поменять местами.

    В программе чтение из двоичного файла закомментировано. Для корректной работы программы сделана условная инициализация полей структуры, чтобы прописать адрес структуры в памяти с данными.

    Возможный вариант выполнения программы при записи информации в двоичный файл показан на рис 13.6. После комментирования программного кода с записью в файл и снятия комментариев к программному коду чтения из файла результат выполнения программы показан на рис 13.7.

    (рис 13.7) Вариант записи информации в двоичный файл(рис 13.6) Результат чтения из двоичного файла

    Задание 6

  • Перезапишите информацию из файла data12.dat в двоичный файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа. Символьные массивы полей структуры задайте с помощью указателей.
  • Запись данных произведите в двоичный файл с различными расширениями: .txt, .bin, .doc. Определите размеры этих файлов в байтах.
  • Напишите программу записи массива структур в двоичный файл и чтения из него всей структуры с выводом результатов на консоль.
  • Контрольные вопросы

  • Как определяется структура в языке С?
  • Как объявляется структура в языке С?
  • Какими способами можно объявить новые структурные переменные?
  • Какие форматы используются для доступа к элементам структуры?
  • Что такое вложенная структура?
  • Какой уровень вложенности структур поддерживается стандартом С89?
  • Как объявляется массив структур?
  • Как объявляется указатель на структуру?
  • Как инициализируется указатель на структуру?
  • Как осуществляется инициализация полей структуры, определенных как символьные массивы?
  • Какой оператор может быть использован для определения структурного типа данных?
  • Является ли тег структуры именем ее типа?
  • Страницы:

    Теоретическая часть

    Структура – это совокупность нескольких переменных, часто различных типов [13.1]. В структурах совокупность переменных объединяют под одним именем. Переменные, из которых состоит структура, называются ее членами. Члены структуры еще называются элементами или полями [13.2].

    С помощью структур удобно размещать в смежных полях связанные между собой элементы информации. В структуре могут быть собраны различные объекты – переменные, массивы, указатели, другие структуры и т.д., которые для удобства работы с ними сгруппированы под одним именем. Если в массиве собраны переменные одного типа (например, float ), то в структуре могут быть переменные различных типов. Объявление структуры создает шаблон, который можно использовать для создания ее объектов (то есть экземпляров этой структуры) [13.2]. При объявлении структуры определяется агрегатный тип данных, но не переменная

    Определение структуры состоит из двух шагов:

  • объявление шаблона структуры (задание нового типа данных, определенного пользователем);
  • определение переменных типа объявленного шаблона [13.3].
  • Имена шаблонов должны быть уникальными в пределах их области определения, для того чтобы компилятор мог различать типы шаблонов. Задание шаблона осуществляется с помощью ключевого слова struct, за которым следует имя шаблона структуры и списка элементов, заключенных в фигурные скобки [13.3]. Имена элементов в одном шаблоне также должны быть уникальными. Задание только шаблона не влечет резервирования памяти компилятором. Шаблон предоставляет компилятору необходимую информацию об элементах структурной переменной для резервирования места в оперативной памяти и организации доступа к ней при определении структурной переменной и использовании ее отдельных элементов [13.3].

    Рассмотрим шаблон структуры для определения имени и фамилии работника (служащего – employee), его возраста, почасовой оплаты:

    struct employee {
    char Name [20+1];     // Имя 
    char Surname [20+1];  // Фамилия
    int age;              // возраст
    double hourlysalary;  // почасовой оклад
    };

    Как видно, шаблон структуры struct employee состоит из символьных массивов типа char, целого числа типа int и числа с плавающей точкой и двойной точности типа double. Описания элементов производится в фигурных скобках, после закрывающей скобки обязательно должна быть точка с запятой.

    Определение структуры начинается с ключевого слова struct. Идентификатор employee является именем-этикеткой (tag name), дескриптором. Имя-этикетка employee именует структуру и используется совместно с ключевым словом struct для объявления переменных структурного типа [13.4].

    Переменные структуры объявляются так же, как и переменные других типов. На основе вышеприведенного шаблона сделаем несколько объявлений новых структурных переменных:

    struct employee new_ employee, * employeePtr, stack[120];

    В приведенном объявлении new_employee – переменная типа struct employee, *employeePtr – указатель на struct employee, emstack[120] – массив из 120 элементов типа struct employee.

    Объявленные структурные переменные new_employee, *employeePtr, stack[102] могут быть объединены с определением структуры, а именно:

    struct employee {
    char Name [20+1];       // Имя 
    char Surname [20+1];    // Фамилия
    int age;                // возраст
    double hourlysalary;    // почасовой оклад
    }  new_employee, *employeePtr, stack[120];

    Имя-этикетка (tag name) не является для структуры обязательным. Если определение структуры не содержит имя-этикетку, то переменные для этой структуры могут быть объявлены только в определении структуры, но не отдельным объявлением [13.1].

    При создании структур часто используется ключевое слово typedef (оператор). Оно предоставляет программисту средство для создания синонимов (или псевдонимов) для ранее определенных типов данных. Часто используют typedef для того, чтобы дать укороченное имя структурному типу [13.4]. Например, оператор вида

    typedef struct card Card;

    определяет новый тип с именем Card как синоним типа struct card.

    Ключевое слово typedef может быть использовано в определении типа структуры без имени-этикетки. Например:

    typedef  struct  {
    char *Name;          // Имя 
    char *Surname;       // Фамилия
    int age;             // возраст
    double hourlysalary; // почасовой оклад
    }  Man;

    создает тип Man без использования отдельного оператора typedef.

    В приведенном примере под символьные указатели необходимо предусмотреть выделение памяти.

    Созданный тип Man можно использовать для объявления структурных переменных типа struct employee, например:

    Man stack[120];

    Примечание. Использование typedef помогает сделать программу более переносимой.

    Синтаксис инициализации структур аналогичен инициализации массивов. Например, выполним инициализацию структуры:

    struct employee {
    char Name [20+1];      // Имя 
    char Surname [20+1];   // Фамилия
    int age;               // возраст
    double hourlysalary;   // почасовой оклад
    }   new_employee;

    Возможный вариант инициализации:

    struct employee {
    char Name [20];       // Имя 
    char Surname [20];    // Фамилия
    int age;              // возраст
    double hourlysalary;  // почасовой оклад
    }   new_employee =  { "Peter", "Smith", 25, 6.78 };

    При инициализации структуры структурные элементы (инициализаторы) должны соответствовать заданному типу и отделяться друг от друга запятыми.

    Доступ к элементам (компонентам, полям) структуры осуществляется двумя способами:

  • с помощью оператора связывающей точки (оператора точки) "." при непосредственной работе со структурой;
  • при использовании указателей на структуры с помощью стрелки "–>".
  • Общий формат доступа к элементам структуры имеет следующий вид:

    имя_переменной_структуры.имя_поля;
    имя_указателя_на_структуру–>имя_поля;
    (*имя_указателя_на_структуру).имя_поля;

    Например, для вышеприведенной инициализации можно изменить почасовой оклад с помощью оператора точки и указателя на структуру:

    new_employee.hourlysalary = 21.0;
    employeePtr –> hourlysalary = 21.0;

    Следует обратить внимание, что new_employee – это имя всего объекта-структуры, а hourlysalary – имя элемента этой структуры. Аналогично и в случае указателя *employeePtr на структуру.

    В случае изменения полей структуры следует выделить случай со строками, например:

    strcpy(new_employee.name, "Stephen");

    При этом должен быть предусмотрен заголовочный файл <string.h>. для функции strcpy().

    Когда объявлен массив структур, например, stack[120], то это означает, что создано 120 наборов переменных, каждый из которых организован также, как определено в структуре с дескриптором employee.

    Чтобы получить доступ к определенной структуре stack[120], следует указать имя массива с индексом, который пробегает значения от 0 до 119. Например, для пятой структуры можно сделать изменения в почасовом окладе:

    stack[4].hourlysalary = 121.5;

    Как и в других массивах переменных языка С, в массивах структур индексирование начинается с нуля [13.2]. Членами структуры могут быть также массивами или структурами. Когда структура является членом другой структуры, она называется вложенной [13.2].

    Рассмотрим следующий пример:

    struct X = {
    int A[7][8]; 
    float b;
    char ch;
    struct employee Emp2;
    } Y;

    Тогда инициализация элементов двухмерного массива А может быть такой:

    Y.A[2][5] = 99;

    Инициализация вложенной структуры может быть такой:

    Y.Emp2.hourlysalary = 12.75;

    В соответствии со стандартом С89 структуры могут быть вложенными вплоть до 15-го уровня. Стандарт С99 допускает уровень вложенности до 63-го включительно [13.2].

    Практическая часть

    Пример 1. Напишите программу структурного описания каталога одной книги.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #define N 40
    struct  book  { // Определение структуры
    	char title[N+1];    // Название книги
    	char author[N+1];   // Автор
    	int year;           // Год издания
    	int page;           // Количество страниц
    	float price;        // Цена в у.е.
    } Library;
    
    int main (void)
     {
    // Инициализация полей структуры
    Library.year = 2007;
    Library.page = 496;
    Library.price = 12.78F;
    strcpy_s(Library.title, N, "Programming in C");
    strcpy_s(Library.author, N, "Stephen G. Kochan");
    
    // Вывод на консоль
    printf("\n\t Title: %s\n", Library.title);
    printf("\t Author: %s\n", Library.author);
    printf("\t Year: %d\n", Library.year );
    printf("\t Number of pages: %d p.\n", Library.page );
    printf("\t Price: %1.2f y.e.\n", Library.price);
    
    	printf("\n\n Press any key: ");
    	_getch();
    	return 0; 
    }

    В программе использованы функции strcpy_s() вместо стандартных функций strcpy(), что позволило избавиться от предупреждений в системе Visual Studio 2008. В случае применения функций strcpy(), их формат записи был бы следующим:

    strcpy(Library.title, "Programming in C");
    strcpy(Library.author, "Stephen G. Kochan");

    Результат выполнения программы показан на рис 13.1.

    (рис 13.1) Пример инициализированных полей структуры

    Задание 1

  • Совместите объявление и инициализацию структуры. После инициализации структуры выполните изменение ее полей с последующим выводом на консоль.
  • Примените оператор typedef.
  • Поля структуры title и author определите с помощью указателей.
  • Произведите инициализацию структуры после ввода значений полей с клавиатуры.
  • Выполните вывод полей структуры в текстовый файл compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
  • Пример 2. Напишите программу анализа средней успеваемости четырех студентов по четырем предметам за сессию на основе структурного типа данных.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <stdlib.h>
    
    #define N 4 // Число студентов
    #define CH 30 // Число символов для фамилии или имени
    
    // Определение структуры
    struct {
    char *name;// Имя студента
    char *surname; // Фамилия студента
    int M;   // Отметка по математическому анализу
    int A;   // Отметка по алгебре
    int H;   // Отметка по истории
    int In;  // Отметка по информатике
    } student[N];
    
    int main (void)  {
    float mark;
     int i;
    
     // Выделение памяти для символьных указателей
     for (i = 0; i < N; ++i) {
    student[i].name = (char *) malloc(CH*sizeof(char));
    student[i].surname = (char *) malloc(CH*sizeof(char));
     }
     
    printf("\n");
    for (i = 0; i < N; ++i) {
    	printf("\t Enter a name of %d student \n\t: ", i+1);
    gets_s(student[i].name, CH);
    
    printf("\t Enter a surname of %d student \n\t: ", i+1);
    gets_s(student[i].surname, CH);
    
    printf("\t Enter marks in 4 subjects for %d student (through a blank) \n\t: ", i+1);
    
    scanf_s("%i%i%i%i", (student[i].M),(student[i].A),(student[i].H),(student[i].In));
    _flushall();
    }
    
    puts("\n=====================================================================================");
    printf("\t Statement of Achievement students:\n");
    
    puts("======================================================================================\n");
    for (i = 0; i < N; ++i)
     {
    printf("\t %s \t %s:\n\t Mathematical analyses, Algebra, History, Informatics\n \
    \n\t\t %d\t\t %3d\t \
    %3d\t %5d\n----------------------------------------------\n", \
    student[i].name, student[i].surname, \
    student[i].M,student[i].A,student[i].H,student[i].In); }
    
    mark = 0.0F; // F – спецификатор для типа float 
    
    for (i = 0; i < N; ++i)
    {
    mark += (student[i].M + student[i].A + student[i].H + student[i].In); 
    }
    
    // Средняя оценка группы из 4 (N)студентов
    printf("\n\t The average mark groups of %d students: %1.4f", N, mark/(4*N));
    // 4*N - общее количество оценок
    
       printf("\n\n Press any key: ");
       _getch();
       return 0; 
    }

    В программе использован массив структур – переменная student[N]. Для определения имени и фамилии предварительно выделяется память для символьных указателей с помощью функций malloc(), для которых включен заголовок #include <stdlib.h>.

    Шаблон структуры задан без имени-этикетки (без тегового имени).

    Возможный результат выполнения программы показан на рис 13.2.

    (рис 13.2) Пример инициализированных полей структуры

    Задание 2

  • Выполните усреднение оценок для каждого студента.
  • Предусмотрите ввод названий предметов (математический анализ, алгебра и т.д.) и определите их в виде инициализаторов структуры.
  • Увеличьте число студентов до семи и произведите запись результатов в текстовый файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
  • В шаблоне структуры задайте теговое имя. Проанализируйте работу программы.
  • Примените оператор typedef для определения структурного типа данных
  • Расположите фамилии (с именем) студентов в порядке возрастания их среднего балла за сессию.
  • Пример 3. Напишите программу создания карточки служащего с помощью структурного типа данных и указателя на структуру. Предусмотрите инициализацию полей структуры и изменения этих полей.

    Для решения примера воспользуемся структурой, рассмотренной в теоретической части данной лабораторной работы:

    struct employee {
    char Name [20+1];         // Имя 
    char Surname [20+1];      // Фамилия
    int age;                  // возраст
    double hourlysalary;      // почасовой оклад
    }   employee_new, *PTR;  // *PTR – указатель на структуру

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #include <locale.h>
    // Предполагаемое число символов в имени или фамилии
    #define n 20 
    
    int main (void)
     {
    
    // Определение структуры
    struct emloyee {
    char name[n+1];          // имя 
    char surname[n+1];       // фамилия
    int age;               // возраст
    double hourlysalary;   // почасовой оклад в у.е.
    } emloyee_new, *PTR;   // *PTR - указатель на структуру
    
    // Для поддержки русских шрифтов
    setlocale( LC_ALL, ".1251");// кодовая страница Windows – 1251
    PTR = emloyee_new; //В указатель помещается адрес employee_new 
    // Инициализация полей структуры
    strcpy_s(PTR -> name, n, "Владимир");
    strcpy_s(PTR -> surname, n, "Викулов");
    PTR -> age = 25;
    PTR -> hourlysalary = 6.78;
    
    // Вывод на консоль
    puts("\n=============== Поля структуры ====================");
    printf("\n Имя: %s\n Фамилия: %s\n возраст: %d лет\n почасовой оклад: %1.2f y.e.\n", \
    PTR -> name, PTR -> surname, PTR -> age, PTR -> hourlysalary);
    
    puts("\n==================================================\n");
    printf("\n\n Нажмите любую клавишу (Press any key): ");
    _getch();
    return 0;
    }

    В программе инициализация полей структуры выполнена с помощью оператора стрелка "–>". С подключением заголовочного файла <locale.h> и определением прототипа функции setlocale(LC_ALL,".1251") производится поддержка русских шрифтов.

    Результат выполнения программы показан на рис 13.3.

    (рис 13.3) Пример вывода полей структуры на консоль

    Задание 3

  • В программу добавьте нумерацию полей структуры, например: 1) имя: и т.д.
  • В программу введите свое имя и фамилию, возраст и размер получаемой стипендии (если нет, то нуль). Значения новых полей выведите на консоль и в текстовый файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
  • Инициализацию полей структуры выполните с помощью указателя.
  • Выполните предварительную инициализацию структуры, а затем смените значения полей.
  • Тип данных double замените на тип float
  • Пример 4. Напишите программу информационной карточки студенческой группы с данными о студентах, применив вложенные структуры.

    Как известно, если членом структуры является другая структура, то она называется вложенной.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    
    #define N 20
    
    int main (void)
      {
    struct stud {    // шаблон структуры
    char name[N+1];    // имя студента
    char surname[N+1]; // фамилия студента
    int age;         // возраст - полных лет
    double av_mark;  // средняя успеваемость
    	}; 
    
    struct group {      // шаблон структуры
    int number;         // номер группы
    int quantity;       // количество студентов в группе
    struct stud student;// вложенная структура
    } ACOUY;            // ACOUY - структурная переменная
    
    // Инициализация полей структуры
    ACOUY.number = 3;
    ACOUY.quantity = 21;
    strcpy_s(ACOUY.student.name, N, "Peter");
    strcpy_s(ACOUY.student.surname, N, "Bobrov");
    ACOUY.student.age = 20;
    ACOUY.student.av_mark = 4.25;
    
    // Вывод на консоль
    puts("\n========= Varient field of structure ===============");
    printf("\n Group Number: %d,\n The number of students in the group: %d,\n\
     Name: %s,\n Surname: %s,\n Age: %d,\n Average mark: %1.2f", \
      ACOUY.number, ACOUY.quantity, ACOUY.student.name, ACOUY.student.surname, \
      ACOUY.student.age, ACOUY.student.av_mark);
    puts("\n\n================================================\n");
    
        printf("\n Press any key: ");
        _getch();
        return 0;
     }

    Результат выполнения программы показан на рис 13.4.

    (рис 13.4) Пример информационной карточки студенческой группы

    Задание 4

  • Инициализацию структуры выполните с клавиатуры.
  • Предусмотрите массив структур ACOUY[N], где N – количество групп (например, N = 3 ).
  • Введите данные своей студенческой группы и предусмотрите вывод на консоль данных о себе.
  • Примените оператор typedef и указатель на структуру.
  • Пример 5. Напишите программу составления карточки на студента с динамическим распределением памяти для имени и фамилии на основе структурного типа данных [13.5].

    Для динамического распределения памяти применим функцию malloc() и символьные указатели в качестве инициализаторов структуры.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <locale.h>
    
    const int MAX = 80; // Предполагаемое число символов
    
    int main (void) {
    	char *NAME, *SURNAME;
    
    struct stud {    // шаблон структуры
    char *name;    // указатель вместо массива символов имени студента
    char *surname; // указатель вместо массива символов фамилии студента
    int age;         // возраст - полных лет
    float av_mark;  // средняя успеваемость
    int letters;     // число символов в имени и фамилии
    	} TABLE, *PTR; 
    
    PTR = TABLE; // инициализация указателя на структуру
    NAME = (char *)malloc(MAX);
    printf("\n Enter a name of the student: ");
    gets_s(NAME, MAX);
    
    SURNAME = (char *)malloc(MAX);
    printf(" Enter a surname of the student: ");
    gets_s(SURNAME, MAX);
    
    // Распределение памяти для хранения "структурного" имени 
    PTR->name = (char *)malloc(strlen(NAME)+1);
    // Копирование имени в распределенную память
    strcpy_s(PTR->name, strlen(NAME)+1, NAME);
    
    // Распределение памяти для хранения "структурной" фамилии
    PTR->surname = (char *)malloc(strlen(SURNAME)+1);
    // Копирование фамилии в распределенную память
    strcpy_s(PTR->surname, strlen(SURNAME)+1, SURNAME);
    
    printf(" Enter the age of the student: ");
    scanf_s("%d", TABLE.age);
    
    printf(" Enter an average mark of the student: ");
    scanf_s("%f", TABLE.av_mark);
    
    TABLE.letters = strlen(PTR->name) + strlen(PTR->surname);
    // Для вывода чисел с десятичной запятой
    setlocale(LC_NUMERIC, ".1251"); 
    puts("\n======== Varient field of structure ===============");
    printf("\n Name: %s\n Surname: %s\n Age: %d\n Average mark: %1.2f\n\
     The name and surname of student have: %d letters", \
    PTR->name, PTR->surname, PTR->age, PTR->av_mark, PTR->letters);
    puts("\n\n================================================\n");
    
    // Освобождение памяти
    free(NAME);
    free(SURNAME);
    free(PTR->name);
    free(PTR->surname);
    
       printf("\n Press any key: ");
       _getch(); return 0;
      }

    В программе сначала выделяется память для имени и фамилии, для которых использованы указатели *NAME, *SURNAME. После того как имя и фамилия введены с клавиатуры, рассчитывается количество символов плюс символ окончания строки '\0', которые используются для выделения памяти для структурных переменных.

    Возможный результат выполнения программы показан на рис 13.5.

    (рис 13.5) Пример динамического создания карточки студента

    Задание 5

  • С клавиатуры введите данные о себе (буквами русского алфавита), выведите информацию на консоль и в текстовый файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа.
  • Поменяйте операторы стрелка на операторы точка, и наоборот.
  • Вместо функций malloc() примените функции calloc().
  • Вместо указателей *NAME, *SURNAME примените массивы символов
  • Предусмотрите нумерацию полей структуры, например, 1) Name: Peter и т.д.
  • Пример 6. Напишите программу записи структуры в двоичный файл и чтения ее из двоичного файла.

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

    Для динамического распределения памяти применим функцию malloc() и символьные указатели в качестве инициализаторов структуры.

    Программный код решения примера:

    #include <stdio.h>
    #include <conio.h>
    #include <string.h>
    
    #define MAX  80 // Предполагаемое число символов
    
    // шаблон структуры
    struct stud 
    {  
    char name[MAX+1];    // массив символов имени студента
    char surname[MAX+1]; // массив символов фамилии студента
    char ACOUY[MAX+1];    // специальность
    int age;         // возраст - полных лет
    float av_mark;  // средняя успеваемость
    };
    
    int main (void)
     {
    char NAME[MAX+1], SURNAME[MAX+1], SPEC[MAX+1];
    FILE *fid;
    
    // условная инициализация переменной структуры и 
    // определение указателя на структуру
    struct stud TABLE = {"--", "--", "--", 0, 0.0}, *PTR;
    PTR = TABLE; // инициализация указателя на структуру
    
    printf("\n Enter a name of student: ");
    gets_s(NAME, MAX);
    printf(" Enter a surname of student: ");
    gets_s(SURNAME, MAX);
    printf(" Enter a speciality: ");
    gets_s(SPEC, MAX);
    
    // Занесение имени в структуру
    strcpy_s(PTR->name, strlen(NAME)+1, NAME);
    // Занесение фамилии в структуру
    strcpy_s(PTR->surname, strlen(SURNAME)+1, SURNAME);
    // Занесение названия специальности в структуру
    strcpy_s(PTR->ACOUY, strlen(SPEC)+1, SPEC);
    
    printf("Enter the age of the student: ");
    scanf_s("%d", TABLE.age);
    printf(" Enter the average mark student: ");
    scanf_s("%f", TABLE.av_mark);
    
    puts("\n======= Varient field of structure ============");
    printf("\n Name: %s\n Surname: %s\n \
    Specialisation: %s\n Age: %d\n Average mark: %0.2f\n ", \
    PTR->name, PTR->surname, PTR->ACOUY, PTR->age, PTR->av_mark );
    puts("\n================================================\n");
    if ( fopen_s(fid, "D:\\data12.dat", "wb") )
    {printf("\n File could not be opened\n");
    printf("\n Press any key: ");
    _getch(); return 0; }
    //Пакетная запись в двоичный файл
    fwrite(PTR, sizeof(struct stud), 1, fid);
    fclose(fid);
      
    //if ( fopen_s(fid, "D:\\data12.dat", "rb") )
    //{printf("\n File could not be opened\n");
    //printf("\n Press any key: ");
    //_getch(); return 0; }
    // Чтение из двоичного файла
    //fread(PTR, sizeof(struct stud), 1, fid);
    //puts("\n===== Variants of fields of structure =====");
    //printf("\n Name: %s\n Surname: %s\n \
    //Specialisation: %s\n Age: %d\n Average mark: %1.2f\n ", \
    
    //PTR->name, PTR->surname, PTR->ACOUY, PTR->age, PTR->av_mark );
    //puts("\n===============================================\n");
    //fclose(fid);
       printf("\n\n Press any key: ");
       _getch();
       return 0; 
    }

    Форматы записи в двоичный файл и чтения из двоичного файла:

    fwrite(PTR, sizeof(struct stud), 1, fid);
    fread(PTR, sizeof(struct stud), 1, fid);

    В функции fwrite() первый параметр PTR определяет собой содержимое структуры (данных в других случаях), которое по указателю *fid на файл записывается в файл. Второй параметр sizeof(struct stud) определяет собой размер в байтах. Третий параметр 1 – это количество блоков, которое будет записываться в файл. При этом второй и третий параметры перемножаются, поэтому их можно поменять местами.

    В программе чтение из двоичного файла закомментировано. Для корректной работы программы сделана условная инициализация полей структуры, чтобы прописать адрес структуры в памяти с данными.

    Возможный вариант выполнения программы при записи информации в двоичный файл показан на рис 13.6. После комментирования программного кода с записью в файл и снятия комментариев к программному коду чтения из файла результат выполнения программы показан на рис 13.7.

    (рис 13.7) Вариант записи информации в двоичный файл(рис 13.6) Результат чтения из двоичного файла

    Задание 6

  • Перезапишите информацию из файла data12.dat в двоичный файл с именем compX.txt, где Х – номер компьютера, за которым выполняется лабораторная работа. Символьные массивы полей структуры задайте с помощью указателей.
  • Запись данных произведите в двоичный файл с различными расширениями: .txt, .bin, .doc. Определите размеры этих файлов в байтах.
  • Напишите программу записи массива структур в двоичный файл и чтения из него всей структуры с выводом результатов на консоль.
  • Контрольные вопросы

  • Как определяется структура в языке С?
  • Как объявляется структура в языке С?
  • Какими способами можно объявить новые структурные переменные?
  • Какие форматы используются для доступа к элементам структуры?
  • Что такое вложенная структура?
  • Какой уровень вложенности структур поддерживается стандартом С89?
  • Как объявляется массив структур?
  • Как объявляется указатель на структуру?
  • Как инициализируется указатель на структуру?
  • Как осуществляется инициализация полей структуры, определенных как символьные массивы?
  • Какой оператор может быть использован для определения структурного типа данных?
  • Является ли тег структуры именем ее типа?
  • Вернуться к учебному плану