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

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

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 13.04.2018, 13:26   #1
Fronzi
Пользователь
 
Регистрация: 11.03.2017
Сообщений: 23
По умолчанию Не работает функция считывания структуры из файла

Не работает функция считывания структуры из файла (fromfile()).
И второе: неоходимо по номеру введенному номеру id изменить оценки студента, но работает только с введенным последним id, в чем могут быть ошибки?
Код:
struct fig 
{
    char surn[30];
    int mark[100];
    int modulcount;         
    int id; 
};
void fCloseFile(FILE *file) 
{
    fclose(file);
}
void push(fig *&stud)
{
    
    cout<<"Введите id: "<<endl;
    cin>>stud->id;
    cout<<"Введите фамилию :"<<endl;
    cin>>stud->surn;    
    cout<<"Введите кол-во модулей: "<<endl;
    cin>>stud->modulcount;
    cout<<"Введите оценки: "<<endl;
    for(int j=0; j<stud->modulcount; j++)
    {
        cin>>stud->mark[j];     
    }       
}
void infile(FILE* file, fig *stud)
{
    push(stud);
    int sum = 0;
    cout << "id: " << stud->id << endl;
    cout << "Фамилия: " << stud->surn << endl;
    cout << "Кол-во модулей : " << stud->modulcount << endl;
    cout << "Оценки : " << endl;
    for(int j=0; j<stud->modulcount; j++)
    {
        cout<<stud->mark[j]<<" ";
        sum+=stud->mark[j];
    }
    if (sum>=60)
        cout<<"Зачет "<<endl;
    else cout<<"Незачет "<<endl;
    cout<<endl;
    fwrite(stud, sizeof(file), 1, file);
    cout << "Данные в файл записаны \n";
    fCloseFile(file);
}
 
void fromfile(char *filename)
{
    fig stud;
    FILE *file = fopen(filename,"rb");
    fread(&stud, sizeof(fig), 1, file);
    cout << "Данные из файла: "<<endl;
    cout << "id: " << stud.id << endl;
    cout << "Фамилия: " << stud.surn << endl;
    cout << "Кол-во модулей : " << stud.modulcount << endl;
    for(int j=0; j<stud.modulcount; j++)
    {
        cout<<stud.mark[j]<<" ";
    }
    fCloseFile(file);
    return;
}
FILE* fOpenFile(char *filename) {
    FILE *file;
    file = fopen(filename,"a+b");
    return file;
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    setlocale(LC_ALL, "rus");
    SetConsoleOutputCP(1251);
    SetConsoleCP(1251); 
    fig *student = new fig;
    char *fName = "myfile.txt";
    FILE *file = fOpenFile(fName);
    cout<<"Введите кол-во студентов: "<<endl;
    int num;
    int vibor;
    int p=0;
    int change;
    int newmark[100];
    cin>>num;
    for(int i=0; i<num; i++)
    {
        infile(file,student);
    }   
    fromfile(fName);
    cout<<"Редактировать оценки студента? 1-да, 0-нет "<<endl;
    cin>>vibor;
    if (vibor==0)
        cout<<"Завершение программы... "<<endl;
    else 
    {
        cout<<"Ввод id: "<<endl;
        cin>>change;
        
        for(int i=0; i<num; i++)
        {
            if (student->id==change)
            {
        cout<<"Введите оценки: "<<endl;
        for(int j=0; j<student->modulcount; j++)
        {       
            cin>>newmark[j];
            student->mark[j]=newmark[j];
            
        }       
        break;
            }
        }
        cout<<"Завершение программы... "<<endl;
    }
    _getch();
    return 0;
}
Fronzi вне форума Ответить с цитированием
Старый 13.04.2018, 14:36   #2
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Тут фундаментальный косяк есть. Структуры в памяти машины выравниваются компилятором, чтобы были оптимально быстрые. Скажем, процессор эффективно глотает по 8 байт за раз. Поэтому поля будут выровнены, чтобы быть кратными 8. Этот момент у вас никак не учитывается. Он может проявлятся, а может и нет - от многих факторов зависит. Причем, если у вас тестовый файл создан на другой машине, вероятнее всего ниче не заработает.

Вобщем смысл такой - структуру, которые должны сериализироватся в поток байт (файл) нужно специальным образом компилировать, запрещая вольности компилятору.
В GCC делатеся так
https://gcc.gnu.org/onlinedocs/gcc-3...ttributes.html
(__aligned(packed)__)
Для визуалки ищите..


Ну там еще по мелочи у вас утечки памяти, например тут

