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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 16.01.2013, 07:58   #1
hvz-
Форумчанин
 
Регистрация: 14.11.2010
Сообщений: 138
По умолчанию [C] ReadFile/WriteFile

Всем доброго времени суток!
Есть вроблема с програмкой ,а именно: Unhandled exception at 0x010b1493 in lab3.exe: 0xC0000005: Access violation reading location 0x00000000.

Исходник:
Код:
#include <conio.h>
#include <stdio.h>
#include <windows.h>
#include <shlobj.h>

struct Student
{
	int code;
	char name[20];
	char surname[20];
	char group[10];
};

BOOL CheckStudentDirAndFile(void);
void MakeStudents(Student *st);
void WriteStudentsToFile(Student *st, int stud_number, DWORD *nb);
void ReadStudentsFromFile(int stud_number, DWORD *nb);
void CopyStudentsToDocs(void);

int main()
{
	if(CheckStudentDirAndFile() == TRUE)
	{
		HANDLE hFindFile;
		WIN32_FIND_DATAA fdFindData;
		SYSTEMTIME smSysTime;
		hFindFile=FindFirstFileA("C:\\Student\\stud.dat",&fdFindData);
		if(hFindFile != INVALID_HANDLE_VALUE)
		{
			FileTimeToSystemTime(&fdFindData.ftLastWriteTime, &smSysTime);
			printf("%s\t%d.%d.%d  %d:%d\n",fdFindData.cFileName,smSysTime.wDay,smSysTime.wMonth,smSysTime.wYear, smSysTime.wHour, smSysTime.wMinute);
			FindClose(hFindFile);
			printf("Press any key to exit...\n");
			_getch();
			return 0;
		}
	}
	else
	{
		DWORD nb;
		int stud_number=0;
		printf("Enter student's number: ");
		scanf_s("%d", &stud_number);
		Student* st=new Student[stud_number];
		for (int i=0;i<stud_number;i++)
			MakeStudents(&st[i]);

		WriteStudentsToFile(st, stud_number, &nb);
		ReadStudentsFromFile(stud_number, &nb);
		CopyStudentsToDocs();
		printf("Press any key to exit...\n");
		_getch();
		return 0;
	}
}

