Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

Файл. Функции чтения-записи

Файл может читаться посимвольно, построчно, с форматными преобразованиями или поблочно.

Когда аргументом функции является указатель на FILE, этот указатель в описании функции называют потоком.

Объявления прототипов функций чтения-записи находятся в файле заголовков stdio.h, поэтому программы, использующие эти функции, должны включать следующую директиву препроцессора:

#include <stdio.h>

EOF — признак конца файла определен в файле заголовков stdio.h. Значение EOF зависит от компилятора (типичным значением для ОС UNIX является –1). Значение EOF может быть введено с клавиатуры путем нажатия клавиш <CTRL>, <D> в начале строки.

Описания функций чтения-записи

int fgetc(FILE *stream)

Функция возвращает следующий символ из потока в формате int или EOF, если исчерпан файл или обнаружена ошибка.

int fputc(int c, FILE *stream)

Функция пишет символ, переведенный в формат unsigned char в поток, возвращает переданный символ или EOF в случае ошибки.

int ungetc(int c, FILE *stream)

Функция отправляет символ, переведенный в формат unsigned char, обратно в поток. При следующем чтении из потока он будет получен снова. Для каждого потока вернуть можно не более одного символа. Нельзя возвращать EOF. Функция возвращает переданный символ или EOF в случае ошибки.

char *fgets(char *s, int n, FILE *stream)

Функция читает не более n-1 символов в массив s, прекращая чтение, если встретился символ новой строки, который включается в массив, кроме того, записывается символ '\0'. Функция возвращает адрес массива s или NULL, если исчерпан файл или обнаружена ошибка.

int fputs(char *s, FILE *stream)

Функция пишет строку s, которая может не иметь символ '\n', в поток, возвращает неотрицательное целое или EOF в случае ошибки.

int fscanf(FILE *stream, const char *format,... /*аргументы*/)

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

int fprintf(FILE *stream, const char *format,... /*аргументы*/)

Функция преобразует и пишет вывод в поток под управлением формата. Возвращаемое значение — число записанных символов или, в случае ошибки, отрицательное значение. Правила построения форматной строки такие же, как для функции printf().

int fread (void *ptr, size_t size, size_t nitems, FILE *stream)

Функция читает из потока в массив ptr не более nitems объектов размера size. Функция возвращает количество прочитанных объектов, которое может быть меньше заявленного. Для определения состояния после чтения следует использовать функции обработки ошибок feof() и ferror().

int fwrite (const void *ptr, size_t size, size_t nitems, FILE *stream)

Функция пишет из массива ptr в поток nitems объектов размера size. Функция возвращает количество записанных объектов, которое в случае ошибки меньше nitems.

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

Пример 1

Копирование файла посимвольно

