Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

29.01.2011, 21:49

std::copy Problem

Hallo, ich steh mal wieder an.

Ich habe einen Vector, in dem ich eine Struktur speichere.
Diesen Vektor würde ich jetzt gerne per std::copy - funktion ein - und auslesen (in eine Datei).

Ich scheitere jedoch dabei und habe mich auch schon durch google gekämpft, finde aber nichts, das mir Hilft :$

Ich kanns nicht so gut in Worte packen, daher hier ein Codebeispiel:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct STileConfig
{
    STileConfig() : bBackroudGrass(true), bWay(false) {}; //Standardkonstruktor

    bool bBackroudGrass;
    bool bWay;
};

vector<STileConfig> m_vConfig;

//So könnte ich es machen, würde es aber durch eine copy Funktion erstzen
ofstream output("Data/Test.txt",ios::binary);

output << "Konfiguration:";
for(vector<STileConfig>::iterator iter = m_vConfig.begin(); iter != m_vConfig.end(); iter++) 
{
    output << endl << iter -> bBackroudGrass;
    output << iter -> bWay;
}

//Hier mein versuch, die Datei einzulesen
m_vConfig.clear(); //Map Konfiguration löschen
    
ifstream input("Data/Test.txt",ios::binary);
    
//input >> std::noskipws; //Über Google gefunden ... weiß nicht, ob ich das wirklich brauche
copy(std::istream_iterator<STileConfig>(input), std::istream_iterator<STileConfig>(), std::back_inserter(m_vConfig));


Hoffe, ihr könnt mir einen Schups in die richtige Richtung geben :)

Liebe Grüße,
Ombalat

Edit: Über ne Erklärung würde ich mich auf freuen :)

Darkrel

Treue Seele

Beiträge: 143

Wohnort: Zürich

Beruf: Student ETH Zürich

  • Private Nachricht senden

2

29.01.2011, 22:13

Hm... eben ausprobiert. Das einzige was mein compiler mir meldet ist, dass er keinen entsprechenden operator>> finden kann.

C-/C++-Quelltext

1
2
3
4
5
6
7
template<typename StreamType>
StreamType& operator>>(StreamType &stream, STileConfig &object)
{
    stream >> object.bBackroudGrass;
    stream >> object.bWay;
    return stream;
};


eingefügt und er kompiliert zumindest schon mal. Ich melde mich gleich, wenn ich das ganze konkret getestet habe.
:cursing:

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

29.01.2011, 22:15

Ich denke das Problem ist dass du dein struct in Textform in die Datei schreibst...

4

29.01.2011, 22:25

Wie ich schon im Code erwähnt habe, würde ich auch diese ausgabe in textform auf std::copy umstellen, wenn das funktioniert.

Bin aber auch für andere vorschläge offen ;)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

29.01.2011, 22:32

Naja du kannst ja deinen eigenen Satz von iteratoren schreiben wenn du unbedingt meinst std::copy verwenden zu müssen. Ich würd einfach ne Schleife machen die mir die Dinger ausgibt und einliest in was auch immer für einem Format ich eben will^^

Edit: Allerdings frag ich mich warum Binärfile wenn du dann mit stream iteratoren hantierst...

Edit 2: Wenn ich mir das genauer anschau dann kommen da einige Fragen auf. Hast du einen eigenen operator >> definiert für deine STileConfig Objekte? Wenn ja wie weißt du wo bBackroudGrass aufhört und bWay anfängt? Ohne kanns kaum kompilieren wie Darkrel schon festgestellt hat. Und mit einem operator << und operator >> kannst du einfach stream iteratoren verwenden. Du kannst deine operatoren dann auch so schreiben dass die keinen formatierten Output schreiben sondern eben einfach write() und read() verwenden. Das wär aber irgendwie gegen die Konvention. Warum nicht einfach eine Funktion schreiben die eben so einen vector binär in eine Datei dumped bzw. aus einer Datei liest?

Dieser Beitrag wurde bereits 6 mal editiert, zuletzt von »dot« (29.01.2011, 22:50)


Darkrel

Treue Seele

Beiträge: 143

Wohnort: Zürich

Beruf: Student ETH Zürich

  • Private Nachricht senden

6

29.01.2011, 22:47

Und wenn du das ganze wirklich binär machen willst, solltest du dir die std::istreambuf_iterator klasse mal anschauen. <--- Edit dazu: geht doch auch so. istreambuf_iterator ist wirklich nur dazu da, um die daten aus dem input in einen buffer zu lesen. Wenn ich die lust dazu habe, schreibe ich mal noch dazu was. Ansonsten kann ich dir noch empfehlen, diesen operator<< neu zu schreiben, für standard streams, also auch für cout und ofstreams bzw. ifstreams einfach in einer Spezialisierung binär zu handhaben.

Edit: Da, bitteschön. So funktionierts.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
struct STileConfig
{
    STileConfig() : bBackroudGrass(true), bWay(false) {}; //Standardkonstruktor

    bool bBackroudGrass;
    bool bWay;
};

//Schreibt in beliebige stream typen, die write mit der gegebenen Signatur unterstützen.
template<typename StreamType>
StreamType& operator<<(StreamType &stream, STileConfig &config)
{
    stream.write((char*)(&config.bBackroudGrass), sizeof(bool));
    stream.write((char*)(&config.bWay), sizeof(bool));
    return stream;
};