BOOL CheckStudentDirAndFile(void)
{
	HANDLE hFile;
	WIN32_FIND_DATAA fdFindData;
	hFile=FindFirstFileA(("C:\\Student\\stud.dat"),&fdFindData);
	if(hFile != INVALID_HANDLE_VALUE)
	{
		FindClose(hFile);
		printf("Founded file C:\\Student\\stud.dat!\n");
		return TRUE;
	}
	else
	{
		if(CreateDirectoryA("C:\\Student", NULL))
		{
			printf("Directory C:\\Student created successfully!\n");
			hFile = CreateFileA("C:\\Student\\stud.dat",GENERIC_WRITE,0,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
			
			if(hFile)
				printf("File stud.dat created successfully!\n");
			else
				printf("Can not create file stud.dat in C:\\Student!\n");

			CloseHandle(hFile);
			return FALSE;
		}
		else
		{
			printf("Can not create directry C:\\Students! Possibly already exist.\n");
			CloseHandle(hFile);
			return FALSE;
		}
	}
}

void MakeStudents(Student *st)
{
	printf("Student code: ");
	scanf_s("%d", &st->code);
	printf("Student name: ");
	scanf_s("%s", &st->name);
	printf("Student surname: ");
	scanf_s("%s", &st->surname);
	printf("Student group: ");
	scanf_s("%s", &st->group);
}

void WriteStudentsToFile(Student *st, int stud_number, DWORD *nb)
{
	HANDLE hFile;
	char file_path[] = "C:\\Student\\stud.dat";
	hFile = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if(!hFile)
	{
		printf("Error while creating file %s for writing!\n", file_path);
		CloseHandle(hFile);
	}
	else
	{
		SetFilePointer(hFile, 4, NULL, FILE_END);
		for (int i=0;i<stud_number;i++)
			WriteFile(hFile,&i,sizeof(&st[i]),&*nb,NULL);
		CloseHandle(hFile);
		printf("\nStudents writed to file %s\n", file_path);
	}
}

void ReadStudentsFromFile(int stud_number, DWORD *nb)
{
	HANDLE hFile;
	char file_path[] = "C:\\Student\\stud.dat";
	hFile = CreateFileA(file_path, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if(!hFile)
	{
		printf("Error while creating file %s for reading!\n", file_path);
		CloseHandle(hFile);
	}
	else
	{
		printf("%s contains:\n\n", file_path);
		Student *st_buf;
		int i=1;
		ReadFile(hFile, &st_buf, sizeof(Student), &*nb,NULL);
		while (nb!=0)
		{	
			printf("----------%d----------\n", i++);
			printf("Student code: %d\n", st_buf->code);
			printf("Student name: %s\n", st_buf->name);
			printf("Student surname: %s\n", st_buf->surname);
			printf("Student group: %s\n", st_buf->group);
			printf("----------------------\n");
			ReadFile(hFile, &st_buf, sizeof(Student), &*nb, NULL);
		}
		CloseHandle(hFile);
	}
}

void CopyStudentsToDocs(void)
{
	char docs_path[50];
	char path[100];
	SHGetFolderPathA(NULL, CSIDL_COMMON_DOCUMENTS, NULL, SHGFP_TYPE_CURRENT, docs_path);
	sprintf_s(path, "%s\\stud.dat", docs_path);
	if(CopyFileA("C:\\Student\\stud.dat", path, TRUE) != FALSE)
		printf("stud.dat copied to %s\n", path);
	else
		printf("Can not copy C:\\Student\\stud.dat file to %s", path);
}
Ошибка выскакивает в функции ReadStudentsFromFile.
Вроде и записываю и читаю правильно, чего я только не делал...
hvz- вне форума Ответить с цитированием
Старый 16.01.2013, 08:43   #2
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Код:
Student st_buf;
ReadFile(hFile, &st_buf, sizeof(Student), nb, NULL)
while (*nb)
А запись в файл вообще полный аут.
Что бы это значило: ????
Код:
		
for (int i=0;i<stud_number;i++)
WriteFile(hFile,&i,sizeof(&st[i]),&*nb,NULL);
Запись в файл переменной i ????


Должно быть что-то типа этого:
Код:
    // никакого цикла		
    WriteFile(hFile, st, sizeof(Student)*stud_number, nb, NULL);

Последний раз редактировалось EUGY; 16.01.2013 в 09:08.
EUGY вне форума Ответить с цитированием
Старый 16.01.2013, 09:11   #3
hvz-
Форумчанин
 
Регистрация: 14.11.2010
Сообщений: 138
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Код:
Student st_buf;
ReadFile(hFile, &st_buf, sizeof(Student), nb, NULL)
while (*nb)
А запись в файл вообще полный аут.
Что бы это значило: ????
Код:
		
for (int i=0;i<stud_number;i++)
WriteFile(hFile,&i,sizeof(&st[i]),&*nb,NULL);
Запись в файл переменной i ????
Если честно, не знаю, брал из примера преподователя, там с целочисленными данными пример был.
Дело в том, что с winapi функциями для работы с файлами я не знаком, только из стандартной библиотеки C и C++, поэтому делал наугад.
Странно, заменил i на &st[i] и всё равно та же ошибка.
Не могли бы вы направить меня на путь истинный? Другие функции не предлагать, нужны именно winapi.
hvz- вне форума Ответить с цитированием
Старый 16.01.2013, 09:30   #4
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Код:
void WriteStudentsToFile(Student *st, int stud_number, DWORD *nb);
void ReadStudentsFromFile(int stud_number, DWORD *nb);
Поясните, для чего DWORD *nb ?
Я не вижу причин использовать этот параметр. Или какая-то задумка c ним есть?
Вот функция записи
Код:
void WriteStudentsToFile(Student *st, int stud_number, DWORD *nb)
{
	char file_path[] = "C:\\stud.dat";
	if(HANDLE hFile = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) )
	{
		SetFilePointer(hFile, NULL, NULL, FILE_END);
		WriteFile(hFile, st, sizeof(Student)* stud_number, nb, NULL);
		printf("\nStudents writed to file %s\n", file_path);
		CloseHandle(hFile);
	}
	else
	{
		printf("Error while creating file %s for writing!\n", file_path);
	}
}
EUGY вне форума Ответить с цитированием
Старый 16.01.2013, 09:42   #5
hvz-
Форумчанин
 
Регистрация: 14.11.2010
Сообщений: 138
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Код:
void WriteStudentsToFile(Student *st, int stud_number, DWORD *nb);
void ReadStudentsFromFile(int stud_number, DWORD *nb);
Поясните, для чего DWORD *nb ?
Я не вижу причин использовать этот параметр. Или какая-то задумка c ним есть?
Вот функция записи
Код:
void WriteStudentsToFile(Student *st, int stud_number, DWORD *nb)
{
	char file_path[] = "C:\\stud.dat";
	if(HANDLE hFile = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) )
	{
		SetFilePointer(hFile, NULL, NULL, FILE_END);
		WriteFile(hFile, st, sizeof(Student)* stud_number, nb, NULL);
		printf("\nStudents writed to file %s\n", file_path);
		CloseHandle(hFile);
	}
	else
	{
		printf("Error while creating file %s for writing!\n", file_path);
	}
}
DWORD nb - не знаю, говорю же, ориентировался по примеру от преподователя. Если не ошибаюсь, это количество записанных байтов.