while((c=fget

  • Произвольный доступ к файлу.

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

Объявление прототипа функции fseek():

int fseek(FILE *stream, long offset, int ptrname)

Это объявление находится в файле заголовков stdio.h, поэтому программы, использующие эту функцию, должны включать следующую директиву препроцессора:

#include <stdio.h>

Функция fseek() — стандартная функция языка Си, устанавливает позицию в потоке stream для следующей операции чтения-записи на расстоянии offset байтов от позиции ptrname, принимающей следующие значения:

0 — начало

1 — текущая позиция

2 — конец

Функция fseek() возвращает ненулевое значение для недопустимых установок, 0 в противном случае.

  • Виртуальная память пользователя. Функции управления динамической памятью.

Текстовый сегмент – это просто выполняемый код, то есть машинный код программы.

Сегмент данных используется для хранения внешних (external) и статических (static) переменных. Он содержит инициализированные и неинициализированные данные. Неинициализированные данные автоматически устанавливаются равными нулю при входе в программу. Адрес внешней памяти etext обозначает конец текстового сегмента. Конец инициализированных и неинициализированных данных обозначен адресом внешних переменных edata и end, соответственно. Переменные etext, edata и end – целые.

Первоначально, граница выделяемой памяти программы – это адрес end. Граница выделяемой памяти может изменяться при вызове системных вызовов или библиотечных функций управления памятью. Однако адреса трех переменных etext, edata и end неизмены.

Стек программы используется для хранения аргументов функции и ее локальных (automatic) переменных. Стек также используется для сохранения регистров при вызове функции. Расположение вершины стека труднодоступно.

Любая попытка исправить память между концом данных и вершиной стека может привести к порче памяти. Также недоступна память расположенная ниже конца стека.

Можно изменить размер сегмента данных с помощью системных вызовов brk и sbrk, изменяя границы выделяемой области.

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

Функции управления динамической памятью дают возможность легко управлять памятью.

Они являются функциями библиотеки общего назначения.

Объявления этих функций находится в заголовочном файле <stdlib.h>. поэтому в программах, использующих эти функции, необходимо включать следующую директиву препроцессора:

#include <stdlib.h>

Выделение памяти

void * malloc(size_t size)

Функция выделяет память размером size и возвращает адрес начала области памяти. При присвоении указателю происходит явное преобразование типа. Выравнивание границы происходит автоматически, но выделенная память не инициируется нулями.

void realloc (void *block, size_t size)

Функция делает размер блока по указателю block равным size байтов и возвращает указатель на блок, возможно перемещенный. В случае перемещения блока данные из исходного блока копируются в новый блок, освобождая исходный блок.

void * сalloc(size_t nelem, size_t elsize)

Функция выделяет блок, который вмещает nelem элементов размером elsize байтов каждый, возвращает адрес начала области памяти. Выделенная память инициируется нулями.

У каждого блока памяти есть байты, где хранятся длина блока и признак того, занят он или свободен. Эти функции управления памятью используют системные вызовы brk и sbrk. Когда функциям malloc, сalloc и realloc нужно изменить границу выделяемой памяти, они обычно делают это с запасом. Если будущим запросам хватает выделенного пространства, они не используют системный вызов. Так библиотечные функции минимизируют число выполнения системных вызовов.

Если вызов функции закончился неуспешно, то она возвращает значение NULL.

Освобождение памяти

void free(void *block)

Функция освобождает блок памяти по указателю *block и делает его доступным для последующих выделений памяти. Указатель должен указывать на блок, полученный ранее вызовом malloc, calloc или realloc.

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

  • Динамические структуры данных.

 

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

Линейная динамическая структура - изменяемая последовательность элементов. Примеры таких структур:

стек (элемент можно добавлять только в конец; удаляется только последний элемент);

очередь (элемент можно добавлять только в конец; удаляется только первый элемент);

дек (добавление и удаление элементов и с начала, и с конца).

Дерево - структура, в которой каждый элемент (вершина) ссылается на один или более элементов следующего уровня.

В сетевой структуре никаких ограничений на связи не накладывается.

Линейные динамические структуры, такие как стеки, очереди и деки, при известном количестве элементов в них можно реализовать в виде динамических или статических одномерных массивов. В противном случае используют списки.

Список - это структура, в которой помимо данных хранятся также адреса элементов. Элемент списка состоит из двух частей: информационной и адресной, где хранятся указатели на следующие элементы. В зависимости от количества полей в адресной части и порядка связывания элементов различают:

линейные односвязные списки - единственное адресное поле содержит адрес следующего элемента, для последнего элемента списка этот адрес равен нулю (NULL),

кольцевые односвязные списки - единственное адресное поле содержит адрес следующего элемента, последний элемент ссылается на первый,

линейные двусвязные списки - каждый элемент содержит адреса предыдущего и последующего элемента; первый элемент в качестве адреса предыдущего элемента, а последний элемент в качестве адреса последующего элемента содержат нули (NULL),

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

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

Для описания элементов списка используют в программах на языке Си структуры.

 

  • Форматы данных.

Целые числа

Целые числа могут занимать байт, слово или двойное слово. Они могут быть знаковыми и беззнаковыми. В знаковых целых самый старший бит байта, слова или двойного слова, занимаемого числом, отводится для индикации знака числа. Нуль соответствует плюсу, 1 — минусу. Таким образом, возможный диапазон представляемых значений для знаковых целых составляет: от –128 до +127 для байтовых величин, от –32768 до +32767 для слов, от –231 до 231-1 для двойных слов. Беззнаковые целые могут принимать значения: от 0 до 255 для байтовых величин, от 0 до 65535 для слов, от 0 до 232-1 для двойных слов.

 

Двоично-десятичные целые числа

Двоично-десятичные целые — это набор четырехбитовых беззнаковых величин, каждая из которых может принимать значения от 0 до 9. Двоично-десятичные числа могут быть в обычном или упакованном формате. Обычный формат использует только младшие четыре бита байта, в этом формате каждая цифра представляется одним байтом так же, как и целочисленные беззнаковые значения от 0 до 9. Упакованный формат предусматривает использование старших четырех бит байта для представления более старшей значащей цифры десятичного числа, т.е. в упакованном формате требуется в два раза меньше байт для представления десятичных чисел одинаковой разрядности.

 

Битовые поля

Битовые поля — это непрерывные последовательности битов, которые могут располагаться в любом месте памяти и начинаться с любого бита любого байта по любому адресу. Началом битового поля считается самый младший используемый бит самого младшего байта. Битовые поля могут иметь длину до 32 бит.

 

Строки

Строки — это непрерывные последовательности битов, байтов, слов или двойных слов в памяти. Битовые строки могут располагаться в любом месте памяти и начинаться с любого бита любого байта по любому алресу. Максимальная длина битовых строк 232-1 бит. Строки байт, слов и двойных слов могут занимать до 232-1 байт (4 Гб).

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...