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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 31.10.2018, 15:10   #1
KAMLS
Форумчанин
 
Регистрация: 09.04.2017
Сообщений: 598
По умолчанию Запись объекта пользовательского класса в файл

Здравствуйте!
Изучая означенную тему, пришел к выводу, что в общем то большинство примеров ориентированно на то, что в классе есть методы, которые обеспечивают запись объекта в файл DAT.
Есть методы, где подобная запись обеспечивается без таковых методов. Например, код представленный ниже использует
Код:
reinterpret_cast<char*>
хотя пишется везде что это не очень то и комильфо.
Если у меня поля в классе не чар и для бинарного файла надо как-то всё переводить со стрингов, интов и т.п. Как это сделать без
Код:
reinterpret_cast<char*>
?
Код:
class person  // класс person
{
protected:
	char name[80];  // имя человека (тут хочется string)
	int age;  // его возраст
public:
	void getdata()  // получить данные о человеке
	{
		cout << "\n Введите имя: "; cin >> name;
		cout << " Введите возраст: "; cin >> age;
	}
	void showData()  // вывод данных о человеке
	{
		cout << "\n Имя: " << name;
		cout << "\n Возраст: " << age;
	}
};
///////////////////////////////////////////////////////////
int main()
{
	char ch;
	person pers;  // создать объект person
	fstream file;  // создать входной/выходной файл
	
	file.open("GROUP.DAT", ios::app | ios::out |ios::in | ios::binary);// открыть для дозаписи

	do  // данные от пользователя - в файл
	{
		cout << "\nВведите данные о человеке:";
		pers.getdata();  // получить данные 
		file.write(reinterpret_cast<char*>(&pers), sizeof(pers));//записать их в файл
		cout << "Продолжить ввод (y/n)? ";
		cin >> ch;
	} 
	while (ch == 'y');  // выход по 'n'

	file.seekg(0);  // поставить указатель на начало файла

	file.read(reinterpret_cast<char*>(&pers), sizeof(pers));	// считать данные о первом человеке

	while (!file.eof())    // Выход по EOF
	{
		cout << "\nПерсона:";// вывести данные
		pers.showData();  // считать данные о следующем
		file.read(reinterpret_cast<char*>(&pers), sizeof(pers));
	}
	cout << endl;
	_getch();
	return 0;
}
KAMLS вне форума Ответить с цитированием
Старый 31.10.2018, 15:18   #2
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Цитата:
Сообщение от KAMLS Посмотреть сообщение
Изучая означенную тему, пришел к выводу, что в общем то большинство примеров ориентированно на то, что в классе есть методы, которые обеспечивают запись объекта в файл DAT.
1. Естественно, класс (его программист) лучше знает как и что писать/читать.
2. Нет такого понятия, как файл DAT. Есть просто файл, бинарный или нет. Расширение можно выбрать любое.

Цитата:
Сообщение от KAMLS Посмотреть сообщение
Если у меня поля в классе не чар и для бинарного файла надо как-то всё переводить со стрингов, интов и т.п. Как это сделать без
1. Кастование указателя к чар не имеет никакого отношения к тому, что есть у вас в классе чар или нет.
2. Делать более правильно - написать две функции для сериализации и десериализации. В одной записать все или часть полей, во второй прочитать и вызвать конструкторы.
p51x вне форума Ответить с цитированием
Старый 31.10.2018, 15:27   #3
KAMLS
Форумчанин
 
Регистрация: 09.04.2017
Сообщений: 598
По умолчанию

Яснее стало, буду разбираться, спасибо.
KAMLS вне форума Ответить с цитированием
Старый 01.11.2018, 06:50   #4
KAMLS
Форумчанин
 
Регистрация: 09.04.2017
Сообщений: 598
По умолчанию

Здравствуйте!
Столкнулся с одной из методик записи данных в бинарный файл. И вроде всё логично и последовательно и понятно. Да вот только как только попытаешься его выполнить, так сразу ошибка возникает. Причем показывается как исправить ошибку. Исправляешь ошибку как советует визуал, так возникает еще больше ошибок. Зачем же он тогда так советует?
Речь о методе fopen и предложении заменить этот метод на fopen_s.
На скриншотах хорошо видно.

Как правильно сделать такой способ записи в файл?
Изображения
Тип файла: jpg кадр_8.jpg (61.5 Кб, 148 просмотров)
Тип файла: jpg кадр_9.jpg (70.3 Кб, 119 просмотров)
KAMLS вне форума Ответить с цитированием
Старый 01.11.2018, 08:28   #5
Black Fregat
Программист
Участник клуба
 
Аватар для Black Fregat
 
Регистрация: 23.06.2009
Сообщений: 1,772
По умолчанию

1) Вот какая сила мешает открыть справку по fopen_s и посмотреть, какие параметры ей надо передавать?

2) Почему Вы выкладываете код картинкой? Мне проще было бы скопировать нужный кусок и поправить его. Да и цветовая гамма Вашей студии мне глаза режет, уж извините

3) Я бы советовал тут наплевать на рекомендации Microsoft, специфические для её продуктов, и поставить
Код:
#define _CRT_SECURE_NO_WARNINGS
Black Fregat вне форума Ответить с цитированием
Старый 01.11.2018, 08:36   #6
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,695
По умолчанию

