Определение нового имени типа



 

При решении прикладных задач на компьютере часто возникает необходимость в типах данных, которые не определены в языке программирования. В языке С++ можно создавать новые имена типов данных – пользовательские типы данных. Эта возможность реализуется при помощи спецификатора typedef или директивы задания макроопределений #define.  Ключевое слово typedef позволяет заменить имя заранее созданного пользовательского или стандартного типа данных на имя, которое задает программист. Это очень удобно при работе со структурами. Пример определения нового (пользовательского) имени структурного типа данных приведен в табл.10.

 

 

Таблица 10

Определение tovar с помощью typedef Определение tovar с помощью #define
typedef struct { char name[50];// Наименование float price ; // Цена оптовая float percent; // Наценка в % int vol;       // 06ъем партии char date[9] ; // Дата поставки партии } tovar; tovar tv; #define tovar struct tvr tovar { char name[50]; // Наименование float price ;   // Цена оптовая float percent;   // Наценка в % int vol;         // 06ъем партии char date[9] ; // Дата поставки                     //партии }; tovar tv;

В обоих примерах именем нового типа пользователя будет tovar, а tv – это структура-переменная типа tovar. Надо заметить, что такие определения записываются в разделе программы: директивы препроцессора, т.е. перед заголовком главной функции main().

Примечание. В языке С++ кроме структур существует такое понятие, как объединение. Объединение от структуры отличается тем, что объем оперативной памяти, занимаемой объединением, будет равен объему, который необходим для размещения максимального по объёму памяти элемента этого объединения.

 

Массивы структур. Указатели на структуры

 

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

Указатели на структуры определяются, как и указатели на переменные других типов. Если объявлен указатель на структурный тип, то в этом случае говорят о динамическом массиве структур. Динамическим массивам структур ОП выделяется в процессе выполнения программы с помощью одной из соответствующих библиотечных функций, например malloc().

Допустим, что определён новый тип пользователя stud (студент) – структура с полями fio, kurs, facultet, spec.

typedef struct

{

char fio[30];       // ФИО студента

int kurs ;           // курс

char facultet[50]; // наименование факультета

char spec[50] ; // специальность

} stud;

Тогда, чтобы решать задачи об обработке списков студентов, необходимо создать массив структур (статический или динамический) типа stud и обработать его согласно поставленной задаче.

 

Определение статического массива структур

 

Объявление статического массива std из 20 структур типа stud:

stud std[20];

Массив представлен на рис.8.

  Элемент массива Элемент массива

Элемент массива
       

Поля

структуры

fio fio

fio
kurs kurs kurs
facultet facultet facultet
spec spec spec
       
№ элемента массива 0 1 19

Рис.8

Примеры обращения к полям элемента массива с номером i:

gets(std[i].fio);                 //вводится с клавиатуры поле fio

scanf("%i",&std[i].kurs); //с клавиатуры вводится целочисленное поле

                                    // kurs


Определение динамического массива из n структур

Объявление указателя  на структуру типа stud:

stud *st;

int n;

printf("n=");

scanf("%i",&n); //ввод количества элементов динамического массива st

st=(stud*)malloc(n*sizeof(stud)); // выделение динамической памяти

                                                  // под n структур типа stud.

Массив представлен на рис.9. Значением переменной st будет адрес нулевого элемента (первой структуры) динамического массива структур. Число n будет определять количество однотипных объектов (структурный тип stud описывает каждый такой объект), информация о которых будет храниться в созданном динамическом массиве. Именем этого массива будет имя указателя st.

 

  Элемент массива Элемент массива

Элемент массива
     

Поля

структуры

fio fio

fio
kurs kurs kurs
facultet facultet facultet
spec spec spec
st      
№ элемента массива 0 1 n-1

Рис.9

Примеры обращения к полям i-го элемента динамического массива структур st.

gets((st+i)–>fio); //вводится с клавиатуры поле fio

scanf("%i",&(st+i)–>kurs); //с клавиатуры вводится целочисленное

                                        //поле kurs

printf ("kurs=%i\n",(st+i)–>kurs); // на экран выводится значение поля

                                                  // kurs

Здесь операция & определяет адрес в ОП поля kurs i-го элемента динамического массива структур st. Операция –> (записанные последовательно друг за другом два знака: минус (–) и больше (>)) обозначает доступ к полю структуры через указатель:

 


Пример. Каждого студента можно описать при помощи следующих характеристик: ФИО, курс, специальность, предмет1, предмет2, предмет3. Написать программу, определяющую количество студентов:

1) сдавших сессию на «отлично»;