//Liest aus beliebigen streams, die die gegebene Signatur unterstützen.
template<typename StreamType>
StreamType& operator>>(StreamType &stream, STileConfig &config)
{
    char buffer[2];
    stream.read(&buffer[0], 2);
    config.bBackroudGrass = buffer[0];
    config.bWay = buffer[1];
    return stream;
};

//Helferfunktion, um main() für das Beispiel ein wenig frei zu halten ;)
void fill_random_config(vector<STileConfig> &fill)
{
    for(int i = 0; i < 10; ++i)
    {
        STileConfig temp;
        temp.bBackroudGrass = rand() % 2 == 0? true : false;
        temp.bWay = rand() % 2 == 0? true : false;
        fill.push_back(temp);
        cout << "Added STileConfig:" << temp.bBackroudGrass << "/" << temp.bWay << endl;
    }
};

/* Main entry point of the application */
int main(int argc, char** argv)
{
    vector<STileConfig> m_vConfig;
    //Fix mit irgendwas auffüllen ;)
    fill_random_config(m_vConfig);


    ofstream out("Test.txt", ios::binary);
        //Das ruft jetzt das obige template auf, also operator<<(out, *config), es wird also binär geschrieben.
    for(vector<STileConfig>::iterator config = m_vConfig.begin(); config != m_vConfig.end(); ++config)
        out << *config;
        
        //Flushen nicht vergessen. Ohne gings nicht :p
    out.flush();
    out.close();

    m_vConfig.clear();

    ifstream input("Test.txt", ios::binary);
        //Benutzt intern das obige template, also operator>>(input, temporary_STileConfig), wird also binär gelesen.
    copy(istream_iterator<STileConfig>(input), istream_iterator<STileConfig>(), back_inserter(m_vConfig));
        
        //Nur mal testweise noch ausgeben. Hat aber funktioniert :) Hoffe es funktioniert bei dir auch noch.
    for(vector<STileConfig>::iterator config = m_vConfig.begin(); config != m_vConfig.end(); ++config)
        cout << "Found config: " << config->bBackroudGrass << "/" << config->bWay << endl;

        //system("pause") funktioniert bei mir mitm gcc nicht, falls du MSVC benutzt kannst du das wider reinnehmen. 
    //system("pause");
};
:cursing:

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »Darkrel« (29.01.2011, 23:22)


7

30.01.2011, 04:03

Nana also wenn mans sauber machen will überlädt man operator<< und operator>>, einen zum Ausgeben, einen zum Einlesen. Was man dabei jetzt genau mit den Daten anstellt, ist relativ egal.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <iostream> // std::istream, std::ostream
#include <iterator> // std::istream_iterator, std::ostream_iterator, std::back_inserter
#include <vector> // std::vector
#include <cstdlib> // std::srand, std::rand
#include <algorithm> // std::copy
#include <ctime> // std::time


struct TileConfig
{
    TileConfig(const bool backgroundGras = true, const bool way = false) 
        : BackroudGras(backgroundGras), Way(way)
    {}

    bool BackroudGras;
    bool Way;

    friend std::ostream& operator<<(std::ostream& out, TileConfig const& data) 
    { return (out << data.BackgroundGras << data.Way); }
    friend std::istream& operator>>(std::istream& in, TileConfig& data) 
    { return (in >> data.BackgroundGras >> data.Way); }
};

void random_config(std::vector<TileConfig>& data, const unsigned int max = 10)
{
    for (unsigned int i(0); i < max; ++i)
        data.push_back(TileConfig(std::rand() % 2 == 0, std::rand() % 2 == 0));
}

int main() 
{
    std::srand(static_cast<unsigned int>(std::time(NULL)));
    std::vector<TileConfig> tiles;
    random_config(tiles, 100);

    std::cout << "Random Configs: " << std::endl;
    std::copy(tiles.begin(), tiles.end(), std::ostream_iterator<TileConfig>(std::cout, "\n\n"));

    { // save to file
        std::ofstream file_stream("config.dat");
        std::copy(tiles.begin(), tiles.end(), std::ostream_iterator<TileConfig>(std::cout, "\n"));
    }
    tiles.clear();
    { // read from file
        std::ifstream file_stream("config.dat");
        std::copy(std::istream_iterator<TileConfig>(file_stream), std::istream_iterator<TileConfig>(), std::back_inserter(tiles));
    }
    std::cout << "Read configs: " << std::endl;
    std::copy(tiles.begin(), tiles.end(), std::ostream_iterator<TileConfig>(std::cout, "\n\n"));     
}


wie gesagt wie du dann in dem überladenen stream-operator read/write händelst, ist dir überlassen ;) achja und mögen syntaktische fehler drin sein, ich prüf nicht was ich hier schreib.

(generell mal paar Infos über Streams: http://www.c-plusplus.de/forum/p1095570)
Devil Entertainment :: Your education is our inspiration
Der Spieleprogrammierer :: Community Magazin
Merlin - A Legend awakes :: You are a dedicated C++ (DirectX) programmer and you have ability to work in a team? Contact us!
Siedler II.5 RttR :: The old settlers-style is comming back!

Also known as (D)Evil

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »Deviloper« (30.01.2011, 04:13)


8

30.01.2011, 12:44

Vielen Dank für eure Hilfe, hat mir weitergeholfen :)

Werbeanzeige