Еще раз повторю: начать читать справку или хотя бы объявления используемых функций.
https://docs.microsoft.com/en-us/cpp...s?view=vs-2017

Цитата:
Сообщение от Black Fregat Посмотреть сообщение
бы советовал тут наплевать на рекомендации Microsoft, специфические для её продуктов, и поставить
Не такие уж они и специфические https://en.cppreference.com/w/c/io/fopen
p51x вне форума Ответить с цитированием
Старый 01.11.2018, 11:05   #7
KAMLS
Форумчанин
 
Регистрация: 09.04.2017
Сообщений: 598
По умолчанию

Спасибо за советы, они помогли малость разобраться. В итоге на основе примеров из интернета и кое-каких своих редакций сваял вот такой код.
Код:
#include <iostream>
#include<fstream>
#include<string>
#include<Windows.h>
#include<conio.h>

using namespace std;

struct building
{
	char name[35];
	char city[20];
	int exams[5];
	char film[20];
	int years;
	string str;
};

const char *fname1 = "C://Papka//test1.dat";

///////////////////////////////////////////////////////////
int main(int argc, char * argv[])
{
	setlocale(LC_CTYPE, "rus");
	SetConsoleCP(1251);
	SetConsoleOutputCP(1251);

	building bg1, bg2;
	strcpy_s(bg1.name, "Lenin");
	strcpy_s(bg1.city, "Magadan");
	strcpy_s(bg1.film, "Tarzan");
	bg1.str = "чака";
	bg1.years = 33;
	strcpy_s(bg2.name, "Mira");
	strcpy_s(bg2.city, "Riga");
	strcpy_s(bg2.film, "Zizi");
	bg2.str = "ququbema";
	bg2.years = 34;
	for (int i = 0; i < 5; i++) {
		bg1.exams[i] = i;
		bg2.exams[i] = i * 2;
	}

	ofstream ofs1(fname1, ios::app | ios::out | ios::in | ios::binary);
	if (ofs1)
	{
		ofs1.write((char *)&bg1, sizeof(building));
		ofs1.write((char *)&bg2, sizeof(building));
	}
	else
		cout << "File open error: " << fname1 << endl;

	ifstream ofs2(fname1, ios::app | ios::out | ios::in | ios::binary);
	if (ofs1)
	{
		ofs2.open((char *)&bg1, sizeof(building));
		ofs2.read((char *)&bg2, sizeof(building));
	}
	else
		cout << "File open error: " << fname1 << endl;
	cout << bg1.str << endl;
	cout << bg2.str<<endl;
	cout << bg1.years << endl << bg2.years;
	_getch();
	return 0;
}
Всё работает и радует.
Однако возникли вопросы.
1. Зачем в первом примере темы использован
Код:
reinterpret_cast<char*>(&pers)
если и без него строки и числа нормально читаются и записываются.

2. Для чего такое многообразие методов записи в файл и чтения из него, к тому же модифицированные (из fopen в fopen_s )

А при чтении из файла я вообще вот так написал и работает
Код:
ifstream ofs2(fname1, ios::app | ios::out | ios::in | ios::binary);
	if (ofs1)
	{
		ofs2.open((char *)&bg1, sizeof(building));
		ofs2.read((char *)&bg2, sizeof(building));
Для чего такое многообразие? Есть конкретная цель, или это результат развития языка и просто не убирают ранее использовавшиеся методы модифицируют их под современные надобности?
KAMLS вне форума Ответить с цитированием
Старый 01.11.2018, 11:33   #8
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Цитата:
Сообщение от KAMLS Посмотреть сообщение
если и без него строки и числа нормально читаются и записываются.
если работает, то скорее всего компиляторы могут выдать варнинг о неявном касте.
Цитата:
Сообщение от KAMLS Посмотреть сообщение
Для чего такое многообразие?
(type) something это каст из С, в С++ лучше выбрать какой-нибудь из кастов С++.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 01.11.2018, 12:13   #9
KAMLS
Форумчанин
 
Регистрация: 09.04.2017
Сообщений: 598
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
если работает, то скорее всего компиляторы могут выдать варнинг о неявном касте.
Нет, вообще без запинки и каких-либо сообщений.


Цитата:
Сообщение от Alex11223 Посмотреть сообщение
(type) something
Честно сказать написанное не понял. Не шибко в терминах горазд пока.
Это вот такое?
Код:
static_cast < type_to > ( object_from )
KAMLS вне форума Ответить с цитированием
Старый 01.11.2018, 12:31   #10
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Ну варнинги зависят от компилятора и настроек.

Qt Creator c Clang и компилятором VS 2017:



Вы не понимаете где тип и где не тип в С касте?
(int) number
(char*) data

static_cast это С++.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Ответ


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

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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Запись объекта в файл Sheffdmb2010 Общие вопросы C/C++ 9 31.05.2013 19:54
Запись объекта в файл CodeNOT PHP 5 22.06.2011 13:15
Хранение в векторе объектов пользовательского класса jennya Visual C++ 4 03.10.2010 19:16
[PHP] Запись класса в файл Ramirag PHP 3 21.04.2010 00:40
Массив эллементов пользовательского класса windzor Общие вопросы .NET 4 02.03.2010 19:53