Код:
fig *student = new fig;
а
Код:
delete student;
я в упор не вижу...

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

Последний раз редактировалось alexzk; 13.04.2018 в 14:42.
alexzk вне форума Ответить с цитированием
Старый 13.04.2018, 14:42   #3
Fronzi
Пользователь
 
Регистрация: 11.03.2017
Сообщений: 23
По умолчанию

хорошо, спасибо, попробую, а что с циклом изменения оценок, не подскажете? он последнюю структуру только меняет
Fronzi вне форума Ответить с цитированием
Старый 13.04.2018, 14:47   #4
Fronzi
Пользователь
 
Регистрация: 11.03.2017
Сообщений: 23
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Ну и файл остается не закрытым, значит может не читатся при следущем запуске и т.д. Сделайте правильную очистку в конце програмы занятых ресурсов.
так у меня же в каждой функции прописано закрытие файла через close или может я неправильно их записал?
Fronzi вне форума Ответить с цитированием
Старый 13.04.2018, 14:56   #5
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Цитата:
Сообщение от Fronzi Посмотреть сообщение
так у меня же в каждой функции прописано закрытие файла через close или может я неправильно их записал?
Трудно читать тут пеленку кода...

...если вы в каждой ф. закрываете, то как будет работать 2 и 3 функции, после того, как файл закрыт 1й?)

Нет, открыли в начале проги, закрыли в конце. А функции, должны еще делать перемотку fseek, т.к. для файла запоминается позиция, и вторая ф. продолжит чтение с места, где остановилась 1я. Это не совсем то, что вы хотите вроде.
Если вы И читаете И пишите, то перемотка обязательна м-у ними. Без перемотки может быть че угодо - вплоть до радиоактивного пепла ) Перематывать можно и на 0, т.е. по факту оставить все как есть, но сам вызов перемотки нужен.

Последний раз редактировалось alexzk; 13.04.2018 в 14:59.
alexzk вне форума Ответить с цитированием
Старый 13.04.2018, 15:19   #6
Fronzi
Пользователь
 
Регистрация: 11.03.2017
Сообщений: 23
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Трудно читать тут пеленку кода...

...если вы в каждой ф. закрываете, то как будет работать 2 и 3 функции, после того, как файл закрыт 1й?)

Нет, открыли в начале проги, закрыли в конце. А функции, должны еще делать перемотку fseek, т.к. для файла запоминается позиция, и вторая ф. продолжит чтение с места, где остановилась 1я. Это не совсем то, что вы хотите вроде.
Если вы И читаете И пишите, то перемотка обязательна м-у ними. Без перемотки может быть че угодо - вплоть до радиоактивного пепла ) Перематывать можно и на 0, т.е. по факту оставить все как есть, но сам вызов перемотки нужен.
сейчас постараюсь сделать так как вы сказали, а что можно сделать со второй частью моего вопроса? у меня изменяются записи только в последней структуре, а мне нужно, чтобы изменялись записи по введенному id, уже все перепробовал, никак не выходит
Fronzi вне форума Ответить с цитированием
Старый 13.04.2018, 15:25   #7
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

Сначала разберитесь с кашей в файле

FILE *file = fopen(filename,"rb");

fopen(filename,"a+b");

Такого быть не должно. Файл открывается 1 раз, закрывается 1 раз и в м-у чтением и записью обязательно делается перемотка.
Да, и если вы хотите изменить уже записанную запись, то нужно перемотать на нее и записать занова (поверх).
alexzk вне форума Ответить с цитированием
Старый 13.04.2018, 15:37   #8
Fronzi
Пользователь
 
Регистрация: 11.03.2017
Сообщений: 23
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Файл открывается 1 раз, закрывается 1 раз и в м-у чтением и записью обязательно делается перемотка.
перемотка в начало файла?
Fronzi вне форума Ответить с цитированием
Старый 13.04.2018, 15:44   #9
Fronzi
Пользователь
 
Регистрация: 11.03.2017
Сообщений: 23
По умолчанию

