- •Министерство образования Республики Беларусь
- •1. Что такое программа на языке программирования
- •2. Общее знакомство с языком с
- •3. Структура простой программы на языке с
- •4. Что такое программа на языке с
- •5. Представление информации и типы данных в языке с
- •6. Константы
- •7. Переменные
- •8. Элементарный вВод и вывод информации
- •9. Выражения и операции
- •9.1. Арифметические операции
- •9.2. Операция изменения знака
- •9.3. Операции инкремента и декремента
- •9.4. Операция присваивания
- •9.6. Поразрядные логические операции
- •9.8. Логические операции и операции отношения
- •9.9. Условная операция «? :»
- •9.10. Операция последовательного вычисления
- •9.11. Операция определения требуемой памяти в байтах sizeof
- •9.12. Операция приведения типа (type)
- •10. Операторы управления вычислительным процессом
- •10.1. Операторы ветвления if и else
- •10.2. Оператор switch
- •10.3. Оператор цикла while
- •10.4. Оператор цикла do…while
- •10.5. Оператор цикла for
- •10.6. Бесконечные циклы
- •10.7. Другие управляющие средства языка с
- •10.8. Стандартные математические функции
- •11. Вычисление выражений и побочные эффекты
- •11.1. Преобразования типов при вычислении выражений
- •11.2. Побочные эффекты при вычислении выражений
- •12. Массивы
- •12.1. Описание массива
- •12.2. Инициализация массива
- •12.3. Ввод-вывод массива
- •12.4. Двумерные массивы (массивы массивов)
- •13. Указатели
- •14. Адресная арифметика
- •15. Массивы и указатели
- •15.1. Указатели и одномерные массивы
- •15.2. Указатели и двумерные массивы
- •16. Строки
- •17. Массивы строк
- •18. Функции
- •18.1. Определение функции в языке с
- •18.2. Возвращение значений из функции
- •18.3. Формальные и фактические параметры функции
- •18.4. Вызов функции
- •18.5. Объявление и определение функции: прототип функции
- •19. Передача параметров в функции
- •19.1. Способы передачи параметров в функции
- •19.2. Передача параметров в функции в языке с
- •19.3. Передача указателей в функции
- •20. Классы хранения и видимость переменных
- •20.1. Общие положения
- •20.2. Спецификаторы класса памяти
- •20.3. Область видимости функций
- •20.4. Глобальные переменные
- •20.5. Глобальные статические переменные
- •20.6. Локальные переменные
- •20.7. Статические локальные переменные
- •20.8. Регистровые переменные
- •20.9. Выводы
- •21. Организация памяти программы
- •22. Многофайловая компиляция (проекты)
- •23. Передача в функции массивОв
- •23.1. Передача одномерных массивов в функции
- •23.2. Передача двумерных массивов в функции
- •23.3. Передача в функции символьных строк
- •23.4. Возвращение указателей из функций
- •24. Функции с переменным количеством аргументов
- •24.1. Соглашения о вызовах: модификаторы функций
- •24.2. Объявление списка параметров переменной длины
- •25. Передача параметров в функцию main()
- •26. Указатели на функцию
- •27. Стандартные функцИи языка с
- •27.1. Функции для работы со строками
- •27.2. Функции для проверки символов и преобразования данных
- •27.3. Функция быстрой сортировки – gsort()
- •27.4. Функция двоичного поиска – bsearch()
- •28. Работа с файлами
- •28.1. Основные понятия
- •28.2. Основные функции для работы с файлами
- •28.3. Открытие и закрытие файлов
- •28.4. Ввод/вывод символов
- •28.5. Ввод/вывод строк
- •28.6. Форматированный ввод/вывод
- •28.7. Ввод/вывод блоков данных
- •28.8. Другие средства для работы с файлами
- •28.9. Ввод/вывод низкого уровня (префиксный доступ к файлам)
- •29. Типы, определяемые пользователем: Перечисления, структуры и объединения
- •29.1. Переименование типов – оператор typedef
- •29.2. Перечисления (enum)
- •29.3. Основные сведения о структурах
- •29.4. Структурные переменные в памяти компьютера
- •29.5. Доступ к полям структуры
- •29.6. Массивы структур
- •29.7. Структуры и функции
- •29.8. Объединения (union)
- •30. Динамическая память
- •30.1. Понятие динамического объекта
- •30.2 Создание и уничтожение динамических объектов
- •30.3 Динамическое размещение одномерных массивов и строк
- •30.4 Динамическое размещение двумерных массивов
- •30.5. Функции для работы с блоками памяти
- •31. Динамические структуры данных
- •31.1. Понятие структуры данных
- •31.2. Структуры, ссылающиеся на себя
- •31.3. Связанные списки
- •31.5. Очереди
- •Ниже приводятся примеры функций для очереди (структура элемента очереди совпадает со структурой элемента стека в примере выше):
- •32. Препроцессор языка с
- •32.1 Директива включения файлов
- •32.2. Директива определения макрокоманд (макросов)
- •32.3 Директива условной компиляции
- •32.4 Дополнительные директивы препроцессора
28.8. Другие средства для работы с файлами
Функция feof(). Данная функция (на самом деле это макрос) позволяет определить, достигнут ли конец файла. Прототип функции:
int feof(FILE *fp)
Функция feof() возвращает ненулевое значение, если при последней операции ввода из файла был обнаружен конец файла, и 0 в противном случае. Можно использовать как для двоичных, так и для текстовых файлов.
Задача. Ввести из файла неопределенной количество чисел типа long.
void main(void) {
FILE *fp;
long t;
if((fp=fopen("in", "r")) == NULL) {
printf("Ошибка открытия файла\n"); return;
}
fscanf(fp, "%ld", &t);
while (!feof(fp)) {
printf("%ld\n", t);
fscanf(fp, "%ld", &t);
}
fclose(fp);
}
Обратить внимание! Функция feof() возвращает ненулевое значение, только если была попытка чтения чего-либо после конца файла. Поэтому код ниже является ошибочным (последнее введенное из файла число на экране будет отображено дважды).
while (!feof(fp)) {
fscanf(fp, "%ld", &t);
printf("%ld\n", t);
}
Функции fflush() и flushall(). Данные функции применяются для флэширования потоков (одного конкретного потока или всех открытых потоков). Прототипы функций:
int fflush(FILE *fp);
int flushall();
Если заданный поток fp открыт для вывода, то функция fflush() записывает все данные, находящиеся в буфере, в соответствующий файл Если поток открыт для ввода, то функция fflush() очищает содержимое буфера (следующая операция чтения считывает новые данные из входного файла в буфер). После вызова функции поток остается открытым. После своего успешного выполнения функция fflush() возвращает нуль, в противном случае – EOF.
Функция flushall() выполняет действия, аналогичные fflush(), только не для одного конкретного потока, а для всех открытых потоков. Функция возвращает количество открытых потоков (входных и выходных). В случае ошибки возвращаемого значения нет.
Буферы автоматически обновляются, когда они полны, когда потоки закрываются или происходит нормальное завершение работы программы без закрытия потоков.
Произвольный доступ к файлам. Ввод/вывод обычно бывает последовательным, т. е. каждая новая операция чтения/записи имеет дело с позицией файла, следующей за той, что была в предыдущей операции чтения/записи. Другими словами, при последовательном доступе файл читается или пишется последовательно байт за байтом. Операции ввода/вывода начинаются с текущей позиции в файле. Указатель чтения/записи в файле изменяется после каждой операции чтения или записи. Например, при чтении символа из файла указатель продвигается на 1 байт, так что следующая операция начнется с первого несчитанного символа. Для того, чтобы получить доступ к байту с номером К, необходимо просмотреть (прочитать или записать) от начала файла К-1 предшествующих байтов. После обращения к байту с номером К можно обращаться к байту с номером К+1. Если файл открыт для добавления, указатель файла автоматически устанавливается на конец файла перед каждой операцией записи.
Последовательный доступ не всегда удобен. В ряде случаев бывает необходимо обеспечить произвольный (прямой) доступ к файлу. Прямой доступ означает возможность заранее определить в файле блок, к которому будет применена операция ввода/вывода. Т.е. для произвольного доступа необходимо наличие средств позиционирования внутри файла.
Файлы произвольного доступа очень распространены в реальной работе, т.к. в них можно легко добавлять, удалять записи, не перезаписывая остальные данные. Это очень удобно, так как иногда приходится изменять одну и ту же запись много раз.
При последовательном доступе данные в файле обычно имеют разную длину. При произвольном доступе очень желательно, чтобы данные имели определенную длину, что позволяет быстро и легко найти нужную нам запись. Произвольный доступ к файлу с данными различной длины значительно усложняет программу.
Обычно прямой доступ используют для файлов, открытых в двоичном режиме. Причина тут простая – так как в текстовом режиме могут выполняться преобразования символов, то может и не быть прямого соответствия между тем, что находится в файле и тем байтом, к которому нужен доступ. Даже если в файле находится один только текст, все равно этот файл при необходимости можно открыть и в двоичном режиме. Никакие ограничения, связанные с тем, что файлы содержат текст, к операциям прямого доступа не относятся. Эти ограничения относятся только к файлам, открытым в текстовом режиме.
Место в файле, куда ведется запись или откуда осуществляется считывание, определяется значением указателя чтения/записи. Стандартная библиотека языка С содержит функции для установки этого указателя в нужное место, что позволяет получить доступ к любому байту в файле.
Функция rewind(). Данная функция устанавливает указатель текущей позиции в файле на начало файла. Прототип функции:
void rewind(FILE *fp);
Функция fseek(). Данная функция предоставляет способ передвигаться по файлу, не читая и не записывая данные, т.е. устанавливает указатель текущей позиции в файле. Функция fseek() позволяет нам обрабатывать файл подобно массиву. Прототип функции:
int fseek(FILE *fp, long offset, int from_where);
Параметр offset определяет, как далеко следует передвинуться от начальной точки, заданной параметром from_where. Он должен иметь значение типа long, которое может быть положительным (движение вперед) или отрицательным (движение назад). Параметр from_where определяет, откуда отсчитывать смещение offset: значение SEEK_SET – от начала файла; SEEK_CUR – от текущей позиции указателя чтения/записи в файле; SEEK_END – от конца файла. Функция вернет 0, если указатель успешно перемещен, в противном случае – вернет ненулевую величину (-1).
Функция ftell(). Данная функция возвращает текущее положений указателя чтения/записи в файле. Прототип функции:
long ftell(FILE *fp);
Позиция указателя чтения/записи отсчитывается от начала файла, начиная с 0. В случае ошибки функция вернет -1.
Значение, возвращаемое fteel(), физически не отражает байтового смещения offset для файла, открытого в текстовом режиме, т.к. текстовый режим преобразует комбинации символов. Для текстового режима надо использовать функцию ftell() с параметром offset=SEEK_SET совместно с fseek(), чтобы корректно запомнить и восстановить месторасположения указателя в файле.