Как я понимаю, эту функцию нужно будет в цикле вызывать? Т.е. если у меня массив структур, то каждый экземпляр(элемент структурного массива) нужно будет записывать? Или всё разом записывает?
hvz- вне форума Ответить с цитированием
Старый 16.01.2013, 09:55   #6
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Конечно записывает за один раз.
Вот Вы создали Student* st = new Student[stud_number];

st - адрес
stud_number - количество

Для функции WriteFile этого достаточно. Начальный адрес известен, значит его и пишем. Длина записи sizeof(Student) * stud_number.
Лишний параметр из функции убираем:
Код:
void WriteStudentsToFile(Student *st, int stud_number)
{
	DWORD writen;
	char file_path[] = "C:\\stud.dat";
	if(HANDLE hFile = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL) )
	{
		SetFilePointer(hFile, NULL, NULL, FILE_END);
		WriteFile(hFile, st, sizeof(Student)* stud_number, &writen, NULL);
		printf("\nStudents writed to file %s\n", file_path);
		CloseHandle(hFile);
	}
	else
	{
		printf("Error while creating file %s for writing!\n", file_path);
	}
}
Теперь вдумчиво посмотрим на ReadStudentsFromFile.
Тут лишние все параметры. stud_number нигде внутри функции не используется.
EUGY вне форума Ответить с цитированием
Старый 16.01.2013, 10:00   #7
hvz-
Форумчанин
 
Регистрация: 14.11.2010
Сообщений: 138
По умолчанию

Спасибо, буду пробовать.
А на счёт DWORD nb - его использование нужно было что бы в самой функции устроить цикл который будет по одной записи записывать/выводить.

Кстати, а если я хочу устроить в самой функции цикл? Т.е. если записывать в файл - тупо скормить функции массив структур и количество элементов в массиве, а она уже сама проведёт все операции? Хочу так для того, что бы кода в main() было бы меньше и более понятней.
hvz- вне форума Ответить с цитированием
Старый 16.01.2013, 10:09   #8
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

Как нужно для логики программы так и поступайте. Собственно Вы и так main разгрузили. Насчет циклов - дело хозяйское, но если речь идет о том, что есть массив структур и известна его длина, то зачем нужен цикл.
EUGY вне форума Ответить с цитированием
Старый 16.01.2013, 10:19   #9
hvz-
Форумчанин
 
Регистрация: 14.11.2010
Сообщений: 138
По умолчанию

Цитата:
Сообщение от EUGY Посмотреть сообщение
Насчет циклов - дело хозяйское, но если речь идет о том, что есть массив структур и известна его длина, то зачем нужен цикл.
Что бы не тратить время на нудное объяснение, вот что получилось но пока не проверял:
Код:
void WriteStudentToFile(Student *st, int stud_number)
{
	DWORD wdBytesWritten;
	char file_path[] = "C:\\Student\\stud.dat";
	if(HANDLE hFile = CreateFileA(file_path, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);)
	{
		for(int i=0; i<=stud_number; i++)
		{
			SetFilePointer(hFile, NULL, NULL, FILE_END);
			WriteFile(hFile, &st[i], sizeof(Student)* i, &wdBytesWritten, NULL);
		}
		CloseHandle(hFile);
		printf("\nStudents writed to file %s\n", file_path);
	}
	else
	{
		printf("Error while creating file %s for writing!\n", file_path);
		CloseHandle(hFile);
	}
}
А на счёт функции ReadStudentFromFile - если не использовать параметры int stud_number, DWORD *nb то как организовать "читание" файла? Ну stud_number - действительно не используется, а вот *nb нужен был для цикла в котором идёт последовательный вывод записанных экземпляров структур.
Если не использовать *nb параметр, как же тогда читать в цикле?
Может можно как то саму фeнкцию чтения ReadFile запихнуть в условие цикла while?

Последний раз редактировалось hvz-; 16.01.2013 в 10:27.
hvz- вне форума Ответить с цитированием
Старый 16.01.2013, 10:30   #10
EUGY
Форумчанин
 
Аватар для EUGY
 
Регистрация: 11.07.2010
Сообщений: 914
По умолчанию

1) for(int i=0; i < stud_number; i++) // i < stud_number

2) WriteFile(hFile, st + i, sizeof(Student), &wdBytesWritten, NULL);

Цитата:
Если не использовать *nb параметр, как же тогда читать в цикле?
объявить внутри функции, а не использовать как ненужный параметр.
Код:
DWORD wdBytesRead; 
//....
ReadFile(hFile, &st_buf, sizeof(Student), &wdBytesRead, NULL);
EUGY вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
ReadFile/WriteFile - нужен совет. Linnk Win Api 1 07.08.2012 15:57
ошибка в программе - Create ReadFile handle Ted_45 Win Api 2 25.06.2012 20:17
ReadFile() Madmaxisss Visual C++ 4 02.04.2012 01:01
проблема с ReadFile Fog Win Api 4 01.02.2011 12:51
ReadFile nazavrik Общие вопросы C/C++ 14 22.11.2009 15:11