aus Textdatei ins Array schreiben



  • Hallo,

    ich möchte aus einer Textdatei, wo Umfrageergebnisse aufgefasst sind, diese in eine Array speichern. Ich habe bereits alle Zeichen in einer Array speichern können. Nur unsortiert. So sieht mein Array derzeit aus. Es sind alles Zeichen hintereinander abgelegt.
    knoblauch,y,n,y,n,y,y,n,n,y,nmeiermann,y,n,y,n,n,n,n,y,y,y
    Nun möchte ich die Antworten von knoblauch (j=1) und meiermann (j=2) unterscheiden und passend zu deren Antworten in ein Array (array[10][2]) speichern. Ich muss also irgendwie erkennen, welches Zeichen im Array steht und dann dieses in das Array speichern. Außerdem muss ich die Namen auseinanderhalten. Geht´s das so? Und wie? Bitte um Eute Hilfe.

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    int main() {
    
    	char array[10][2];
    	char daten[58];
    	int i;
    
    	fstream objekt;
    
    	objekt.open("daten.txt");
    
    	for(i=0;i<58;i++)	{
    			objekt>>daten[i];
    	}
    
    	for(i=0;i<58;i++)	{
    			cout<<daten[i];
    	}
    
    	return 0;
    }
    


  • Äh was??
    was ist j? was ist knoblauch? Erlär mal bitte was du in welcher Form einlesen willst und was du damit machen willst.



  • Du kannst ein csv format benutzen. Da wird dann auch von vielen anderen produkten erkannt (OO Calc) ...
    http://en.wikipedia.org/wiki/Comma-separated_values

    dazu kannst du die Werte mit komma bzw. Semikolon trenne.
    Die Namen staenden dann jeweils am anfang einer Zeile bis zum ersten Komma.

    Benutze std::endl um eine neue Zeile zu beginnen.



  • Ok, ich habe eine Textdatei. Hier sind Ergebnisse einer Umfrage vermerkt. Zwei Befragte sind knoblauch (1) und meiermann (2). Es sind zehn Fragen gestellt worden, die immer mit ja 👍 und nein (n) beantwortet wurden. Um nun Wahrscheinlichkeiten auszurechnen brauche ich die Daten sortiert. Ich dachte hierzu ist ein Array sinnvoll. Mit einem zweidim. Array kann ich jede Antwort exakt einem Befragten zuordnen. Z. B. array[1][1] würde die erste Antwort von knoblauch speichern (y), array[1][2] speichert die von meiermann (y). So kann ich später mathematisch berechnen lassen, wie die Ergebniss prozentual aussehen.
    Mein Problem ist, wie bekomme ich die Daten aus der Textdatei in so ein zweidim. Array? Als vielleicht ersten Schritt habe ich die Daten hintereinander in ein Array gespeichert. Ich weiß jedoch noch nicht, ob dies sinnvoll gewesen ist. Denn ich weiß nicht, wie ich jetzt erkennen soll, wer hat was geantwortet und wie speicher ich es ab?



  • Ich würde die Daten einfach in einen std::vectorstd::string schreiben und danach diesen mit substr bearbeiten und die entsprechenden Sachen ausrechnen.


  • Mod

    2D-Arrays sind fast nie eine gute Antwort auf ein Problem. Aber ich sehe deine Schwierigkeit nicht, zeig mal deinen Ansatz und warum es nicht geht. Weiterhin wäre noch interessant zu wissen, wie die Daten genau in de Datei stehen? Sind da Kommas zwischen den Werten? Leerzeichen? Gar nichts?

    Insgesamt würde sich aber wohl eher eine map<string, antworten> anbieten, wobei antworten eine irgendwie der Problemstellung angepasste Datenstruktur ist. Das kann intern meinetwegen auch ein (1D) Array sein, wobei ich dies jedoch unflexibel fände.



  • SeppJ schrieb:

    Insgesamt würde sich aber wohl eher eine map<string, antworten> anbieten, wobei antworten eine irgendwie der Problemstellung angepasste Datenstruktur ist. Das kann intern meinetwegen auch ein (1D) Array sein, wobei ich dies jedoch unflexibel fände.

    Ich denke ein vector<frage>, wobei frage hat o..n antwort ist sinnvoller, da so ganz einfach seine Prozente zu berechnen sind. Aber vielleicht ist ja auch das "Wer hat geantwortet" interessant... man weiß es nicht....
    Die eigentliche Frage war ja aber das Einlesen. Darauf kann man nur sinnvoll antworten, wenn man mal socleh Daten zu sehen bekäme.



  • Hallo c++anf,

    Willkommen im C++-Forum.

    Aus Deinen Ausführungen schließe ich, dass Du eine Datei hast, deren Inhalt etwa so aussieht.

    knoblauch,y,n,y,n,y,y,n,n,y,n
    meiermann,y,n,y,n,n,n,n,y,y,y
    huber,y,n,y,y,n,n,n,y,n,y
    

    Du möchtest jetzt die Namen der Personen und deren Antworten lesen. Dazu empfehle ich zunächst eine Struktur, die die Antworten genau einer Person enthält. Im einfachsten Fall sieht das so aus

    struct AntwortenProPerson
    {
        std::string m_person;
        std::vector< bool > m_antworten;
    
        static int const N = 10; // Anzahl der Antworten hier festlegen
    };
    

    nutze bitte std::string für Zeichenketten (also den Namen) und die STL-Container für dynamische Array (hier die Antworten) - das macht in C++ vieles leichter und bewahrt Dich vor Fehlern. Du brauchst dafür die Header <string> und <vector>.

    Um so eine Struktur einzulesen, baue man sich einen sogenannten Streaming-Operator

    std::istream& operator>>( std::istream& in, AntwortenProPerson& a );
    

    danach wird dann folgender Code möglich

    AntwortenProPerson a;
        objekt >> a; // die Antworten einer Person einlesen
    

    dazu braucht man den Header <iostream>.
    Wie man so einen Streaming-Operator implementiert, dafür gibt es hier im Forum etliche Beispiele; ist aber nicht leicht, das passende zu finden.

    Hier mal der ganze Code inklusive der Fehlerbehandlung

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    
    struct AntwortenProPerson
    {
        std::string m_person;
        std::vector< bool > m_antworten;
    
        static int const N = 10; // Anzahl der Antworten hier festlegen
    };
    
    template< char C >
    std::istream& Char( std::istream& in )
    {
        char c;
        if( in >> c && c != C )
            in.setstate( std::ios_base::failbit );
        return in;
    }
    
    // --   hier werden die Antworten einer Person eingelesen
    std::istream& operator>>( std::istream& in, AntwortenProPerson& a )
    {
        getline( in, a.m_person, ',' ); // der Name der Person wird durch das erste Komma beendet
        a.m_antworten.resize( AntwortenProPerson::N );
        for( int i = 0; i < AntwortenProPerson::N; ++i ) // lese N Antworten
        {
            if( i > 0 ) // erstes Komma wurde bereits mit getline(..,',') gelesen (s.o.)
                in >> Char<','>;
            char ja_nein;
            if( in >> ja_nein )
            {
                if( ja_nein == 'y' ) // || ja_nein == 'Y' || ja_nein == 'j' ..
                    a.m_antworten[i] = true;
                else if( ja_nein == 'n' )
                    a.m_antworten[i] = false;
                else
                {
                    // Lesefehler
                    in.setstate( std::ios_base::failbit );
                    return in;
                }
            }
        }
        return in;
    }
    
    int main()
    {
        using namespace std;
        vector< AntwortenProPerson > umfrage;
        ifstream objekt("daten.txt");
        if( !objekt.is_open() )
        {
            cerr << "Fehler beim Oeffnen der Datei" << endl;
            return -1;
        }
        for( AntwortenProPerson a; objekt >> a; )   // Lese bis Fehler oder Ende
            umfrage.push_back( a );
        if( !objekt.eof() )
        {
            cerr << "Fehler beim Lesen der Datei" << endl;
            return -1;
        }
        // ..   alles klar, Ergebnis steht in 'unfrage'
    
        return 0;
    }
    

    Gruß
    Werner



  • Besten Dank für Eure Hilfen.
    Auch ich habe nochmal mein Glück versucht. Der folgende Code trennt mir Person und Antwort, wie gewollt. Dann wollte ich i=1 für eine y-Antwort setzen. Aber da pch ein Zeiger ist, funktioniert dies nicht korrekt. Könnte so ein Vergleich denn so funktionieren? Wie gesagt, ich bin ein Anfänger, der gern immer dazulernen will.

    #include <stdio.h>
    #include <string.h>
    
    int main ()
    {
      char str[] ="democrat,y,n,y,n,y,n";
      char * pch;
      //int i=0;
    
      pch = strtok (str," ,.-");
      while (pch != NULL)
      {
        printf ("%s\n",pch);
        //if (pch=='y')
        	//i=1;
        pch = strtok (NULL, " ,.-");
      }
    
      return 0;
    }
    


  • In deinem Fall nimmst du **pch == 'y'*, damit holst du dir das Zeichen, auf das pch zeigt und vergleichst es mit 'y'. Wenn du eine Zeichenkette vergleichen willst nimmst du strcmp(pch, "y") == 0 , wichtig ist hier y auch als Zeichenkette anzugeben.
    Aber eigentlich willst du mit dem Code ins C-Forum verschoben werden. Wenn wir bei C++ bleiben, dann ist std::string dein Werkzeug. Damit entfällt dann auch die Unterscheidung in Zeichen und Zeichenkette, du hast dann nur noch Texte.



  • c++anf schrieb:

    ... ich bin ein Anfänger, der gern immer dazulernen will.

    das ist gut; nur wenn Du was in C++ dazu lernen möchtest, so solltest Du Dich umgehend von <stdio.h> <string.h> strtok und printf trennen.

    PS.: was macht eigentlich strtok?



  • Werner Salomon schrieb:

    was macht eigentlich strtok?

    Damit werden Strings an Trennzeichen aufgetrennt. In der Man-Page steht aber, man solle lieber strsep() nutzen. Was den negativen Nebeneffekt hat den Ausgangsstring zu bearbeiten und die Trennzeichen mit '\0' ersetzt.



  • Nick Unbekannt schrieb:

    Werner Salomon schrieb:

    was macht eigentlich strtok?

    Damit werden Strings an Trennzeichen aufgetrennt. In der Man-Page steht aber, man solle lieber strsep() nutzen. Was den negativen Nebeneffekt hat den Ausgangsstring zu bearbeiten und die Trennzeichen mit '\0' ersetzt.

    .. Hm!? wenn ich bei www.cplusplus.com nach strsep suche, so kommt ein:

    No results found for 'strsep'

    was will uns das wohl sagen?



  • Werner Salomon schrieb:

    was will uns das wohl sagen?

    Das deine Quelle nicht aktuell ist!

    http://linux.die.net/man/3/strsep


  • Mod

    Nick Unbekannt schrieb:

    Werner Salomon schrieb:

    was will uns das wohl sagen?

    Das deine Quelle nicht aktuell ist!

    http://linux.die.net/man/3/strsep

    Oje. Selfowned kann man da wohl nur sagen. Ich vermute mal, dies war es auch, worauf Werner Salomon hinaus wollte.



  • SeppJ schrieb:

    Nick Unbekannt schrieb:

    Oje. Selfowned kann man da wohl nur sagen. Ich vermute mal, dies war es auch, worauf Werner Salomon hinaus wollte.

    😕

    Die Datei string.h ist auf cplusplus.com sehr wohl vorhanden. Ich weiß jetzt nicht worauf ihr hinaus wollt?


  • Mod

    🙄 strsep ist kein Standard C++. Das ist ein spezieller Befehl der in der C Runtime von POSIX verfügbar ist. Das steht auch klipp und klar auf den selber von dir verlinkten Seiten. Und dann anderen vorzuwerfen, dass ihre Quellen veraltet sind ist schon dreist, wenn man selber falsche Quellen benutzt und es noch nicht einmal merkt.



  • Darauf habe gar nicht geachtet, sonst hätte ich auch nicht gefragt. Man kann aber auch die Leute richtig darauf hinweisen und sich nicht nur feixend in die Ecke stellen, was ich nun wieder dreist finde. Und wenn man schon so korrekt sein möchte, dann steht dort BSD und nicht POSIX.
    Und wenn man sich so umsieht, dann scheint die Funktion bei den meisten vorhanden zu sein. Vielleicht nicht bei MS, aber da ist ja so einiges anders.



  • Hallo Nick Unbekannt,

    Entschuldigung, ich wollte niemandens Unmut erregen. Das war nicht meine Absicht.

    Mich nervt es, dass bei Threads dieser Art immer wieder in die Kerbe 'lese den Text und interpretiere ihn mit String-Funktionen' geschlagen wird.

    Es ist ja völlig ok, dass ein Anfänger fragt wie man die Info aus einer Datei in ein C++-Programm bekommt. Aber es ist traurig, jedes mal diese Ignoranz der dann antwortenden gegenüber den C++-Streams mit anzusehen. Und das von Leuten, denen ich durchaus Erfahrung in der C++-Programmierung unterstelle. Irgendjemand fängt an und schon wird über strtok & Co diskutiert, wo Du völlig korrekt auch noch erwähnst

    Nick Unbekannt schrieb:

    In der Man-Page steht aber, man solle lieber strsep() nutzen.

    .. aus diesen und anderen Gründen ist mal C++ erfunden worden!

    Es ist doch Fakt dass:
    1.) wir hier C++ machen (neuerdings auch C++0x) so steht's in der Überschrift
    2.) die Ein-Ausgabe in C++ über Streams läuft - und zwar ausschließlich über Streams

    istreams können char, int, double, Komma-Zeichen und strings lesen und man kann ihnen auch beibringen, Antworten zu lesen , die aus 'y' oder 'n' bestehen. Also warum das nicht nutzen.

    Jemand der in C++ mit (C-)String-Funktionen versucht, die Eingabe zu interpretieren, ist in meinen Augen wie jemand, der sich zum ersten Mal ein großes Auto kauft, damit in Urlaub fährt und sich sein Gepäck mit der Bahn nachschicken lässt. Nach dem Motto: das hat früher doch auch gut funktioniert - ohne Auto.

    Ich hatte heute nachmittag mal keine Lust, darauf wieder mal hinzuweisen, sondern habe einfach 'blöde Fragen' gestellt. Das Du den Fettnapf gefunden hast, war reiner Zufall 😉

    Gruß
    Werner



  • Das ist genau mein reden, siehe den Post vor deinem. Sich über das Missverständnis zu ärgern, dass ist die Mühe nicht wert. Auch für SeppJ nicht.
    Ich fand deine Frage nur seriös genug, um darauf zu antworten.


Log in to reply