2) не сдавших хотя бы 1 экзамен.

 

Ход выполнения работы

1. Алгоритм решения данной задачи – алгоритм обработки одномерного массива. В задаче каждым элементом массива будет структура, т.е. элемент массива представляет собой набор переменных различного типа. Для ввода элемента массива нужно вводить значения каждого поля элемента массива поочередно. Так как работаем с массивом, то ввод-вывод элементов массива производится с помощью циклов с параметром.

2. Написать программу, соответствующую алгоритму.

Запишем алгоритм решения задачи и соответствующие программы с использованием статического и динамического массивов.

Использование динамических массивов:

Алгоритм Программа
структурный_тип stud {    сhar fio[30];    int kurs;    сhar spec[30];    int hist;    int math;    int phis; }; объявление stud *st; цел: n, i, count_5, count_2; ввод n выделение динамической памяти под указатель st для i=0 до n-1 шаг 1   заполнить каждое поле элемента  массива структур отдельно все_для i count_5=count_2=0 для i=0 до n-1 шаг 1   //определяем количество   //отличников   если sti–>hist= =5 && sti–>math= =5           && sti–>phis= =5      count_5++;   все_если   // определяем количество студентов,   // не сдавших хотя бы один экзамен   если sti–>hist==2|| sti–>math==2||            sti–>phis==2            count_2++;   все_если все_если все_для i печать count_5; печать count_2; освободить выделенную динамическую память под указатель st;     #include "stdio.h" #include "stdlib.h" typedef struct {    char fio[30];   int kurs;    char spec[30];   int hist;    int math;   int phis; } stud; int main() { stud *st; int n, i, count_5, count_2; printf("n="); scanf("%i",&n); st=(stud*)malloc(n*sizeof(stud)); // заполнение массива структур for(i=0;i<=n-1;i++) { printf(“fio=”);gets((st+i)–>fio); printf(“spec=”);gets((st+i)–>spec); printf(" kurs="); scanf("%i",&(st+i)–>kurs); printf(" history="); scanf("%i",&(st+i)–>hist); printf(" math="); scanf("%i",&(st+i)–>math); printf(" phis="); scanf("%i",&(st+i)–>phis); } count_5=count_2=0; for (i=0;i<=n-1;i++) { //определяем количество // отличников if((st+i)–>hist= =5&& (st+i)–>math= =5 && (st+i)–>phis==5) count_5++; //определяем количество студентов, //не сдавших хотя бы один экзамен if((st+i)–>hist= =2||               (st+i)–>math= =2|| (st+i)–>phis= =2) count_2++; } printf("count_5=%i\n",count_5); printf("count_2=%i\n",count_2); free(st); return; }

Использование статических массивов:

Алгоритм Программа
структурный_тип stud {    сhar fio[30];    int kurs;    сhar spec[30];   int hist;       int math;    int phis; }; объявление stud st[10]; цел: i, count_5, count_2; для i=0 до 10-1 шаг 1   заполнить каждое поле  элемента массива   структур отдельно все_для i count_5=count_2=0 для i=0 до 10-1 шаг 1   //определяем количество   //отличников   если st[i]–>hist= =5 &&            st[i]–>math= =5 &&            st[i]–>phis= =5      count_5++;   все_если   // определяем количество   // студентов, не сдавших   // хотя бы один экзамен   если st[i]–>hist= =2||            st[i]–>math= =2||            st[i]–>phis= =2            count_2++;   все_если все_если все_для i печать count_5; печать count_2;     #include "stdio.h" #include "stdlib.h" #define n 10 typedef struct {    char fio[30];   int kurs;    char spec[30];   int hist;    int math;    int phis; } stud; int main() { stud st[n]; int i, count_5, count_2; // заполнение массива структур for(i=0;i<=n-1;i++) { printf(“fio=”);gets(st[i].fio); printf(" kurs=");scanf("%i",&st[i].kurs); printf(“spec=”);gets(st[i].spec); printf(" history=");scanf("%i",&st[i].hist); printf(" math=");scanf("%i",&st[i].math); printf(" phis=");scanf("%i",&st[i].phis); } count_5=count_2=0; for (i=0;i<=n-1;i++) { //определяем количество отличников if(st[i].hist= =5&&st[i].math= =5&& st[i].phis= =5) count_5++; //определяем количество студентов, //не сдавших хотя бы один экзамен if(st[i].hist= =2|| st[i].math= =2|| st[i].phis= =2) count_2++; } printf("count_5=%i\n",count_5); printf("count_2=%i\n",count_2); return; }

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