Цитата:
Сообщение от alexzk Посмотреть сообщение
Сначала разберитесь с кашей в файле
Код:
struct fig 
{
	char surn[30];
	int mark[100];
	int modulcount;			
	int id;	
};
//void fCloseFile(FILE *file) 
//{
//    fclose(file);
//}
void push(fig *&stud)
{
	
	cout<<"Введите id: "<<endl;
	cin>>stud->id;
	cout<<"Введите фамилию :"<<endl;
	cin>>stud->surn;	
	cout<<"Введите кол-во модулей: "<<endl;
	cin>>stud->modulcount;
	cout<<"Введите оценки: "<<endl;
	for(int j=0; j<stud->modulcount; j++)
	{
		cin>>stud->mark[j];		
	}		
}
void infile(FILE* file, fig *stud)
{
	push(stud);
	int sum = 0;
	cout << "id: " << stud->id << endl;
    cout << "Фамилия: " << stud->surn << endl;
    cout << "Кол-во модулей : " << stud->modulcount << endl;
	cout << "Оценки:  ";
	for(int j=0; j<stud->modulcount; j++)
	{
		cout<<stud->mark[j]<<" ";
		sum+=stud->mark[j];
	}
	if (sum>=60)
		cout<<"Зачет "<<endl;
	else cout<<"Незачет "<<endl;
	cout<<endl;
    fwrite(stud, sizeof(stud), 1, file);
    cout << "Данные в файл записаны \n";
    //fCloseFile(file);
	fseek(file, 0, SEEK_CUR);
	fclose(file);
}

void fromfile(char *filename)
{
	fig stud;
	FILE *file = fopen(filename,"rb");
	fseek(file, 0, SEEK_SET);
	fread(&stud, sizeof(stud), 1, file);
	cout << "Данные из файла: "<<endl;
	cout << "id: " << stud.id << endl;
    cout << "Фамилия: " << stud.surn << endl;
    cout << "Кол-во модулей : " << stud.modulcount << endl;
	for(int j=0; j<stud.modulcount; j++)
	{
		cout<<stud.mark[j]<<" ";
	}
	fclose(file);
	//fCloseFile(file);
	return;
}
//FILE* fOpenFile(char *filename) {
//    FILE *file;
//    file = fopen(filename,"a+b");
//    return file;
//}

int _tmain(int argc, _TCHAR* argv[])
{
	setlocale(LC_ALL, "rus");
	SetConsoleOutputCP(1251);
    SetConsoleCP(1251);	
	
	fig *student = new fig;
	char *fName = "myfile.txt";
	FILE *file = fopen(fName, "a+b");
	cout<<"Введите кол-во студентов: "<<endl;
	int num;
	int vibor;	
	int p;
	int change;
	int newmark[100];
	cin>>num;
	for(int i=0; i<num; i++)
	{
		infile(file,student);
	}	
	fromfile(fName);
	cout<<"Редактировать оценки студента? 1-да, 0-нет "<<endl;
	cin>>vibor;
	if (vibor==0)
		cout<<"Завершение программы... "<<endl;
	else 
	{
		//fseek(file, 0, SEEK_CUR);		
		fseek(file, 0, SEEK_SET);
		cout<<"Ввод id: "<<endl;
		cin>>change;
		
		for(int i=0; i<num; i++)
		{
			if (student[i].id==change)
			{
				p=i;
				cout<<"Введите оценки: "<<endl;
		for(int j=0; j<student[i].modulcount; j++)
		{		
			cin>>newmark[j];
			student->mark[j]=newmark[j];
			
		}		
		break;
			}
		}
		cout<<"Завершение программы... "<<endl<<p;
	}
	fclose(file);
	delete student;
	_getch();
	return 0;
}
в каждой функции файл открывается и закрывается, в том числе и в main, также перемотки сделал в записи - на текущее положение, в чтении - на начало. вы же это имели в виду?
Fronzi вне форума Ответить с цитированием
Старый 13.04.2018, 16:08   #10
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

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

Так, теперь ошибки, вот в теле программы:
FILE *file = fopen(fName, "a+b");
Дальше срабатывает infile и делает fclose(), как теперь будет работать fromfile? Файл уже все - закрыт. Ага, и для компенсации этого факта вы его снова открываете FILE *file = fopen(filename,"rb");

Сделайте 1 fopen и 1 fclose вообще на целую программу. Ровно по 1 разу. Во всех остальных местах обойдитесь без них, использую перемотку.
alexzk вне форума Ответить с цитированием
Ответ


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

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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Считывания русского текста из файла apeorin Общие вопросы C/C++ 14 02.12.2012 16:34
Считывания массива из файла Daleaids Общие вопросы C/C++ 4 23.12.2011 15:41
Процедура считывания из файла Black_butterfly Помощь студентам 0 29.05.2011 16:51
Возникла проблема считывания текстового файла Aerial Общие вопросы C/C++ 2 20.09.2010 10:29
потоки сохранение и считывания файла [C++] ArniLand Общие вопросы C/C++ 1 27.05.2010 23:27