По выполнению контрольной работы по курсу
Методические указания
По выполнению контрольной работы по курсу
«Основы алгоритмизации и программирования» (ОАиП)
для студентов заочного отделения ИИТ
Минск 2007
Рукопись
Авторы:
А. Г. Корбит, Т. М. Кривоносова
Методические указания по выполнению контрольной работыпо курсу «Основы алгоритмизации и программирования» для студентов заочного отделения ИИТ. / Корбит А.Г., Кривоносова Т.М. – Минск: БГУИР, 2007.
В практикуме изложены краткие теоретические сведения по основам алгоритмического языка С/С++. Содержатся примеры, реализованные в консольном приложении, приведены 6 лабораторных работ и индивидуальные задания к ним.
© УО «Белорусский государственный университет информатики и радиоэлектроники», 2007 |
СОДЕРЖАНИЕ
Общие требования к оформлению контрольной работы 4
Задание №1. Линейный вычислительный процесс.. 4
1.1. Теоретические сведения. 4
1.2. Пример выполнения задания. 9
1.3. Индивидуальные задания. 10
Задание №2. Реализация разветвляющихся алгоритмов 11
2.1. Теоретические сведения. 12
2.2. Пример выполнения задания. 13
2.3. Индивидуальные задания. 14
Задание №3. Реализация циклических алгоритмов.. 17
3.1. Теоретические сведения. 17
3.2. Пример выполнения задания. 17
3.3. Индивидуальные задания. 19
Задание №4. Обработка одномерных массивов.. 20
4.1. Теоретические сведения. 20
4.2. Пример выполнения задания. 21
4.3. Индивидуальные задания. 22
Задание №5. Обработка двухмерных динамических массивов. Функции пользователя.. 23
5.1. Теоретические сведения. 23
5.2. Пример выполнения задания. 27
5.3. Индивидуальные задания. 29
Дополнительное задание №6. Обработка структур с использованием файлов.. 30
6.1. Теоретические сведения. 30
6.2. Пример выполнения задания. 32
6.3. Индивидуальные задания. 35
Приложение. Операции языка С/С++. 37
Основная литература.. 39
Дополнительная литература.. 39
Общие требования к оформлению контрольной работы
1. Стандартный титульный лист, с указанным номером варианта задания, должен быть подписан исполнителем.
2. Отчет о решенных задачах должен содержать:
– постановку задачи;
– структурную (обобщенную) схему алгоритма;
– листинг (текст кода) программы с пояснением его отдельных участков;
– результаты (экранные формы), иллюстрирующие работоспособность программы;
– список используемой литературы.
В зачетной сессии контрольная должна быть защищена (демонстрация на ПК решения задач своего варианта, указанного в списке группы).
Задание №1. Линейный вычислительный процесс
Цель работы: изучить правила составления текстов программ, научиться реализовывать линейные алгоритмы. Написать и отладить программу линейного алгоритма в консольном приложении.
Теоретические сведения
Алфавит языка С/С++ состоит из: прописных и строчных букв латинского алфавита, арабских цифр и специальных символов, смысл и правила, использования которых будут рассматриваться далее.
В языке C применяются данные двух категорий: простые (скалярные) и сложные (составные).
К основным (базовым) типам данных относятся целый (int), вещественный (float, double) и символьный (char) типы. В свою очередь, данные целого типа могут быть короткими (short) и длинными (long), со знаком (signed) и беззнаковыми (unsigned). Атрибут long может использоваться и с типом double – длинное вещественное.
К сложным типам данных относятся массивы, структуры (struct), объединения (union) и перечисления (enum).
Запись самоопределенных констант
Тип данных | Общий формат записи | Примеры |
Десятичные целые | ±n | 22 –15 176 –1925 |
Вещественные с фиксированной десятичной точкой | ±n.m | 1.0 –3.125 –0.001 |
Вещественные с плавающей точкой | ±n.mE±p смысл записи ±n,m×10±p | 1.01E–10 0.12537е+4 |
Символьные | ' * ' | 'A' 'х' '0' '<' |
Строковые | “ ****** ” | “Minsk” “Press any key” |
В таблице * – любой символ, набранный на клавиатуре.
Декларация объектов
Все объекты (переменные, массивы и т.д.), с которыми работает программа, необходимо декларировать. В декларации объектам присваиваются идентификаторы (ID), которые могут включать латинские буквы, символ нижнего подчеркивания «_» и цифры, причем первым символом ID не может быть цифра.
Внимание! В языке С/С++ строчные и прописные буквы имеют различные коды, т.е. PI, Pi и pi – различные идентификаторы (прил. 1).
При декларации объектам можно задавать начальные значения (инициализировать), например:
int k = 10, m = 3, n;
double c = –1.3, w = –10.23, s;
Принято использовать в ID переменных строчные буквы, а в именованных константах – прописные, например:
const double PI = 3.1415926;
double pi = 3.1415926;
Разделителями ID являются пробелы, символы табуляции, перевода строки и страницы, а также комментарии.
Комментарий – любая последовательность символов, начинающаяся парой символов /* и заканчивающаяся парой символов */ или начинающаяся // и до конца текущей строки.
Директивы препроцессора
Перед компиляцией программы с помощью директив препроцессора выполняется предварительная обработка текста программы.
Директивы начинаются с символа # (шарп), за которым следует наименование операции препроцессора. Чаще всего используются директивы include и define.
Директива #include используется для подключения к программе заголовочных файлов с декларацией стандартных библиотечных функций, например:
#include <stdio.h> – стандартные функции ввода-вывода;
#include <conio.h> – функции работы с консолью;
#include <math.h> – математические функции.
Директива #define(определить) создает макроконстанту и ее действие распространяется на весь файл, например:
#define PI 3.1415927
– в ходе препроцессорной обработки идентификатор PI везде заменяется указанным значением 3,1415927.
Операции языка С/С++(арифметические: +,–,*,/,%) и наиболее часто использующиеся стандартные математические функцииописаны в прил.1.
Операция присваивания имеет полную и сокращенную формы записи.
Полная форма: ID = выражение;
– выполняется справа налево, т.е. сначала вычисляется выражение, а затем его результат присваивается указанному ID, например: y=(x+2)/(3*x)–5;
В одном операторе можно присвоить значение нескольким переменным, например: x = y = z = 0;
или z = (x = y) * 5; – сначала переменной x присваивается значение переменной y, далее вычисляется выражение x*5 , и результат присваивается переменной z.
Сокращенная форма:IDоперация=выражениe;
где операция – одна из арифметических операций + , –, *, /, %;например:
s += 7; (s = s+7;) или y *= x+3; (y = y*(x+3));
Сокращенная форма применяется, когда переменная используется в обеих частях ее полной формы.
В языке С/С++ существуют операции инкремента (--) и декремента (++), т.е. уменьшения или увеличения значения переменной на 1. Операции могут быть префиксные (++i и --i) и постфиксные (i++ и i--). При использовании данной операции в выражении в префиксной форме, сначала выполняется сама операция (изменяется значение i), и только потом вычисляется выражение. В постфиксной форме – операция применяется после вычисления выражения, например, для значений b = 7 и n = 1 будут получены следующие результаты:
1) c = b*++n; – порядок выполнения: n = n+1, c = b*n, т.е. c = 14;
2) c = b*n++; – в этом случае: c = b*n, n = n+1, т.е. c = 7 .
Задание №2. Реализация разветвляющихся алгоритмов
Цель работы: изучить операции сравнения, логические операции, операторы передачи управления if, switch, break. Написать и отладить программу с разветвлениями.
Теоретические сведения
Оператор выбора switch
Общая форма оператора выбора (переключателя):
switch(выражение){
caseconst_1: операторы; break;
…
caseconst_N: операторы;break;
default:операторы;
}
Вычисляется выражение и проверяется, совпадает ли его результат со значением одной из констант. При совпадении выполняются операторы этого case. Значениями const_1,…, const_N могут быть только целые или символьные константы. Конструкция default выполняется, если результат выражения не совпал ни с одной из констант, и может отсутствовать. Оператор break выполняет досрочный выход из switch (после выполнения ветви case все остальные будут опущены). Если оператор break в case не записан, то будут выполняться операторы следующих ветвей case до появления оператора break, либо до завершения оператора switch.
Например:
switсh(i) {
case 1: f=pow(x,2); break;
case 2: f=fabs(x); break;
case 3: f=sqrt(x); break;
default: printf(“Ошибка!”); exit(1);
}
f=f+5;
2.2. Пример выполнения задания
Ввести значения исходных данных x, y и z. Вычислить значение функции
Предусмотреть вывод сообщения, по какой ветви выполнялись вычисления.
Текст программы может иметь седующий вид (в комментариях указаны действия по вводу-выводу в потоках, набираемые вместо записанных):
#include <conio.h> // #include <iostream.h>
#include <stdio.h>
#include <math.h>
void main()
{
double x, y, z, u;
puts("Input x, y, z"); // cout << "Input x, y, z" << endl;
scanf("%lf%lf%lf",&x, &y, &z); // cin >> x >> y >> z;
if (x*y > z){
u = x*sin(y);
puts(" x*y > z"); // cout << " x*y > z" << endl;
}
else {
u = y*cos(x);
puts(" x*y <= z"); // cout << " x*y <= z" << endl;
}
printf("\n\t Rezult U = %8.6lf", u); // cout << "\n\t Rezult U = " << u;
puts("\nPress any key ... "); // cout <<"\nPress any key ... " << endl;
getch();
}
Результаты выполнения программы для различных исходных данных, вводимых в одной строке, разделяя их пробелами, могут иметь следующий вид:
1 вариант введенные значения соответсвуют первому условию:
2 вариант введенные значения соответсвуют второму условию:
2.3. Индивидуальные задания
Составить программу для вычисления значения rez в зависимости от поставленного условия.
Для получения результатов подобрать исходные данные так, чтобы выполнялись все возможные ветви алгоритма. Перед выводом полученного результата должно выводиться сообщение о ветви, при прохождении которой он получен. Обратите внимание, что возможен случай, при котором исходные данные не будут подходить ни для одного из предложенных условий.
1. rez =
2. rez =
3. rez =
4. rez =
5. rez =
6. rez =
7. rez =
8. rez =
9. rez =
10. rez = .
11. rez =
12. rez =
13. rez =
14. rez =
15. rez =
16. rez =
Задание №3. Реализация циклических алгоритмов
Цель работы: изучить циклические операторы while, do-while, for, научиться реализовывать циклические алгоритмы. Составить и отладить программу.
Теоретические сведения
Под циклом понимается многократное выполнение одних и тех же операторов при различных значениях промежуточных данных. Число повторений может быть задано в явной или неявной формах. Для организации повторений в языке C++ используются три различных оператора цикла.
1. Оператор цикла с предусловием
while (выражение)
код цикла
организует повторение операторов кода цикла до тех пор, пока выражение истинно (не равно 0), если выражение = 0 (ложно) при первом входе, то код цикла не выполнится ни разу. Если код цикла состоит более чем из одного оператора, то организуется блок.
2. Оператор цикла с постусловием
do
код цикла
while (выражение);
организует повторение кода цикла до тех пор, пока выполнится выражение истинно, после чего управление передается следующему за циклом оператору. Данный оператор гарантирует выполнение кода цикла хотя бы один раз.
3. Оператор с предусловием и коррекцией
for (выражение 1;выражение 2;выражение 3)
код цикла
где выражение 1 – начальное значение параметра цикла; выражение2 – проверка условия на продолжение цикла; выражение3 – изменение (коррекция) параметра цикла.
Вначале вычисляется выражение 1, затем проверяется выражение 2, если оно – истинно, то выполняется код цикла, затем производится коррекция в выражении 3, и так до тех пор, пока выражение 2 не примет значение «ложь».
Досрочный выход из операторов цикла выполняет оператор break, а оператор continue выполняет передачу управления в головной оператор цикла.
3.2. Пример выполнения задания
Написать и отладить программу вывода всех значений функции S(x) для аргумента х, изменяющегося в интервале от а до b c шагом h и заданном n.
.
Текст программы предложенного задания может иметь следующий вид (в комментариях указаны действия по вводу-выводу в потоках, набираемые вместо записанных):
#include <stdio.h> // include <iostream.h>
#include <conio.h>
void main()
{
double a, b, x, h, r, s;
int n, zn = -1, k;
puts("Input a,b,h,n"); // cout << "Input a,b,h,n" << endl;
scanf("%lf%lf%lf%d", &a, &b, &h, &n); // cin >> a >> b >> h >> n;
for(x = a; x<=b; x+=h) {
r = s = 1;
for(k = 1; k<=n; k++) {
r=zn*r*x/k;
s+=r;
}
printf("\n x= %8.2lf sum= %8.5lf", x,s);
// cout << "\n x= " << x << " sum= " << s;
}
puts("\nPress any key ... "); // cout << "\nPress any key ... " << endl;
getch();
}
Результат программы с введенными в одной строке значениями a=0.1, b=1.0, h=0.2 и n=10, будет иметь следующий вид:
3.3. Индивидуальные задания
Для каждого x, изменяющегося от a до b с шагом h, найти значения функции Y(x), суммы S(x) и |Y(x)–S(x)| и вывести в виде таблицы. Значения a, b, h и n вводятся с клавиатуры. Так как значение S(x) является рядом разложения функции Y(x), при правильном решении значения S и Y для заданного аргумента x (для тестовых значений исходных данных) должны совпадать в целой части и в первых двух-четырех позициях после десятичной точки.
Работу программы проверить для a = 0,1; b = 1,0; h = 0,1; значение параметра n выбрать в зависимости от задания.
1. , .
2. .
3. .
4. .
5. .
6. .
7. , .
8. , .
9. , .
10. , .
11. , .
12. , .
13. , .
14. , .
15., .
16. .
Задание №4. Обработка одномерных массивов
Цель работы: изучить составной тип данных – массив. Написать и отладить программу с использованием одномерных массивов.
Теоретические сведения
Массив – конечная последовательность данных одного типа. Массив – объект сложного типа, каждый элемент которого определяется именем (ID) и целочисленным значением индекса (номера), по которому к элементу массива производится доступ. Рассмотрим одномерные массивы.
Внимание! Индексы массивов в языке С/С++ начинаются с 0.
В программе одномерный массив декларируется следующим образом:
тип ID массива [размер];
где размер – указывает количество элементов в массиве. Размер массива может задаваться константой или константным выражением. Для использования массивов переменного размера существует отдельный механизм – динамическое выделение памяти.
Примеры декларации массивов:
int a[5];
double b[4] = {1.5, 2.5, 3.75};
в целочисленном массиве а первый элемент а[0], второй – а[1], …, пятый – а[4]. Для массива b, состоящего из действительных чисел, выполнена инициализация, причем элементы массива получат следующие значения: b[0]=1.5, b[1]=2.5, b[2]=3.75, b[3]=0.
В языке С/С++ не проверяется выход индекса за пределы массива. Корректность использования индексов элементов массива должен контролировать программист.
Примеры описания массивов:
const Nmax=10; – задание максимального значения;
typedef double mas1[Nmax*2]; – описание типа одномерного массива;
mas1 a; – декларация массива а типа mas1;
int ss[10]; – массив из десяти целых чисел.
Элементы массивов могут использоваться в выражениях так же, как и обычные переменные, например:
f = 2*a[3] + a[Ss[i] + 1]*3;
a[n] = 1 + sqrt(fabs(a[n–1]));
4.2. Пример выполнения задания
В статическом массиве А размером N (не более 20), состоящем из целых чисел найти количество четных чисел и их сумму. Размер массива и его элементы вводятся с клавиатуры.
Текст программы с использованием ввода-вывода в потоках может иметь следующий вид:
#include <iostream.h>
#include <conio.h>
void main()
{
int a[20], n, i, kol = 0, s = 0;
cout << "\t Input N (<=20) ";
cin >> n;
cout <<"\n\t Massiv A" << endl;
for(i = 0; i < n; i++) {
cout << "\t a[ " << i+1 << " ] = ";
cin >> a[i];
}
for(i=0; i<n;i++)
if(a[i] % 2 == 0){
kol++;
s += a[i];
}
cout << "\n Kol-vo = " << kol << "\t Summa = " << s << endl;
cout << "\n Press any key ... " << endl;
getch();
}
Результат выполнения программы может иметь следующий вид:
4.3. Индивидуальные задания
В одномерном целочисленном массиве (размер массива (не больше 20) и значения его элементов вводить с клавиатуры) вычислить:
1. Произведение элементов массива, расположенных между максимальным и минимальным элементами.
2. Сумму элементов массива, расположенных между первым и последним нулевыми элементами.
3. Сумму элементов массива, расположенных до последнего положительного элемента.
4. Сумму элементов массива, расположенных между первым и последним положительными элементами.
5. Произведение элементов массива, расположенных между первым и вторым нулевыми элементами.
6. Сумму элементов массива, расположенных между первым и вторым отрицательными элементами.
7. Сумму элементов массива, расположенных до минимального элемента.
8. Сумму целых частей элементов массива, расположенных после последнего отрицательного элемента.
9. Сумму элементов массива, расположенных после последнего элемента, равного нулю.
10. Сумму модулей элементов массива, расположенных после минимального по модулю элемента.
11. Сумму элементов массива, расположенных после минимального элемента.
12. Сумму элементов массива, расположенных после первого положительного элемента.
13. Сумму модулей элементов массива, расположенных после первого отрицательного элемента.
14. Сумму модулей элементов массива, расположенных после первого элемента, равного нулю.
15. Сумму положительных элементов массива, расположенных до максимального элемента.
16. Произведение элементов массива, расположенных между первым и последним отрицательными элементами.
Задание №5. Обработка двухмерных динамических массивов. Функции пользователя
Цель работы: изучить понятие «указатель», правила создания и приемы обработки динамических массивов на примере двухмерного массива. Познакомиться с механизмом составления и организации взаимодействия пользовательских функций, составить и отладить программу.
Теоретические сведения
Указатели на указатели
Связь указателей и массивов с одним измерением справедливо и для массивов с бóльшим числом измерений.
Если рассматривать предыдущий массив (int a[2][3];) как массив двух массивов размерностью по три элемента каждый, то обращение к элементу а[i][j] соответствует эквивалентное выражение *(*(а+i)+j), а объявление этого массива с использованием указателей будет иметь вид
int **а;
Таким образом, имя двухмерного массива – ID указателя на указатель.
Функции пользователя
Подпрограмма – это именованная и определенным образом оформленная группа операторов, вызываемая по мере необходимости.
В языке С++ в качестве подпрограмм используют функции, которые должны быть декларированы до их первого использования. Предварительное описание функции называется прототипом, который обычно размещается в начале программы (*.cpp) либо в заголовочном файле (*.h) и сообщает компилятору о том, что далее в программе будет приведен ее полный текст, т.е. реализация.
Описание прототипа имеет следующий вид:
тип_результата ID_функции (список типов параметров);
а определение функции имеет следующую структуру:
тип_результата ID_функции (список параметров)
{
код функции
return результат;
}
Результат возвращается из функции в точку вызова при помощи оператора returnи преобразуется к типу, указанному в заголовке функции. Если тип функции не указан, то по умолчанию устанавливается тип int, если же функция не возвращает результата, то следует указать пустой тип void. Список параметров состоит из перечня типов и ID параметров, разделенных запятыми.
Из функции можно передать только одно значение, при необходимости возвратить несколько – в списке параметров используют указатели.
Пример реализации функции, определяющей наименьшее из двух целых чисел:
int Min_x_y(int x, int y) {
return (x<y) ? x : y;
}
Вызов функции имеет следующий формат:
ID_функции(список аргументов);
где в качестве аргументов можно использовать константы, переменные, выражения (их значения перед вызовом функции будут компилятором определены). Аргументы списка вызова должны совпадать со списком параметров вызываемой функции по количеству и порядку следования параметров, а типы аргументов при передаче будут преобразованы к указанным в функции типам параметров.
Вызов предыдущей функции может иметь вид: min = Min_x_y(a, b);
Область действия переменных
Область действия переменной – это правила, которые устанавливают, какие данные доступны из текущего места программы, и определяют переменные двух типов: глобальные и локальные.
Глобальные переменные объявляются вне какой-либо функции и могут быть использованы в любом месте программы, но перед их первым использованием они должны быть объявлены и инициализированы. Область действия глобальных переменных – вся программа с момента их объявления. При объявлении глобальные переменные обнуляются.
Область действия локальных переменных – это блоки, где они объявлены. К локальным относятся и формальные параметры в заголовке функций пользователя с бластью действия – кодом функции. При выходе из блока значения локальных переменных теряются.
В языке С каждая переменная принадлежит одному из четырех классов памяти – автоматической (auto), внешней (extern), статической (static) и регистровой (register). Тип памяти указывается перед спецификацией типа, например, register int a; или static double b; По умолчанию устанавливается класс auto и переменные размещаются в стеке.
5.2. Пример выполнения задания
В целочисленном двухмерном динамическом массиве (матрице) размером N´М найти сумму четных элементов и их количество. Ввод исходных данных (размеры массива и его элементы) и вывод результатов выполнить в основной функции. Решение поставленной задачи оформить в фунции пользователя.
Текст программы может иметь следующий вид:
#include <iostream.h>
#include <conio.h>
int Fun_Sum_Kol(int, int, int**, int*); // Описание прототипа функции
void main()
{
int **a, i, j, n, m, sum, kol;
cout << "\t Input N, M : ";
cin >> n >> m;
a = new int*[n]; // Захват памяти под указатели
for(i=0; i<n;i++)
a[i] = new int[m]; // Захват памяти под элементы
cout <<"\n Input A" << endl;
for(i=0; i<n; i++)
for(j=0; j<m; j++){
cout << "\t a[" << i+1 << "][" << j+1 << "] = ";
cin >> a[i][j];
}
cout <<"\n Matrix A:" << endl;
for(i=0; i<n; i++) {
for(j=0; j<m; j++)
cout << "\t" << a[i][j];
cout << endl;
}
// Обращение к функции с указанием фактических аргументов
sum = Fun_Sum_Kol(n, m, a, &kol);
cout << "\n Kol-vo = " << kol << "\t Summa = " << sum << endl;
delete []a; // Освобождение памяти
cout << "\n\t Delete !" << endl;
cout << " Press any key ... " << endl;
getch();
}
/* Реализация описанной выше функции, в заголовке которой указаны формальные параметры, идентификаторы которых обрабатываются в ее коде */
int Fun_Sum_Kol(int a, int b, int **x, int *k)
{
int i, j, s = 0;
*k = 0;
for(i=0; i<a;i++)
for(j=0; j<b;j++)
if(x[i][j] % 2 ==0){
(*k)++; // Скобки обязательны
s += x[i][j];
}
return s;
}
Обратите внимание на то, что из функции мы должны получить два скалярных результата – посчитанные сумму и количество четных чисел. С помощью оператора return мы возвращаем первое значение (сумму), а второе значение мы передаем в точку вызова с помощью указателя (адреса): при обращении к функции в качестве четвертого параметра передаем адрес &kol, а в функции используем «содержимое, находящееся по указанному адресу» *k ( * – операция разадресации).
При вводе значений элементов массивов в одной строке через пробелы должен получиться следующий результат:
5.3. Индивидуальные задания
В двухмерном целочисленном массиве (размеры массива N, M и значения его элементов вводить с клавиатуры) найти указанное значение.
Массив в памяти разместить динамически (с использованием операций new и delete), ввод исходных данных и вывод полученных результатов выполнить в основной функции, а решение задачи оформить в виде отдельной функции пользователя. Не использовать глобальных переменных.
1. Найти сумму элементов, расположенных на главной диагонали.
2. Найти произведение элементов, расположенных на главной диагонали.
3. Найти максимальный элемент и поменять его с первым элементом.
4. Найти минимальный элемент и поменять его с первым элементом.
5. Найти максимальный элемент и поменять его с последним элементом.
6. Найти минимальный элемент и поменять его с последним элементом.
7. Найти количество отрицательных и положительных элементов массива.
8. Найти количество 0-й и 1-ц в массиве, а также сумму единиц.
9. Найти число элементов массива, больших T (вводится с клавиатуры) и просуммировать эти элементы.
10. Найти число элементов массива > T* и их произведение.
11. Найти число элементов массива < T* и их сумму.
12. Найти число элементов массива < T* и перемножить эти элементы.
13. Найти число элементов массива = T* и сложить эти элементы.
14. Найти число элементов массива = T* и перемножить эти элементы.
15. Найти максимальный элемент среди лежащих ниже главной диагонали.
16. Найти минимальный элемент среди лежащих выше главной диагонали.
Дополнительное задание №6. Обработка структур с использованием файлов
Цель работы: изучить правила создания и обработки данных структурного типа с использованеием файлов. Написать и отладить программу по созданию файлов.
Теоретические сведения
Структура объединяет логически связанные данные разных типов. Структурный тип данных определяется описанием шаблона:
struct Рerson {
char Fio[30];
double sball;
};
Объявление переменных созданного структурного типа:
Person Stud, *p_Stud;
Обращение к элементам структур производится посредством:
1) операции принадлежности ( .) в виде:
ID_структуры . ID_поля или (*указатель) .ID_поля
2) операции косвенной адресации (–>) в виде:
указатель –> ID_поля или &(ID_структуры) . ID_поля
Для приведенного выше примера
1) Stud.Fio = “Иванов А.И.”; //Инициализация данных
Stud.sball = 5.75;
2) р_Stud –> Fio = “Иванов А.И.”;
р_Stud –> sball =5.75;
В языке C/С++ файл рассматривается как поток (stream), представляющий собой последовательность считываемых или записываемых байт. При этом последовательность записи определяется самой программой.
Работа с файлами
Файл – это набор данных, размещенный на внешнем носителе и рассматриваемый в процессе обработки и пересылке как единое целое. Прототипы большинства функций по обработке файлов описаны в библиотеках stdio.h и io.h.
Прежде чем работать с файлом, его нужно открыть для доступа, т.е. создать и инициализировать область данных, которая содержит информацию о файле: имя, путь и т.д. В языке С/С++ это выполняет функция fopen(), которая связывает физический файл на носителе с логическим именем в программе. Логическое имя – это указатель на файл, т.е. на область памяти, где хранится информация о файле. Указатели на файлы необходимо декларировать:
FILE *указатель на файл;
Формат функции
fopen( “строка 1” , “строка 2” );
в строке 1 указывается место, в которое мы собираемся поместить файл, например: “d:\\work\\sved.txt” – файл с именем sved.txt, который будет находиться на диске d, в папке work; если путь к файлу не указывать, то он будет размещен в рабочей папке проекта.
В строке 2 указывается код открытия файла:
w – для записи, если файла с заданным именем нет, то он будет создан, если же такой файл существует, то перед открытием прежняя информация уничтожается;
r– для чтения; если файла нет, то возникает ошибка;
a – для добавления новой информации в конец;
r+, w+ – возможны чтение и запись информации;
a+ – то же, что и для a, только запись можно выполнять в любое место файла, доступно и чтение файла.
По умолчанию файл открывается в текстовом режиме (t), указав b – файл открывается в двоичном режиме.
Если при открытии файла произошла ошибка, функция fopen возвращает значение NULL.
После работы доступ к файлу необходимо закрыть с помощью функции fclose(указатель файла), например, fclose ( f );
Для закрытия нескольких файлов введена функция: void fcloseall(void);
Приведем пример минимального набора операторов, необходимых для корректной работы с файлом:
#include <stdio.h>
. . .
FILE *f_my;
if( ! ( f_my = fopen(“rez.txt”, “r+t” ) ) ) {
puts(“\n Ошибка открытия файла!”);
return;
}
. . . // Работа с файлом
fclose(f_my);
. . .
Для работы с текстовыми файлами в консольном приложении удобнее всего пользоваться функциями fprintf() и fscanf(), параметры и выполняемые действия аналогичны функциям printf() и scanf(), (см. лаб.раб.№1), только первым параметром добавлен указатель файла, к которому применяется данная функция.
Функции работы с текстовыми файлами удобны при создании результирующих файлов для отчетов по лабораторным и курсовым работам.
Для создания баз данных удобнее пользоваться функциями работы с бинарными файлами. Рассмотрим некоторые из них, обозначив указатель файла – fp (FILE *fp;):
1) int fread(void *ptv, int size, int n, fp) – считывает n блоков по size байт каждый из файла fp в область памяти, на которую указывает ptv (необходимо заранее отвести память под считываемый блок);
2) int fwrite(void *ptv, int size, int n, fp) – записывает n блоков по size байт каждый из области памяти, на которую указывает ptv в файл fp;
3) int fileno(fp) – возвращает значение дескриптора файла fp (дескриптор –число, определяющее номер файла);
4) long filelength(int дескриптор) – возвращает длину файла в байтах;
5) int chsize(int дескриптор, long pos) – выполняет изменение размера файла fp, признак конца