Л екция 16

Файлы

Цели:

ü получить представление о потоке и потоковом вводе-выводе; файлах и функциях, работающих с файлами.

Потоковый ввод-вывод данных

 

Процесс ввода-вывода данных предполагает обмен данными между ОП и внешними устройствами. Например, между ОП и клавиатурой, ОП и жестким диском и др. Под вводом понимается запись данных с внешнего устройства в ОП; под выводом – чтение информации из ОП и перенос этой информации на внешнее устройство.

В языке С++ процесс ввода-вывода информации тесно связан с понятием потока – последовательностью байтов, передаваемой в процессе ввода-вывода данных. Так как при вводе-выводе информации создается связь между ОП и внешними устройствами, то в процессе выполнения программы созданные потоки связываются с конкретными внешними устройствами. По-другому говорят, что поток направлен на внешнее устройство.

При запуске программы кроме потоков, которые объявляет программист, создаются три основных стандартных потока:

1) stdin – поток стандартного ввода (как правило связан с клавиатурой);

2) stdout – поток стандартного вывода (обычно связан с монитором);

3) stderr – поток сообщений об ошибках (всегда связан с монитором).

 

2. Форматированный ввод-вывод в С++

 

В разделе «Линейные вычислительные процессы» были рассмотрены функции ввода–вывода printf() и scanf(). В языке С++ существует стан­дартная библиотека (головной файл), ориентированная на организацию потокового форматированного ввода-вывода – iostream.h. Потоковый форматированный ввод-вывод в С++ основан на понятии объектов, под которыми понимаются величины, содержащие в себе свойства (характеризуют состояние объекта в данный момент времени) и методы (функции, которые могут изменять свойства объекта).

В библиотеке iostream.h описаны два объекта:

1) cout – поток вывода, связанный с дисплеем;

2) cin – поток ввода, связанный с клавиатурой.

Знак << (два знака меньше подряд) обозначает операцию вставки символов в поток вывода cout, а знак >> (два знака больше подряд) – операцию извлечения из потока ввода cin:

int i;

float f;

cout<<"Введите целое число ";//на монитор выводится текст

cin>>i; //с клавиатуры вводится целое число

f=5.9*i;

//на монитор выводится текст и значение переменной

cout<<"Значение f = "<<f<<"\n";

Часть строки "\n" обозначает перевод курсора на следующую строку.

Для организации форматированного потокового ввода-вывода в С++ существуют два средства: применение флагов форматирования; применение манипуляторов.

Флаги форматирования управляют форматом выводимых значений и тесно связаны с объектно-ориентированным программированием, поэтому в этом разделе не будем их рассматривать.

Для управления форматами потокового вывода можно использовать специальные функции, называемые манипуляторами. Доступ к стандартным манипуляторам можно получить, подключив файл iomanip.h. Список стандартных манипуляторов:

Манипулятор Назначение манипулятора
dec Десятичный формат
endl Вывод "\n" и освобождение буфера
hex Шестнадцатеричный формат числа
setbase(int baz) Установить основание системы счисления baz
setfill(char ch) Установить символ заполнения ch
setprecision (int pr) Установить рr цифр в дробной части
setw(int wd) Установить ширину wd поля выдачи

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

 

Программа, реализующая эту задачу:

 

#include <iostream.h>

#include <math.h>

