Kopie eines Textes [geloest]



  • Hallöchen, nun bin ich beim Einlesen und Kopieren von Textdateien (Beispiel aus Buch). Das klappt alles wunderbar.

    Jetzt wollte ich (Eigeninitiative) die Anzahl Zeichen und Zeilen zählen und ausgeben.
    Ich kann beide Pfade eingeben und die Zeilen und Zeichen gibt er auch richtig aus, aber in die unbeschriebene txt-Datei wird nicht mehr kopiert.

    #include<iostream>
    #include<fstream>
    #include<string>
    
    int main()
    {
    	std::fstream quelle;
    	std::string quelldateiname;
    	std::cout << "Welche Datei soll geoeffnet werden?(ohne Lehrzeichen)\n";
    	std::cin >> quelldateiname; // Pfad der zu kopierenden Datei angeben
    	quelle.open(quelldateiname.c_str(), std::ios::binary|std::ios::in);
    	if(!quelle)
    	{
    		std::cerr << quelldateiname << " kann nicht geoeffnet werden!\n";
    		exit (-1);
    	}
    	char c;
    	unsigned long zeichenzahl = 0, zeilenzahl = 0;
    	while (quelle.get(c))
    	{
    		if (c == '\n')
    		{
    			++zeilenzahl;
    		}
    		else
    		{
    			++zeichenzahl;
    		}
    	}
    	std::string zieldateiname;
    	std::cout << "Zieldatei?(keine Lehrzeichen)\n";
    	std::cin >> zieldateiname; // Pfad angeben, in den kopiert werden soll
    	std::ofstream ziel(zieldateiname.c_str(), std::ios::binary|std::ios::out);
    	if(!ziel)
    	{
    		std::cerr << zieldateiname << " kann nicht geoeffnet werden!\n";
    		exit(-1);
    	}
    	char ch;
    	while(quelle.get(ch))
    		ziel.put(ch); // zeichenweise kopieren
    	std::cout << zeilenzahl << " " << zeichenzahl;
    
    	std::cin.get();
    	return 0;
    }
    

    Bitte um Hilfe.

    Eine Frage nebenbei, welche im Buch nicht beantwortet wird: Wieso ein

    exit(-1);
    

    und nicht

    exit(0);
    

    Danke im Voraus.

    MfG

    Stryke

    EDIT: Habe mir grade überlegt, die while-Schleife in die if(!ziel) zu setzen, möglich?
    EDIT 2: Dumme Idee hab ich mir grade gedacht xD brauch das net mal zu probieren 🙄



  • Ich vermute, du hast mit der ersten while-Schleife die Quelle schon komplett leergelesen (also dein Lesezeiger steht am Ende der Datei). Wenn du jetzt nochmal get() machst, woher sollte er wissen, dass er wieder von vorne beginnen soll?
    Entweder du machst die Quelle nochmal auf, setzt den Lesezeiger wieder nach vorne(seek() oder so ähnlich), oder du speicherst dir beim ersten durchlauf gleich den Inhalt (vermutlich das schönste)

    exit(x); heißt, du gibst an das aufrufende Programm x zurück. 0 wird dabei normalerweise als "Programm ist ohne Fehler gelaufen" interpretiert und alles != 0 als "Es ist ein fehler aufgetreten". Deshalb an der stelle exit(-1);


  • Mod

    In Zeile 40 wird die Eingabe immer fehlschlagen, da du in Zeile 12 bereits alles gelesen hast, was zu lesen war. Alternativen:
    1. Fehlerstatus zurück setzen (clear), an den Anfang springen (seekg), dann wie gehabt lesen
    2. Die Zeichen beim ersten Lesen irgendwo zwischenspeichern, z.B. in einem String.
    3. Gleich in einem Rutsch lesen, zählen, schreiben

    exit(-1) vs. exit(0): Die Zahl gibt den Rückgabewert an, den das Programm an die Umgebung liefern soll. Bei vielen Systemen steht 0 für erfolgreiche Ausführung und ungleich 0 für Fehler. Das ist zum Beispiel dann wichtig, wenn man Programme automatisiert verbindet (Batch-Datei), so dass spätere Programme nur ausgeführt werden, wenn die ersten richtig gelaufen sind. Die Bedeutung der 0 ist aber nicht einheitlich auf allen Systemen, daher sollte man richtiger die vordefinierten Konstanten EXIT_SUCCESS und EXIT_FAILURE aus cstdlib benutzen. Aber: exit solltest du in C++ sowieso nicht benutzen, da es den Stack nicht richtig aufräumt, was bei vielen typischen C++-Programmierstrukturen aber wichtig ist. Daher solltest du zum Beenden des Programmes, wenn du schon in der main bist, einfach ein return machen oder, wenn du irgendwo in einer anderen Funktion bist, eine Exception schmeißen.



  • DerBaer schrieb:

    Ich vermute, du hast mit der ersten while-Schleife die Quelle schon komplett leergelesen[...]

    Habe ich mir schon fast gedacht. 😕
    seek() bzw überhaupt etwas, was dem Code sagt er solle zurückgehen zu Punkt x kenne ich leider noch nicht. Hier wär eventuell ein bissel Erlärungsbedarf nötig 🙂

    DerBaer schrieb:

    exit(x); heißt, du gibst an das aufrufende Programm x zurück. 0 wird dabei normalerweise als "Programm ist ohne Fehler gelaufen" interpretiert und alles != 0 als "Es ist ein fehler aufgetreten". Deshalb an der stelle exit(-1);

    Ok Danke sehr 🙂 👍

    EDIT: Tut mir Leid SeppJ, habe deinen Post net mehr gesehen 😞
    Aber ist im Grunde ja das gleich wie beim baerchen 😉 😃



  • exit(-1);
    

    von 0 abweichende Fehlermeldungen sollten bearbeitet oder beachtet werden.

    In deinem Fall kann eine Datei nicht geöffnet werden. Deshalb Rückgabewert !=0.

    Wird aber nicht ganz einheitlich genutzt.

    Rückgabewert 0 gleich 0 Fehler bei der Ausführung sollte einfach zu merken sein.



  • Da fehlt:

    quelle.clear();
    	quelle.seekg(std::ios_base::beg);
    

    Wurde glaube ich schon erwähnt.
    In welchem Buch steht das mit dem exit(-1) und exit(0)?



  • out schrieb:

    Da fehlt:

    quelle.clear();
    	quelle.seekg(std::ios_base::beg);
    

    Wurde glaube ich schon erwähnt.

    Wundervoll, danke, klappt alles 😃
    Aaaaaber 😃 was ist der Unterschied zwischen dem vorigen "seek" zu dem jetzigen "seekg"? 😃
    Und "std::ios_base::beg" sagt einfach nur, zum Beginn der eingelesen Datei?

    out schrieb:

    In welchem Buch steht das mit dem exit(-1) und exit(0)?

    Breymann´s "Der C++ Programmierer"
    Ich sag mal, es wird nur kurz exit(int) erwähnt, warum aber in seinem Code dann -1 steht nicht. Hier ist es ja leicht die möglichen Fehler abzuzählen, aber bei etwas längerem Code nicht (also quasi von Hand)


  • Mod

    xStrykex schrieb:

    Aaaaaber 😃 was ist der Unterschied zwischen dem vorigen "seek" zu dem jetzigen "seekg"? 😃

    seekg gibt es, seek nicht.



  • Astrein, danke euch 😉



  • Möchte noch eine andere Lösung vorstellen. 🙂

    #include <algorithm>
    #include <iostream>
    #include <iterator>
    #include <fstream>
    #include <string>
    
    int main()
    {
    	std::cout << "Welche Datei soll geoeffnet werden?\n";
    	std::string datei;
    	std::getline( std::cin, datei ); // Dass es mit Leerzeichen auch geht.
    	std::ifstream quelle( datei.c_str() );
    	if( !quelle.is_open() )
    	{
    		std::cerr << datei << " kann nicht geoeffnet werden!\n";
    		return -1;
    	}
    	std::string inhalt( (std::istreambuf_iterator<char>(quelle)), (std::istreambuf_iterator<char>()) ); // Kompletter Dateiinhalt einlesen.
    	const unsigned zeilenzahl  = std::count( inhalt.begin(), inhalt.end(), '\n') +1; // +1, auch wenn es kein \n gibt, gibt es eine Zeile.
    	const unsigned zeichenzahl = inhalt.size()-zeilenzahl +1; // +1, weil eins zu viel subtrahiert wird, wegen dem +1 oben.
    
    	std::cout << "Zieldatei?\n";
    	std::getline( std::cin, datei ); // Dass es mit Leerzeichen auch geht.
    	std::ofstream ziel( datei.c_str() );
    	if( !ziel.is_open() )
    	{
    		std::cerr << datei << " kann nicht geoeffnet werden!\n";
    		return -1;
    	}
    	ziel << inhalt; // Datei kopieren
    
    	std::cout << zeilenzahl << " " << zeichenzahl;
    }
    


  • out schrieb:

    Möchte noch eine andere Lösung vorstellen. 🙂

    std::getline( std::cin, datei ); // Dass es mit Leerzeichen auch geht.
    

    Also kopieren tut er die Leerzeichen bei mir auch, oder was meinst du?

    out schrieb:

    if( !quelle.is_open() )
    	{
    		std::cerr << datei << " kann nicht geoeffnet werden!\n";
    		return -1;
    	}
    

    Bezweckt return -1 dasselbe wie exit(-1)?
    meine Annahme ist jetzt, dass exit nicht nur den Fehler zurückgibt, sondern auch das Programm schließt und return nicht.(?)

    😃


  • Mod

    xStrykex schrieb:

    Also kopieren tut er die Leerzeichen bei mir auch, oder was meinst du?

    Leerzeichen im Dateinamen.

    Bezweckt return -1 dasselbe wie exit(-1)?

    Jain. Ein return aus der main beendet die Funktion main und somit das Programm und gibt den Wert an die Systemumgebung zurück. Ein exit von irgendwoher beendet das Programm und gibt den Wert an die Systemumgebung zurück. Wie aber schon gesagt wurde, hat exit in einem C++-Programm eigentlich nichts zu suchen, weil es die Destruktoren der automatischen Variablen nicht abwickelt. Bei einem return aus main wird alles aus main sauber aufgeräumt. Das halte ich für einen großen Fehler in dem Buch, wenn dort wirklich exit mehr als nur eine Randnotiz ist. exit ist ein Überbleibsel aus der C-Standardbibliothek und ist bestenfalls für irgendwelche Quick&Dirty Schweinereien geeignet.



  • SeppJ schrieb:

    xStrykex schrieb:

    Also kopieren tut er die Leerzeichen bei mir auch, oder was meinst du?

    Leerzeichen im Dateinamen.

    Ah ok, das ist gut, danke 🙂

    SeppJ schrieb:

    xStrykex schrieb:

    Bezweckt return -1 dasselbe wie exit(-1)?

    Jain. Ein return aus der main beendet die Funktion main und somit das Programm und gibt den Wert an die Systemumgebung zurück. Ein exit von irgendwoher beendet das Programm und gibt den Wert an die Systemumgebung zurück. Wie aber schon gesagt wurde, hat exit in einem C++-Programm eigentlich nichts zu suchen, weil es die Destruktoren der automatischen Variablen nicht abwickelt. Bei einem return aus main wird alles aus main sauber aufgeräumt. Das halte ich für einen großen Fehler in dem Buch, wenn dort wirklich exit mehr als nur eine Randnotiz ist. exit ist ein Überbleibsel aus der C-Standardbibliothek und ist bestenfalls für irgendwelche Quick&Dirty Schweinereien geeignet.

    Ok, verstanden. 🙂
    Hab im Buch nochmal nachgeschaut und siehe da, es wird nochmal erklärt, aber leider erst 50-70 Seiten weiter. Gut, dass es euch gibt 😃
    Ich muss ja mal am Rande bemerken, dass dieses Forum (mir zumindest) zu einem großen Teil beim Lernen hilft. 👍 Mit bloßer Lektüre würde ich mit Sicherheit nicht so "schnell" vorranschreiten 😃


  • Mod

    xStrykex schrieb:

    Hab im Buch nochmal nachgeschaut und siehe da, es wird nochmal erklärt, aber leider erst 50-70 Seiten weiter.

    Gut 👍 . Das Buch wird hier sonst nämlich oft gelobt, ich war da jetzt ziemlich überrascht.


Anmelden zum Antworten