Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

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

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

Ответ
 
Опции темы
Старый 27.01.2013, 20:20   #1
NinjaNoob
Пользователь
 
Регистрация: 02.10.2012
Сообщений: 40
Репутация: 10
По умолчанию 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
Адрес: Мурманск
Сообщений: 913
Репутация: 132
По умолчанию

Очень смущает вот это
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
Репутация: 10
По умолчанию

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

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

skype: Perchik71
По умолчанию

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

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
Адрес: Мурманск
Сообщений: 913
Репутация: 132
По умолчанию

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

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
Адрес: Мурманск
Сообщений: 913
Репутация: 132
По умолчанию

Код:

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
Репутация: 10
По умолчанию

Если кому интересно, решилось вот так:
Код:

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 вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

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


18:19.


Powered by vBulletin® Version 3.8.8 Beta 2
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.

RusProfile.ru


Справочник российских юридических лиц и организаций.
Проекты отопления, пеллетные котлы, бойлеры, радиаторы
интернет магазин respective.ru