Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 27.01.2013, 20:20   #1
NinjaNoob
Пользователь
 
Регистрация: 02.10.2012
Сообщений: 40
По умолчанию c++ получение информации из файла

Читаю информацию из файла следующей функцией:
Код:
void ReadFile(Element **Top) {
	Element *Current,*Tail; //указатели
	FILE *datafile; //файлы
	system("CLS");
	*Top=Tail=NULL; //обнуление ссылок на хвост и вершину
	datafile=fopen("data.txt","r"); //открытие файла Base.txt

	if(datafile==NULL) printf("Файл не может быть прочитан.");//если файлов нет
	else {
		while(!feof(datafile)) {
			Current=(Element*)malloc(sizeof(Element)); //выделение памяти под новый элемент (далее текущий)
			Current->NEXT=NULL; //обнуление указателя на следующий элемент текущего элемента
			Current->PREV=Tail; //присваивание указателя на предыдущий элемент текущего элемента хвосту списка
			if((*Top)==NULL) (*Top)=Current; //если указатель на начало списка пуст, то указателем на начало списка становится текущий элемент
			else Tail->NEXT=Current; //если нет, то указателем на хвост списка становится текущий элемент
			Tail=Current; //указатель на хвост становится приравнивается текущему элементу
			fread(&Current->inf,sizeof(Element),1,datafile);
		}
		fcloseall(); //закрываем файлы
		printf("Списки успешно загружены из файлов!");
	}
getch();
}
При попытке вывода содержимого файла вижу следующее:
dsfb.jpg

Функция вывода:
Код:
void PrintList(Element *Current) {
	system("CLS");
	printf("Текущий список:\n");
	if(Current==NULL) printf("Список пуст или не существует.");
	else {
		while(Current!=NULL) {					
			printf("id:%d\n",Current->inf.id);
			printf("ФИО:%s %s %s\n",Current->inf.surname,Current->inf.name,Current->inf.secondname);
			printf("Факультет: %s\t",Current->inf.faculty);
			printf("Специальность: %s\t",Current->inf.specialty);
			printf("Курс: %d\n",Current->inf.course);
			printf("Средний балл: %d\n\n\n",Current->inf.mid_ball);
			
			Current=Current->NEXT; //переход к следующему элементу
		}
	}
getch();
}
Сама структура:
Код:
typedef struct StudentInfo //создание нового типа запись для хранения информационных полей элемента списка
{
	int id; 
	char surname[20]; //
	char name[20]; //
	char secondname[20];
	int year; //
	char faculty[10];
	char specialty[10];
	int course;
	int mid_ball;

} Student; //имя созданного типа

typedef struct List //создание нового типа запись для хранения информации элемента списка
{
Student inf; //информационные поля
struct List* NEXT; //указатель на следующий элемент списка
struct List* PREV; //указатель на предыдущий элемент списка
} Element; //имя созданного нового типа

Последний раз редактировалось NinjaNoob; 27.01.2013 в 21:12.
NinjaNoob вне форума Ответить с цитированием
Старый 27.01.2013, 20:33   #2
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Очень смущает вот это
fread(&Current->inf,sizeof(Element),1,datafile);
&Current->inf Это адрес структуры Student.
Длина записи sizeof(Element) превышает длину структуры Student.
Тем самым затираются поля NEXT, PREV которым до этого были присвоены значения
Current->NEXT=NULL;
Current->PREV=Tail;
EUGY вне форума Ответить с цитированием
Старый 27.01.2013, 21:14   #3
NinjaNoob
Пользователь
 
Регистрация: 02.10.2012
Сообщений: 40
По умолчанию

Вместо sizeof(Element) написал sizeof(Student) - ничего не изменилось. Или я вас не правильно понял
NinjaNoob вне форума Ответить с цитированием
Старый 27.01.2013, 21:35   #4
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
Вместо sizeof(Element) написал sizeof(Student) - ничего не изменилось. Или я вас не правильно понял
Поняли правильно.
Едем дальше.
Нужно проверять возвращаемое значение fread. Если оно меньше, чем количество запрашиваемых из файла структур (в вашем случае меньше единицы), то чтение Current некорректно. Значит этот элемент не следует добавлять в список.
EUGY вне форума Ответить с цитированием
Старый 27.01.2013, 21:52   #5
Perchik71
С++, Delphi
Форумчанин
 
Аватар для Perchik71
 
Регистрация: 24.11.2012
Сообщений: 495
По умолчанию

Поступите просто.... последняя запись обычно всегда при fread неверна... точнеее её не существует. делайте count - 1.
Если помог, тут весы есть , Вам не сложно, а мне приятно.
Perchik71 вне форума Ответить с цитированием
Старый 27.01.2013, 22:05   #6
NinjaNoob
Пользователь
 
Регистрация: 02.10.2012
Сообщений: 40
По умолчанию