#include <iomanip.h>

int main()

{

float a,b,x,h;

int i;

a=0;  

b=4*atan(1);

h=(b-a)/10;

cout<<" x sin(x) cos (x)"<<endl;

cout<<endl;

x=a;

for(i=1; i<=10; i++)

{

cout<<setprecision (4)<<setw(7)<<x<<" "

<<setprecision(4)<<setw(7)<<sin(x)<<" "

<<setprecision(4)<<setw(7)<<cos(x)<<endl;

x=x+h;

}

return 1;

}

Результат работы программы:

Под каждое выводимое значение выделяется по 7 позиций на экране. По умолчанию число занимает крайнюю правую позицию в отведенном под него поле. Оставшиеся слева позиции занимает символ-заполнитель. По умолчанию символом-заполнителем является пробел. Однако с помощью манипулятора setfill() его можно заменить. Если в крайних правых позициях оказываются нули, то они не выводятся. Действие манипулятора распространяется только на значение, непосредственно следующее за ним в потоке вывода.

 

Понятие файла.

Функции работы с файлами

 

Файлом в С++, с одной стороны, называется последовательность байт, ограниченная стандартной константой EOF – признаком конца файла, с другой стороны, файлом называют некоторое пространство (объём памяти) на жёстком диске или некотором носителе. Таким образом, работа с файлами (запись в файл информации, чтение данных из файла) невозможна без создания потоков.

При работе с файлами создается указатель на поток байтов. Этот поток может быть направлен из ОП на жёсткий диск при записи информации в файл или в ОП с жесткого диска при чтении информации из файла. Кроме того, при чтении или записи информации в файл особое место занимает переменная, которая носит название «указатель файла». Указатель файла определяет позицию (номер байта) в файле, начиная с которой записывается или считывается некоторая порция информации. Следовательно, указатель файла – это  адрес байта,  который  предназначен

для текущей обработки.

В языке С++ работают с потоками (файлами) двух видов: текстовыми и двоичными. Текстовый поток – последовательность символов. В данном разделе такие потоки рассматриваться не будут. Двоичный поток – это последовательность байтов, соответствующая байтам на внешнем устройстве. Далее рассматривается работа именно с такими потоками. 

Объявление указателя на поток, который может быть направлен на жесткий диск (файл) записывается в виде:

FILE *<имя_указателя>;

Слово FILE – стандартное имя структурного типа, описанного в головном файле stdio.h. В этой структуре содержится вся необходимая информация для работы с файлами (например, указатель файла и др.).

Следующий этап – это открытие потока с помощью стандартной функции fopen(). Форма открытия потока:

<имя_указателя_на_поток>=fopen(<имя_файла>,<режим_открытия_файла>);

<имя_файла> – строковая величина следующего формата. "<имя>.<расширение>" определяет имя физического файла расположенного на диске. <имя> файла – полный путь к файлу с указанием имени диска и имён папок, в которых находится этот файл. Полный путь записывается в случае, если открываемый файл находится не в одной папке с исполняемой программой. Под строкой <расширение> понимается тип файла.

<режим_открытия_файла> – строковая величина, определяющая режим работы с открытым файлом. Режимы открытия файлов даны в табл.11.

Таблица 11

Параметр Режим
1 2
"r" Файл открывается только для чтения: Ø если файла с указанным именем не существует, то его открытие приведет к остановке программы; Ø если открываемый файл с указанным именем существует, то открывается для чтения
"w" Файл открывается только для записи: Ø если файла с указанным именем не существует, то он создаётся в той же папке, что и исполняемая программа; Ø если открываемый файл с указанным именем уже существует, то вся информация из этого файла удаляется. В этот файл можно только записывать информацию
"а" Файл открывается для добавления данных: Ø если файл с указанным именем существует, то данные будут записываться в конец файла; Ø если файла с указанным именем не существует, то он создаётся, и в него может только записываться информация
   

Продолжение таблицы 11

1 2
"r+" Файл открывается для чтения и записи. Информация записывается с того места, на которое ссылается указатель файла
"w+" Файл создаётся для чтения и записи. Информация записывается с того места, на которое ссылается указатель файла
"a+" Файл открывается для добавления данных и чтения

 

