ЗАМЕЧАНИЕ
Несмотря на широкое использование слова «функционал» для обозначения
набора функций программы, в русском языке оно является некорректным.
112
Функционал — понятие из математики, а в упомянутом контексте правильно
говорить «функциональность».
Особое внимание следует уделить удалению записей. Для уникальной
идентификации удаляемой записи (нельзя перепутать и отчислить из вуза
другого студента!) нужно выбрать комбинацию параметров, не
совпадающую ни у одной из возможных групп студентов. Вполне
обоснованным представляется использовать фамилию, имя, отчество и год
рождения — предполагаем, что даже если в нашем вузе встретятся полные
тезки, они не будут рожденными в один год. Реализовать удаление записи
можно по-разному. Например, воспользоваться следующей процедурой:
1.
Создать копию базы данных с именем Students.bak, перенести в нее
все записи, кроме удаляемой, например, с помощью цикла и проверки.
2.
Удалить исходный файл базы данных.
3.
Переименовать промежуточный файл, дав ему исходного —
Students.dat
.
Для удаления и переименования можно воспользоваться библиотечными
функциями remove и rename из все того же stdio.h. Их аргументами
являются имена файлов.
Альтернативным вариантом удаления является способ, при котором
удаляемые записи фактически не удаляются, а лишь особым образом
помечаются. Физическое удаление происходит при выполнении
специальной операции — сжатия базы данных.
После всего сказанного можно приступать к реализации программы.
Возможный вариант содержится в приложении А.
Контрольные вопросы
4.
Что такое нисходящее проектирование программ?
5.
Применимо ли к программам понятие «функционал»?
6.
Какую информацию о студенте вы сочли бы уместным сохранять
дополнительно к рассмотренной? Почему?
Особые возможности Си
В этом разделе мы рассмотрим отличительные особенности языка Си, в
других языках почти не встречающиеся, что делает их некой экзотикой.
Тем не менее их существование вызвано вполне серьезными причинами —
потребностями системного программирования.
Одна из важнейших особенностей Си, приближающая его по уровню к
языку ассемблера, — возможность использования так называемой
113
адресной арифметики. Напомним, что указатель — переменная,
используемая для хранения значения адреса в памяти ЭВМ, где
располагается некоторый другой объект (одиночная переменная, массив,
функция и др.). В случае их использования открываются интересные
возможности. Переменные, которые являются указателями, нужно
объявлять специальным образом:
int *a,*b; /* a и b — указатели на целые числа в памяти ЭВМ */
int* a; /* аналогично, где ставить звездочку — дело вкуса */
char *d; /* d —
указатель на символ или строку */
Переменную-указатель можно сравнить с предопределенным значением
NULL
(пустая ссылка). При выводе с помощью функций форматного
вывода printf можно использовать для указателей специальный
форматный символ %p (значение указателя — адрес — обычно
представляется в виде шестнадцатеричного числа).
В Си операция & (амперсанд) возвращает адрес объекта:
y=&x; /* y присваивается адрес x */
Обратная операция * (звездочка) используется для выборки содержимого
по указанному адресу в памяти:
z=*y; /* z присвоено значение по адресу y */
*y=7; /* занесение семерки по адресу y */
(*z)++; /* содержимое по адресу z увеличивается на единицу */
Указатели можно использовать в довольно сложных выражениях.
Но это не все. Поскольку адрес в памяти ЭВМ, фактически, представляет
собой целое число, то к нему применимы арифметические операции —
сложение, вычитание и др.:
*z++; /* адрес увеличен на размер типа данных в байтах, на который
ссылается z */
a=*(p+11); /*взятие значения из ячейки, на 11 элементов отстоящей от
p */
Можно складывать указатели друг с другом, а также указатели и целые
числа.
Как уже говорилось, параметры в языке программирования Си передаются
в функции по значению, что не дает прямой возможности изменить
переменные, объявленные в вызывающей функции, из вызываемой. В этом
случае допустимо использование указателей при объявлении функции,
например:
int utr3(int* a, int* b,int* d) /*
утраиваем три параметра */
{
*a=(*a)+(*a)+(*a);
114
*b=(*b)+(*b)+(*b);
*d=(*d)+(*d)+(*d);
return 0;
}
При этом вызов данной функции должен осуществляться, как показано
ниже, с использованием операции
&
для взятия адреса переменной:
int a=1,b=2,d=3;
utr3(&a,&b,&d);
Указатели в качестве аргументов обычно используются в функциях,
которые должны возвращать более одного значения.
В языке Си массив передается с помощью ссылки на первый элемент
массива в памяти. В связи с этим следующие записи эквивалентны:
int a[]
и int *a (при записи аргументов функции);
char a[][], char* a[]
и char **a;
a[5]
и *(a+5);
Достарыңызбен бөлісу: |