• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

zapis i odczyt binarny z pliku

Aruba Cloud - Virtual Private Server VPS
0 głosów
2,355 wizyt
pytanie zadane 27 września 2017 w C i C++ przez B0nkers Początkujący (310 p.)

W zadaniu program, wczytuje dane wejściowe z klawiatury do wektora obiektów klasy string, zapisuje treść tych łańcuchów (a nie obiekty) w pliku, a następnie kopiuje zawartość z powrotem do wektora obiektów klasy string.

Plik jest otwierany w trybie binarnym i że w zamierzeniu operacje wejścia-wyjścia powinny być realizowane za pomocą funkcji read() i  write(). W zadaniu trzeba było zdefiniować:

  • funkcję void ShowStr(const string &) wyświetaljącą zawartość obiektu klasy string zakończoną znakiem nowego wiersza.
  • zdefiniować obiekt funkcyjny Store zapisujący dane łańcuchowe do pliku. Konstruktor obiektu Store powinien pobierać obiekt klasy ofstream, a przeciążona funkcja  operator()(const string &) powinna wskazywać łańcuch do zapisu -> w pliku najpierw ma być wypisany rozmiar łańcucha, a potem jego treść za pomocą instrukcji:
    os.write((char *)&len, sizeof(std::size_t));      //zapisz długość
    os.write(s.data(), len);                                    //zapisz znaki
  • na końcu zdefiniować funkcje GetStrs() odczytującą dane z pliku, w podobny sposób jak funkcja write() powyżej

Poniżej kod programu, jak narazie pojawiają się 2 błędy o podobnej treści związane z inicjalizacją obiektu Store, obiektem ofstream , fragment błędu to : element funkcji nie może być przywołany - jest to usunięta funkcja.  

Związane jest to z inicjalizacją obiektu przez konstruktor opisany powyżej. Nie mam pojęcia jak to poprawnie zrobić.

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <fstream>
#include <cstring>

void ShowStr(const std::string & str);
void GetStrs(const std::ifstream & f, std::vector<std::string> & vec);

class Store
{
private:
	std::ofstream file;
public:
	Store(std::ofstream & f)
		: file(f) {}
	/*Store(const Store & st)
	{
		file = st.file;
	}*/

	~Store()
	{
		file.close();
	}
	void operator()(const std::string & str)
	{
		size_t len = str.size();
		file.write((char *)&len, sizeof(std::size_t));
		file.write(str.data(), len);
	}

};


int main()
{
	using namespace std;
	vector<string> vostr;
	string temp;

	//pobierz łańcuchy
	cout << "Podaj lancuchy (aby zakonczyc, wprowadz pusty wiersz):\n";
	while (getline(cin, temp) && temp[0] != '\0')
		vostr.push_back(temp);
	cout << "Oto twoje dane wejsciowe.\n";
	for_each(vostr.begin(), vostr.end(), ShowStr);

	//zapisz w pliku
	ofstream fout("lancuchy.dat", ios_base::out | ios_base::binary);
	for_each(vostr.begin(), vostr.end(), Store(fout));
	fout.close();

	//odczytaj zawartość pliku
	vector<string> vistr;
	ifstream fin("lancuchy.dat", ios_base::in | ios_base::binary);
	if (!fin.is_open())
	{
		cerr << "Nie mozna otworzyc pliku do odczytu.\n";
		exit(EXIT_FAILURE);
	}
	GetStrs(fin, vistr);
	cout << "Oto lancuchy odczytane z pliku:\n";
	for_each(vistr.begin(), vistr.end(), ShowStr);

	system("PAUSE");
    return 0;
}


void ShowStr(const std::string & str)
{
	std::cout << str << std::endl;
}

void GetStrs(std::ifstream & f, std::vector<std::string> & vec)
{
	int len;
	std::string str;
	f.read((char *)&len, sizeof(std::size_t));
	len = vec.size();

	while (f.read((char *)&str, len))
	{
		vec.push_back(str);
	}

}

 

1
komentarz 27 września 2017 przez niezalogowany
Jest to błąd z kompilatora? Poprosimy cały log błędu + najlepiej w wersji angielskiej
komentarz 27 września 2017 przez B0nkers Początkujący (310 p.)

Błąd z kompilatora. Mam VS w wersji polskiej, nie wiem czy się opłaca szukać zmiany języka. Poniżej log błędu, niestety po polsku(3 błędy):


Błąd (aktywny)    E1776    element funkcja "std::basic_ofstream<_Elem, _Traits>::basic_ofstream(const std::basic_ofstream<_Elem, _Traits>::_Myt &) [gdzie _Elem=char, _Traits=std::char_traits<char>]" (zadeklarowane w wierszu 1065 w "c:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.11.25503\include\fstream") nie może być przywoływany — jest to usunięta funkcja    zd7    c:\Users\marci\OneDrive\Dokumenty\Jezyk C++. Szkola programowania\Rozdzial 17\zd7\zd7.cpp    21    