Если  файл  не  может  быть  открыт  по  какой-либо  причине,  то функция fopen() возвращает значение NULL.

Конструкция, позволяющая открыть файл. Если файл невозможно открыть, то работа программы будет корректно завершена:

FILE*pf;

if((pf=fopen("my_file.dat", "r+”)) = = NULL)

{

printf("файл не открыт\n"); return 1;

}

Если поток (файл) открыт удачно, то можно записывать или считывать информацию с жесткого диска (файла) с помощью функций fwrite() или fread(). Формат записи этих функций выглядит следующим образом.

Функция чтения блока данных из файла:

i=fread(<адрес_буфера>,<объем_данных_блока>,<число_читаемых_блоков>, <указатель на поток>);

Здесь i – переменная типа int; i = 1, если было произведено чтение из файла; i = 0, если чтение из файла невозможно; <адрес_буфера> – адрес переменной-буфера в ОП, по которому записываются читаемые данные из файла; <объем_данных_блока> – объем в байтах читаемых в буфер данных из файла; <число_читаемых_блоков> – количество блоков, читаемых из файла. Размер каждого блока указывается в параметре <объем_данных_блока>. <указатель на поток> – указатель на файл.

Функция записи в файл:

i=fwrite(<адрес_буфера>,<объем_данных_блока>,<число_записываемых_блоков>, <указатель на поток>);

Здесь i – переменная типа int; i = 1, если была произведена запись в файл; i = 0, если записи не было; <адрес_буфера> – адрес переменной-буфера в ОП, из которого считываются данные в файл; <объем_данных_блока> – объем в байтах записываемых данных в файл из буфера; <число_читаемых_блоков> – количество блоков, записываемых в файл. Размер каждого блока указывается в предыдущем параметре <объем_данных_блока>. <указатель на поток> – указатель на файл.

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

i = fseek (<указатель_на_поток>, <смещение>, <стартовая_позиция>) ;

Здесь i – переменная типа int; i = 1, если смещение произошло, i = 0, если, например, произошло смещение за пределы файла; <указатель на поток> – указатель на открытый поток; <смещение>  (длинное  целое)  –   значение,   которое   определяет,  на сколько байт от стартовой позиции будет смещён указатель файла. Если <смещение> больше нуля, то смещение производится к концу файла, если меньше нуля, то смещение происходит к началу файла. Нужно учитывать то, что автоматически не определяется, был ли указатель перемещен за пределы файла.

<стартовая_позиция> – одна из констант:

SEEK_SET  (или 0) – установка указателя файла на нулевой байт файла;

SEEK_CUR (или 1) – определение текущей позиции указателя файла;

SEEK_END (или 2) – установка указателя файла на последний байт файла.

В конце работы необходимо закрыть открытый поток с помощью стандартной функции fclose(). Формат её записи:

fclose(<имя_указателя_на_поток>);

Функции работы с файлами описаны в головном файле stdio.h. Примеры обращения к некоторым из них приведены в табл12.

Таблица 12

Функция Форма обращения к функции
1 2
fopen pf=fopen("my_file.dat", "r+"); pf – указатель на поток; "my_file.dat" – имя файла; "r+" – файл открывается в режиме чтения/записи
fgetc ch=fgetc(pf); pf – указатель на поток; считывает один символ в переменную ch (тип char) из файла pf. Если достигнут конец файла, то в ch записывается константа EOF
fputc сh1=fputc(ch, pf); pf – указатель на поток; записывает один символ в файл pf из переменной ch (тип char). Если запись произошла, то в ch1 (тип char) возвращается записанный символ, в противном случае в ch1 записывается константа EOF
getw i=getw(pf); pf – указатель на поток; считывает целое число в переменную i (тип int) из файла pf. Если достигнут конец файла, то в i записывается константа EOF
putw i1=putw(i, pf); pf – указатель на поток; записывает целое число в файл pf из переменной i (тип int). Если запись произошла, то в i1 (тип int) возвращается записанное число, в противном случае в i1 записывается константа EOF
fwrite i=fwrite(&buf, sizeof(block),num_block, pf); &buf – адрес буферной переменной; sizeof(block) – объем записываемых данных из переменой buf в файл; num_block – переменная типа int (число записываемых блоков); pf – указатель на файл

Продолжение таблицы 12

1 2
fread i=fread(&buf, sizeof(block),num_block, pf); &buf – адрес буферной переменной; sizeof(block) – объем читаемых данных в переменную buf из файла; num_block – переменная типа int (число читаемых блоков); pf – указатель на файл, из которого читается информация
fseek i=fseek(pf, -5, SEEK_END); pf – указатель на поток; -5 – смещение к началу файла; SEEK_END – смещение производится с последнего байта файла
rewind rewind(pf); pf – указатель на поток; возвращает указатель на нулевой байт файла pf
ftell li=ftell(pf); pf – указатель на поток; в переменную li (тип long int) возвращается значение указателя текущей позиции в файле pf
fclose fclose(pf); pf – имя_указателя_на_поток
remove remove ("my_file.dat"); Удаляет файл с именем "my_file.dat"

Для нахождения длины файла в байтах можно определить конструкцию:

FILE *pf;

long int n;

if((pf=fopen("my_file.dat", "r+”)) = = NULL)

{

printf("файл не открыт\n");

return 1;

}

fseek(pf, 0, SEEK_END); //указатель файла на последнем байте файла

n=ftell(pf); //в переменной n – значение указателя файла, т.е.

              //количество байт в файле

rewind(pf); //перемещение указателя файла в начало файла

 

 

Лекция 17

Файлы

Цели:

ü освоить методику написания алгоритмов с использованием файлов, перевода таких алгоритмов на язык программирования С++ и разработки соответствующего проекта в среде Visual C++ 6.0.

 

Работу с файлами можно сравнить с работой с массивами. Главное преимущество файлов перед массивами заключается в том, что массивы хранятся в ОП и информация исчезает с завершением работы программы, а информация, хранящаяся в файлах, может храниться нужное время на каком-либо носителе. Основной задачей, которая предполагает использование файлов, является обработка и хранение большого объёма информации. Когда происходит обработка информации из файла, программа часто обращается к файлу, следовательно, и к некоторой области жёсткого диска, что может нанести вред поверхности жёсткого диска. Поэтому нужно, определив размер файла, выделить динамическую память, в которую затем записать информацию из файла, обработать эту информацию и переписать обработанную информацию в файл. Для хранения и обработки информации из файла используют динамический массив структур и динамические структуры – списки, стеки, очереди.

 

Пример. Каждого студента можно описать при помощи следующих характеристик: ФИО, курс, специальность, предмет1, предмет2, предмет3. Написать программу (с использованием файлов), определяющую количество студентов:

1) сдавших сессию на «отлично»;

2) не сдавших хотя бы 1 экзамен.

 

Ход выполнения работы

1. Алгоритм должен быть универсальным с точки зрения пользователя. Это означает, что он должен давать возможность не только определять указанные в задаче характеристики, но и предлагать пользователю вводить данные в файл, добавлять в конец файла новую порцию информации и читать информацию из файла. Для достижения этих целей при написании программы воспользуемся оператором выбора switch(). При этом работа с файлом будет осуществляться не напрямую, а через динамический массив структур. Для ввода-вывода значений будут использоваться потоковые функции.

2. Написать программу, соответствующую алгоритму:

Алгоритм Программа
структурный_тип stud {    сhar fio[30];    int kurs;    сhar spec[30];   int hist;    int math;    int phis; }; объявление stud *st, FILE *pf; цел: var, n, i, count_5, count_2; var=0 пока var!=0 ввод var выбор var случай 1: // создание и             // запись в файл ввод n выделение динамической памяти под указатель st для i=0 до n-1 шаг 1   заполнить каждое поле  элемента массива   структур отдельно все_для i открыть файл pf в режиме записи записать в файл pf массив st закрыть файл освободить выделенную динамическую память под указатель st выход случай 2: //открытие файла            // для добавления ввод n выделение динамической памяти под указатель st для i=0 до n-1 шаг 1    заполнить каждое поле   элемента массива   структур отдельно все_для i открыть файл pf в режиме  добавления дозаписать в файл pf массив st закрыть файл освободить выделенную динамическую память под указатель st выход случай 3: // открытие файл в           // режиме чтения        //определение        // характеристик открыть файл pf в режиме чтения определить длину файла n выделение динамической памяти под указатель st заполнить массив st из файла pf count_5=count_2=0 для i=0 до n-1 шаг 1   //определяем //количество отличников   если sti–>hist= =5 &&            sti–>math= =5 &&            sti–>phis= =5    count_5++;   все_если //определяем количество // студентов, не //сдавших хотя бы один //экзамен   если sti–>hist= =2||            sti–>math= =2||            sti–>phis= =2            count_2++;   все_если все_если все_для i закрыть файл освободить выделенную динамическую память под указатель st печать count_5; печать count_2; выход все_выбор все_цикл #include "stdio.h" #include "stdlib.h" #include "iostream.h" #include "iomanip.h" typedef struct {    char fio[30];   int kurs;    char spec[30];   int hist;    int math;    int phis; } stud; int main() { stud *st; FILE *pf; int var, i, count_5, count_2; long int n; var=-1; while(var!=0) { cout<<"0–выход; 1–запись; "    <<"2–добавление;"    <<"3–характеристики: var="; cin>>var; switch(var) { case 1: cout<<"n="; cin>>n; st=(stud*)malloc(n*sizeof(stud)); //заполнение массива структур for(i=0;i<=n-1;i++) { cout<<"fio="; cin>>((st+i)–>fio); cout<<"kurs="; cin>>((st+i)–>kurs); cout<<"spec="; cin>>((st+i)–>spec); cout<<"history=";cin>>((st+i)–>hist); cout<<"math="; cin>>((st+i)–>math); cout<<"phis="; cin>>((st+i)–>phis); } //файл открывается для записи данных if((pf=fopen("my_f.dat","w”))==NULL) { printf("файл не открыт\n"); break; } //запись в файл fwrite(st, sizeof(stud), n, pf); fclose(pf); free(st); break; case 2: cout<<"n="; cin>>n; st=(stud*)malloc(n*sizeof(stud)); //заполнение массива структур for(i=0;i<=n-1;i++) { cout<<"fio="; cin>>((st+i)–>fio); cout<<"kurs="; cin>>((st+i)–>kurs); cout<<"spec="; cin>>((st+i)–>spec); cout<<"history=";cin>>((st+i)–>hist); cout<<"math=";cin>>((st+i)–>math); cout<<"phis="; cin>>((st+i)–>phis); } //файл открывается для добавления if((pf=fopen("my_f.dat","a”))==NULL) { printf("файл не открыт\n"); break; } //дозапись в файл fwrite(st, sizeof(stud), n, pf); fclose(pf); free(st); break; case 3: //файл открывается для чтения if((pf=fopen("my_f.dat","r”))==NULL) { printf("файл не открыт\n"); break; } //определение длины файла в байтах fseek(pf, 0, SEEK_END); n=ftell(pf); //n – количества записей в файле n=n/sizeof(stud); st=(stud*)malloc(n*sizeof(stud)); rewind(pf); //заполнение массива структур fread(st, sizeof(stud), n, pf); count_5=count_2=0; for (i=0;i<=n-1;i++) {    //количество отличников if((st+i)–>hist= =5&& (st+i)–>math= =5&& (st+i)–>phis= =5)     count_5++; //количество студентов, не //сдавших хотя бы один экзамен if((st+i)–>hist= =2|| (st+i)–>math= =2|| (st+i)–>phis= =2) count_2++; } cout<<"count_5="<<count_5<<endl; cout<<"count_2="<<count_2<<endl; fclose(pf); free(st); break; } }return 1; }

Примечание. Записью в файле называется блок данных, хранящихся в одной структуре, т.е. порция информации об одном студенте (в данном примере).

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

Лекция 1 8

Функции пользователя

 

Цели:

ü познакомиться с приемами построения алгоритмов;

ü получить представление о пользовательских функциях, освоить методику их написания.

 


Дата добавления: 2019-11-25; просмотров: 274; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!