EUGY, я не совсем понял как проверить условие. Делал вот так:
Код:
while(!feof(datafile)) {
			Current=(Element*)malloc(sizeof(Element)); //выделение памяти под новый элемент (далее текущий)
			Current->NEXT=NULL; //обнуление указателя на следующий элемент текущего элемента
			Current->PREV=Tail; //присваивание указателя на предыдущий элемент текущего элемента хвосту списка
			if((*Top)==NULL) (*Top)=Current; //если указатель на начало списка пуст, то указателем на начало списка становится текущий элемент
			else Tail->NEXT=Current; //если нет, то указателем на хвост списка становится текущий элемент
			Tail=Current; //указатель на хвост становится приравнивается текущему элементу
			if(fread(&Current->inf,sizeof(Student),1,datafile)<1) {fcloseall();}
			
		}
Perchik71
То есть посчитать количество записей, отнять от этого количества единицу. И в цикле for читать нужное количество записей?
Я попытался вот так, но выкидывает на цикле while.
Код:
while(fread(&Current->inf,sizeof(Student),1,datafile)) 
{g++;}
		g-=1;
		for (int i=0; i<g; i++)
		{
			Current=(Element*)malloc(sizeof(Element)); //выделение памяти под новый элемент (далее текущий)
			Current->NEXT=NULL; //обнуление указателя на следующий элемент текущего элемента
			Current->PREV=Tail; //присваивание указателя на предыдущий элемент текущего элемента хвосту списка
			if((*Top)==NULL) (*Top)=Current; //если указатель на начало списка пуст, то указателем на начало списка становится текущий элемент
			else Tail->NEXT=Current; //если нет, то указателем на хвост списка становится текущий элемент
			Tail=Current; //указатель на хвост становится приравнивается текущему элементу
			fread(&Current->inf,sizeof(Student),1,datafile);
		}
NinjaNoob вне форума Ответить с цитированием
Старый 27.01.2013, 22:09   #7
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Цитата:
последняя запись обычно всегда при fread неверна...
Perchik71, неизвестно как у ТС еще запись в файл идет, может там такое, что еще на десяток мусорных структур наберется. Если у него было чтение полной структуры Element с кривыми NEXT PREV, то и запись может также идти.
EUGY вне форума Ответить с цитированием
Старый 27.01.2013, 22:13   #8
NinjaNoob
Пользователь
 
Регистрация: 02.10.2012
Сообщений: 40
По умолчанию

EUGY, запись в файл
Код:
void Filing(Element *Current) {
	FILE *datafile; //файлы
	datafile=fopen("data.txt","wb"); //файл для первого списка

	if (datafile==NULL) printf("Файл не может быть прочитан.");
	else {
		while(Current!=NULL) {
			fwrite(&Current->inf,sizeof(Student),1,datafile); //запись данных текущего элемента в файл
			Current=Current->NEXT; //переход к следующему элементу

		}
	printf("Запись произошла успешно");
	fcloseall(); //закрытие файлов
	}
getch();
}
NinjaNoob вне форума Ответить с цитированием
Старый 27.01.2013, 22:14   #9
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Код:
if  ( 0== fread(&Current->inf,sizeof(Student),1,datafile) )
{
(*Top)= ??;
// лень вникать, но вообщем восстановить предыдущее состояние
free (Current);
}

Последний раз редактировалось EUGY; 27.01.2013 в 22:19.
EUGY вне форума Ответить с цитированием
Старый 27.01.2013, 23:52   #10
NinjaNoob
Пользователь
 
Регистрация: 02.10.2012
Сообщений: 40
По умолчанию

Если кому интересно, решилось вот так:
Код:
long len,n,m=sizeof(Student);
	if(datafile==NULL) printf("Файл не может быть прочитан.");//если файлов нет
	else {
		fseek(datafile, 0, SEEK_END);
		len = ftell(datafile);
		n = len/m; // количество записей в файле
		fseek(datafile,0,SEEK_SET);
		for (int i=0; i<n; i++) {
			Current=(Element*)malloc(sizeof(Element)); //выделение памяти под новый элемент (далее текущий)
			Current->NEXT=NULL; //обнуление указателя на следующий элемент текущего элемента
			Current->PREV=Tail; //присваивание указателя на предыдущий элемент текущего элемента хвосту списка
			if((*Top)==NULL) {
				(*Top)=Current;
			} else {
				Tail->NEXT=Current;
			} //если нет, то указателем на хвост списка становится текущий элемент
			Tail=Current; //указатель на хвост становится приравнивается текущему элементу
			fread(&Current->inf,sizeof(Student),1,datafile);
		}
NinjaNoob вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Получение информации из памяти 9esa Помощь студентам 3 26.03.2012 02:12
Получение информации о принтере mutabor Общие вопросы Delphi 4 17.05.2011 16:37
Получение информации о железе FalseMaster Win Api 2 25.11.2009 06:05
Получение информации из мр3 GAGARIN-NEW Мультимедиа в Delphi 2 24.03.2008 15:19
Получение информации о классе Sibedir Общие вопросы Delphi 7 07.12.2007 14:37