Błąd (aktywny)    E1776    element funkcja "Store::Store(const Store &)" (zadeklarowano niejawnie) nie może być przywoływany — jest to usunięta funkcja    zd7    c:\Users\marci\OneDrive\Dokumenty\Jezyk C++. Szkola programowania\Rozdzial 17\zd7\zd7.cpp    53    

Błąd    C2280    „std::basic_ofstream<char,std::char_traits<char>>::basic_ofstream(const std::basic_ofstream<char,std::char_traits<char>> &)”: próba odwania do usuniętej funkcji    zd7    c:\users\marci\onedrive\dokumenty\jezyk c++. szkola programowania\rozdzial 17\zd7\zd7.cpp    21    
 

1 odpowiedź

+2 głosów
odpowiedź 27 września 2017 przez j23 Mędrzec (195,240 p.)
wybrane 27 września 2017 przez B0nkers
 
Najlepsza

ofstream nie ma konstruktora kopiującego, więc nie możesz przypisać wartości polu Store::file tak, jak teraz to robisz. Zrób tak:

class Store
{
private:
    std::ofstream &file;
public:
    Store(std::ofstream & f)
        : file(f) {}

	~Store() { }
	...
};

albo:

class Store
{
private:
    std::ofstream file;
public:
    Store(std::ofstream && f)
		:file(move(f)) 
	{}
 
    ~Store()
	{
        	file.close();
	}
	
	... 
};

Opcja pierwsza bardziej pasuje do tego, co chcesz zrobić.

komentarz 10 sierpnia 2019 przez Pawel81PK Nowicjusz (100 p.)

@j23,

Piszę to samo ćwiczenie ale w MS VS2019 po Twojej modyfikacji klasy Store wyrzuca mi błąd w

for_each(vostr.begin(), vostr.end(), Store(fout));

podkreśla fout i wyrzuca:

Błąd (aktywny)    E1776    element funkcja "std::basic_ofstream<_Elem, _Traits>::basic_ofstream(const std::basic_ofstream<_Elem, _Traits> &) [gdzie _Elem=char, _Traits=std::char_traits<char>]" (zadeklarowane w wierszu 1043 w "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.21.27702\include\fstream") nie może być przywoływany — jest to usunięta funkcja    StringToBinaryFile    C:\Users\PolKom\source\repos\StringToBinaryFile\StringToBinaryFile.cpp    44    
 

komentarz 10 sierpnia 2019 przez j23 Mędrzec (195,240 p.)

A zdefiniowałeś w Store operator()?

komentarz 10 sierpnia 2019 przez Pawel81PK Nowicjusz (100 p.)

tak wygląda cały kod:

// StringToBinaryFile.cpp 
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;


void ShowStr(const string& str) { cout << str << endl; }
//void Store(ofstream& f, const string& str) { f.write(str.c_str(), size(str)); }

class Store
{
public:
	Store(ofstream fo):f(fo) {};
	~Store() { f.close(); };
	void operator()(const string& str)
	{
		size_t len = str.size();
		f.write((char*)& len, sizeof(size_t));//zapisz długość
		f.write(str.data(), len);//zapisz łańcuch bez '\0'
	};

private:
	ofstream &f;
};

int main()
{
	
	vector<string> vostr;
	string temp;

	//pobierz łańcuchy
	cout << "Podaj łańcuchy (aby zakończyć wprowadz pusty wiersz):\n";
	while (getline(cin, temp) && temp[0] != '\0')
		vostr.push_back(temp);
	cout << "Oto Twoje dane wejściowe:\n";
	for_each(vostr.begin(), vostr.end(), ShowStr);
    //zapisz w pliku
	ofstream fout("lancuchy.dat", ios_base::out | ios_base::binary);
	for_each(vostr.begin(), vostr.end(), Store(fout));
	fout.close();

}

 

komentarz 10 sierpnia 2019 przez j23 Mędrzec (195,240 p.)
edycja 10 sierpnia 2019 przez j23
  • Linia 17: masz ten sam błąd co OP - przekazujesz strumień przez wartość.
  • Linia 18 i 45: zdecyduj się, albo zamykasz strumień w destruktorze Store, albo poza klasą. IMO tutaj w obu przypadkach nie ma sensu jawne wywołanie close.
  • Linia 38: jak chcesz sprawdzić, czy temp jest puste, użyj metody empty.
komentarz 10 sierpnia 2019 przez Pawel81PK Nowicjusz (100 p.)
Dzięki, przeoczyłem brak referencji.

Podobne pytania

0 głosów
0 odpowiedzi 1,927 wizyt
0 głosów
1 odpowiedź 1,719 wizyt
0 głosów
0 odpowiedzi 854 wizyt
pytanie zadane 13 stycznia 2022 w C i C++ przez Nikso Nowicjusz (230 p.)

93,327 zapytań

142,323 odpowiedzi

322,396 komentarzy

62,657 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 1 Wprowadzenie do ITsec, tom 2

Można już zamawiać dwa tomy książek o ITsec pt. "Wprowadzenie do bezpieczeństwa IT" - mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy aż 15% zniżki! Dziękujemy ekipie Sekuraka za fajny rabat dla naszej Społeczności!

...