Новосибирский Государственный Университет
Опубликован: 26.08.2005 | Доступ: свободный | Студентов: 19045 / 3448 | Оценка: 4.07 / 3.55 | Длительность: 13:11:00
ISBN: 978-5-9556-0057-4
Лекция 15:

Библиотека языка Си и файлы ввода-вывода

< Лекция 14 || Лекция 15: 1234 || Лекция 16 >

Функция fseek( )

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

Покажем на примере работу fseek( ):

/* использование fseek( ) для печати содержимого файла */
#include <stdio.h>
int main(int number, char *names[]) 
{
	FILE *fp; long set = 0L;
	if(number<2)
	puts("Введите имя файла в качестве аргумента.");
	else {
	if ((fp=fopen(names[1],"r")) == 0)
	printf("Нельзя открыть %s\n",names[1]);
	else {
		while(fseek(fp, set++,0) ==0)
		putchar(getc(fp));
		fclose(fp);
		}
	}
}

Первый из трех аргументов функции fseek( ) является указателем типа FILE на файл, в котором ведется поиск. Файл следует открыть, используя функцию fopen( ). Второй аргумент " set " . Этот аргумент сообщает, как далеко следует передвинуться от начальной точки (см. ниже). Он должен иметь значение типа long, которое может быть положительным (движение вперед) или отрицательным (движение назад). Третий аргумент является кодом, определяющим начальную точку.

Функция fseek( ) возвращает 0, если все хорошо, и -1, если есть ошибка. Поскольку переменная set инициализирована нулем, при первом прохождении через цикл

while(fseek(fp,set++,0)==0)
putchar(getc(fp));

мы имеем выражение

fseek(fp,OL,0);

означающее, что мы идем в файл, на который ссылается указатель fp, и находим байт, отстоящий на 0 байт от начала, т.е. первый байт. Затем функция putchar( ) печатает содержимое этого байта. При следующем прохождении через цикл переменная set увеличивается до 1L, и печатается следующий байт. То есть, переменная set действует подобно индексу для элементов файла. Процесс продолжается до тех пор, пока set не попытается попасть в fseek( ) после конца файла. В этом случае fseek( ) возвращает значение -1 и цикл прекращается.

Распределение памяти

Функция malloc( )

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

char str[ ] = "Символьная строка";

Будет выделена память, достаточная для запоминания этой строки. Мы можем запросить определенный объем памяти:

int mas[150];

Это описание выделяет 150 ячеек памяти, каждая из которых предназначена для запоминания целого значения. Но язык Си позволяет нам распределять дополнительную память во время работы программы. Предположим, мы пишем программу и не знаем, сколько данных нам придется вводить. Тогда можно выделить нужный нам, по нашему предположению, объем памяти, а затем, если понадобится, потребовать еще. Чтобы сделать это, нужно использовать функцию malloc( ). И без указателей тут не обойтись!

/* добавляем память, если необходимо */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STOP "\n" /* сигнал прекращения ввода */
#define BLOCK 100 /*байты памяти */
#define LIM 40 /*предельная длина вводимой строки*/
#define MAX 50 /*максимальное число вводимых строк */
#define TIME 20000 /* большая задержка времени */
main ( )
{
	char store[BLOCK]; /* исходный блок памяти*/
	char symph[LIM]; /* приемник вводимых строк*/
	char *end; /* указывает на конец памяти */
	char *starts[MAX]; /* указывает на начала строк*/
	int index = 0; /*количество вводимых строк */
	int count; /* счетчик*/
	char malloc( ); /* распределитель памяти */
	starts[0]=store;
	end=starts[0]+BLOCK-1;
	puts("Вводите строки по одной");
	puts("для завершения ввода в начале строки нажимите клавишу [ввод]");
	puts("Начинайте!.");
	while(index<MAX) {
		if(fgets(symph,LIM,stdin))
			if (strcmp(fgets(symph,LIM,stdin),STOP) == 0)
		break;
		if(strlen(symph)>end - starts[index]) {
			/* действия при недостатке памяти для 
			запоминания вводимых данных*/
		puts("подождите, программа попробует найти дополнительную память");
			starts[index]=malloc(BLOCK);
			end=starts[index]+BLOCK- 1;
			for(count=0; count<TIME; count++);
			puts("память найдена");
		}
		strcpy(starts[index],symph);
		starts[index+1]=starts[index] + strlen(symph)+1;
		if(++index<MAX)
		printf("Строка: %d. продолжайте.\n", index);
	}
	puts("Вывод программы");
	for(count=0; count<index; count++)
	puts(starts[count]);
}

Давайте посмотрим, что делает функция malloc( ). Она берет аргумент в виде целого без знака, которое представляет количество требуемых байтов памяти. Так, malloc(BLOCK) требует 100 байт. Функция возвращает указатель на тип char в начало нового блока памяти. Мы использовали описание

char *malloc( );

чтобы предупредить компилятор, что malloc( ) возвращает указатель на тип char. Поэтому мы присвоили значение этого указателя элементу массива starts[index] при помощи оператора

starts[index]=malloc(BLOCK);

Предположим, что мы хотим работать с памятью типа int, а не char. Mожете и здесь использовать malloc( ). Вот как это делается:

char malloc( ); 
/* по-прежнему описываем как указатель на char */
int *newmem; newmem = (int *)malloc(100); 
/* используем операцию приведения типа */

Снова требуется 100 байт. Операция приведения типа преобразует значение, возвращенное указателем на тип char, в указатель на тип int. Если в системе int. занимает два байта памяти, это значит, что 100 байт можно использовать для запоминания 50 целых чисел.

Функция calloc( )

Другую возможность распределения памяти дает нам применение функции calloc( ).

char *calloc( ); long *newmem;
newmem=(long *) calloc(100,sizeof(long));

Функция calloc( ) возвращает указатель на char. Нужно использовать оператор приведения типа, если вы хотите запомнить другой тип. calloc( ) имеет два аргумента, и оба они должны быть целыми без знака. Первый аргумент содержит количество требуемых ячеек памяти. Второй аргумент - размер каждой ячейки в байтах. Функция calloc( ) обнуляет содержимое всего блока. Ваша библиотека языка Си возможно представляет несколько других функций управления памятью, вы можете исследовать их самостоятельно!

< Лекция 14 || Лекция 15: 1234 || Лекция 16 >
Иван Руднев
Иван Руднев
Фраза "Структурная переменная описывается с помощью переменной структурного типа" на мой Взгляд является тафтология. Из нее сложно понять суть утверждения. Хотелось бы полке понятного описания.
Руслан Поддубный
Руслан Поддубный

"

printf("Добро пожаловать!\n");  - на консоль выводится непонятный набор знаков вместо русского текста.