2010-03-04 17 views

Odpowiedz

7

Można zastąpić operator>> i operator<< do odczytu/zapisu do strumienia.

Przykład Entry struct z pewnymi wartościami:

struct Entry2 
{ 
    string original; 
    string currency; 

    Entry2() {} 
    Entry2(string& in); 
    Entry2(string& original, string& currency) 
     : original(original), currency(currency) 
    {} 
}; 


istream& operator>>(istream& is, Entry2& en); 
ostream& operator<<(ostream& os, const Entry2& en); 

Realizacja:

using namespace std; 

istream& operator>>(istream& is, Entry2& en) 
{ 
    is >> en.original; 
    is >> en.currency; 
    return is; 
} 

ostream& operator<<(ostream& os, const Entry2& en) 
{ 
    os << en.original << " " << en.currency; 
    return os; 
} 

Wtedy otwarty filestream, a dla każdego obiektu zadzwonić:

ifstream in(filename.c_str()); 
Entry2 e; 
in >> e; 
//if you want to use read: 
//in.read(reinterpret_cast<const char*>(&e),sizeof(e)); 
in.close(); 

lub wyjście:

Entry2 e; 
// set values in e 
ofstream out(filename.c_str()); 
out << e; 
out.close(); 

Lub jeśli chcesz użyć strumienia read i write, po prostu zamień odpowiedni kod w implementacji operator s.

Gdy zmienne są prywatne wewnątrz struktury/klasy, musisz zadeklarować operator s jako metody znajomych.

Implementujesz dowolny format/separatory, które lubisz. Gdy twój ciąg znaków zawiera spacje, użyj getline(), który pobiera łańcuch i strumień zamiast >>, ponieważ operator>> domyślnie używa spacji jako ograniczników. Zależy od twoich separatorów.

0

Niestety, zazwyczaj nie jest to możliwe. Jeśli twoja struktura zawiera tylko zwykłe dane (bez wskaźników lub złożonych obiektów), możesz zachować ją jako jedną porcję, ale należy zachować ostrożność, jeśli przenośność jest problemem. Obciążenie, rozmiar i problemy z typem danych sprawiają, że jest to problematyczne.

Można użyć funkcji Boost.Serialization, aby zminimalizować ilość kodu wymaganą do prawidłowej, przenośnej i wersjonowanej funkcji wyszukiwania.

1

Lepszą metodą jest zapisanie każdego pola pojedynczo wraz z długością ciągu.

Alternatywnie można utworzyć tablicę char (lub std::vector<char>) i zapisać wszystkie elementy w buforze, a następnie zapisać bufor na wyjściu.

Podstawowym kolcem jest to, że kompilator może wstawiać dopełnienie między elementami w klasie lub strukturze. Użycie memcpy lub std::copy spowoduje dopełnienie bajtów zapisanych na wyjściu.

Pamiętaj tylko, że musisz wpisać długość łańcucha i treść lub treść, a następnie znak kończący.

Inne osoby zasugerują sprawdzenie biblioteki Boost Serialization.

3

Jeśli masz:

struct A { 
    char a[30], b[25], c[15]; 
    int x; 
} 

następnie można napisać to wszystko tylko z zapisu (FH, PTR, sizeof (struct a)).

Oczywiście, nie jest to przenośne urządzenie (ponieważ nie oszczędzamy na poziomie docelowym lub wielkości "int", ale może to nie być problemem dla Ciebie.

Jeśli masz:

struct A { 
    char *a, *b, *c; 
    int d; 
} 

wtedy nie szukasz napisać obiektu; szukasz serializacji. Najlepiej jest zajrzeć do bibliotek Boost i skorzystać z ich procedur serializacji, ponieważ nie jest to łatwy problem w językach bez refleksji.

0

Zakładając, że Twój cel jest taki, jak stwierdzono, aby wypisać obiekt za pomocą pojedynczego wywołania funkcji write() lub fwrite() lub cokolwiek innego, najpierw musisz skopiować ciąg i inne dane obiektów do pojedynczego ciągłego bloku pamięć. Następnie możesz napisać() ten blok pamięci za pomocą jednego połączenia. Lub możesz napisać wektor, dzwoniąc do writev(), jeśli to połączenie jest dostępne na twojej platformie.

Powiedział, że prawdopodobnie nie zyska znacznie redukując liczbę połączeń zapisu. Zwłaszcza jeśli używasz już fwrite() lub podobnego, biblioteka C robi już buforowanie, więc koszt wielu małych połączeń i tak jest minimalny. Nie postawić się przez wiele dodatkowego bólu i złożoności kodu, chyba że będzie to rzeczywiście zrobić coś dobrego ...