Schwierige Aufgabe :(?
-
Danke für die schnelle Antwort zur solch später Stunde.
Nein,Die Position ist egal nur die Reihe nicht...
-
Misha schrieb:
Danke für die schnelle Antwort zur solch später Stunde.
Nein,Die Position ist egal nur die Reihe nicht...ja, dann musst Du Matched::operator() noch anpassen. Ich geh' jetzt in's Bett!
Gute Nacht :xmas1:
-
Werner Salomon schrieb:
Misha schrieb:
Danke für die schnelle Antwort zur solch später Stunde.
Nein,Die Position ist egal nur die Reihe nicht...ja, dann musst Du Matched::operator() noch anpassen. Ich geh' jetzt in's Bett!
Gute Nacht :xmas1:
Edit:
Das heist :Wenn X oder mehr Zahlen aus Liste B Reihe 1 zur Liste A reihe 1 passen soll diese Reihe(Liste A Reihe 1) gelöscht werden, dann wird mit Liste B reihe 1 bei Liste A reihe 2 weiter gemacht, ist die Liste A durch ,so wird Liste B reihe 2 vorgenommen...
-
...hmm eh länger ich dies angucke desto weniger verstehe ich das Pragramm, könntest du vielleicht es so kommentieren das auch ein Misha das versteht?
Ich habe bisschen gegoogelt und nachgeschlagen aber mein Kopf ist zu klein für so viele neue Funktionen...hab kein plan wie ich jetzt die Listen in a und b reinbekommen kann
meine textdateien sind so geschrieben worden
12,15,11,83,26,83,44,18,58,54,
51,64,1,35,67,21,83,77,11,56,
.....(also immer 10 Zahlen von einem Komma getrennt)
Ich dachte mir man könnte Irgendwie immer 10 Zahlen nehmen und den Umbruch weglassen ...
habs in BASIC erstellt falls ein anderes Verfahren zur Speicherung von Zahlen für das obig genannte Beispiel sich besser eignet...höre ich zu.
Danke nochmal, ihr seid echt Freaks um Mitternacht noch in Foren zu sitzen
...also meine Frage:Wie kann mann 2 Listen voller Zahlen (in .txt) die nur Durch Kommas getrennt sind in den obigen Lösungsvorschlag von Werner Solomon reinbringen,
Es ist so das eine Reihe immer aus 10 Zahlen Besteht
Danke im Vor-raus
-
Misha schrieb:
...hmm eh länger ich dies angucke desto weniger verstehe ich das Pragramm, könntest du vielleicht es so kommentieren das auch ein Misha das versteht?
Da wir Misha nicht kennen, weiß auch niemand wo man mit dem Erklären anfangen soll. Es wäre extrem hilfreich, wenn Du konkrete Fragen stellst.
Misha schrieb:
.. hab kein plan wie ich jetzt die Listen in a und b reinbekommen kann

meine textdateien sind so geschrieben worden
12,15,11,83,26,83,44,18,58,54,
51,64,1,35,67,21,83,77,11,56,
.....(also immer 10 Zahlen von einem Komma getrennt)Ok, das ist 'ne einigermaßen konkrete Frage.
Erstmal vorneweg eine Bemerkung. Diese Kommas machen immer nur Arbeit. Ich weiß nicht wer sich sowas ausdenkt; es wäre sehr viel einfacher die Zahlen einfach durch Leerzeichen und/oder Zeilenumbruch zu trennen.
Einlesen geht so
#include <iostream> #include <fstream> #include <vector> #include <algorithm> // remove_if, find_if #include <utility> // std::pair typedef std::vector< int > Reihe; typedef std::pair< std::vector< int >, int > ReiheZ; // -- folgendes Graffi ist nur für das trennende Komma const int KOMMA_FLAG = std::ios_base::xalloc(); std::istream& komma( std::istream& in ) { if( in.iword( KOMMA_FLAG ) ) { char k; if( in >> k && k != ',' ) in.setstate( std::ios_base::failbit ); } else { in.iword( KOMMA_FLAG ) = 1; } return in; } std::istream& start_reading( std::istream& in ) { in.iword( KOMMA_FLAG ) = 0; return in; } // -- jetzt kommt das Einlesen einer Reihe mit 10 Zahlen namespace std // das ist beim VC-Compiler notwendig, da er den namespace lookup nicht korrekt beherrscht { std::istream& operator>>( std::istream& in, Reihe& r_ ) { Reihe r( 10 ); for( Reihe::iterator i = r.begin(); i != r.end(); ++i ) { in >> komma >> *i; } if( in ) r.swap( r_ ); return in; } // -- und hier das Einlesen der Reihe mit Zusatzzahl std::istream& operator>>( std::istream& in, ReiheZ& rz ) { Reihe r( 10 ); for( Reihe::iterator i = r.begin(); i != r.end(); ++i ) { in >> komma >> *i; } if( in >> komma >> rz.second ) r.swap( rz.first ); return in; } } int main() { using namespace std; std::vector< Reihe > a; std::vector< ReiheZ > b; { ifstream datei( "A.txt" ); copy( istream_iterator< Reihe >( datei ), istream_iterator< Reihe >(), back_inserter( a ) ); } { ifstream datei( "B.txt" ); copy( istream_iterator< ReiheZ >( datei ), istream_iterator< ReiheZ >(), back_inserter( b ) ); } // usw. return 0; }Misha schrieb:
Danke nochmal, ihr seid echt Freaks um Mitternacht noch in Foren zu sitzen

.. sonst habe ich ja keine Zeit für sowas

Gruß
Werner
-
Danke,Danke, Danke das du mich nicht vergessen hast.(hab sogar versucht den Thread zu Pushen ^^,geht leider nicht,er ist festgewachsen)
So und jetzt kommt die traurige Wahrheit:
Ich hab nicht den geringsten Peil
Wenn ich deinen Code lese macht es einfach keinen *Klick* im meinem Kopf
und die Suche nach den einzelnen Begriffen(was sie bringen usw.)hat mir nur noch mehr Kopfschmerzen bereitet.
Ich habe deine beide Codeteile irgendwie zusammengebaut(besser gesagt : "geschändet" )
Aber ich bin mir 100% sicher das ich das falsch gemacht hab:
Ich schätze deine Bemühungen sehr, aber dein C++ ist zu hoch für meinen Kopf,
(eigentlich C++ im allgemeinem,ader das wird mir erst jetzt klar)
Darum meine Bitte: Könntest du mir bitte,bitte den GANZEN Code aufschreiben?
Folgende Änderungen wurden an den Listen vorgenommen:
Die Zahlen sind jezt durch Leerzeichen getrennt und die Reihen durch Umbrüche
so etwa:
1 2 3 4 5 6 7 8 9 0
1 2 3 4 5 6 7 8 9 0
Es sind immernoch immer 10 Zahlen pro Reihe
Sorry nochmal für die Umstände aber ich bin mehr ein Plankton als ein Homo Sapiens Sapiens.
Ich will jetz blos das ganze hinter mich bringen und wieder mit dem Thema anfangen wenn ich C++ einigermaßen beherrsche.~absolute ultra low skilled beginner alias: Misha
-
Hallo Misha,
ich hab' im Augenblick kein Zeit. Ich werde versuchen Dir innerhalb der nächsten Woche zu antworten.
Gruß
Werner
-
OK,danke, kein Problem, ich warte.
-
Misha schrieb:
Ich hab nicht den geringsten Peil

Wenn ich deinen Code lese macht es einfach keinen *Klick* im meinem Kopf
und die Suche nach den einzelnen Begriffen(was sie bringen usw.)hat mir nur noch mehr Kopfschmerzen bereitet.Hallo Misha,
ich kann mich nur wiederholen: Stelle konkrete Fragen; meinetwegen auch zu einzelnen Programmzeilen. Abgesehen davon; wenn Du nicht 'den geringsten Peil' hast, wie kommst Du dann zu so einem - keineswegs trivialen - Programmier-Problem? Du solltest Dich mindestens mit der Anwendung des Containers vector<> aus der STL und rudimentärem IO in C++ auskennen, um das zu lösen.
Misha schrieb:
Ich habe deine beide Codeteile irgendwie zusammengebaut(besser gesagt : "geschändet" )
Aber ich bin mir 100% sicher das ich das falsch gemacht hab:Funktioniert es denn? Falls nicht, wo liegt das Problem? Auch hier würden Dich konkrete Angaben von Deiner Seite weiterbringen. In welcher Programmier-Umgebung arbeitest Du?
Misha schrieb:
Darum meine Bitte: Könntest du mir bitte,bitte den GANZEN Code aufschreiben?
Kommt hier:
#include <iostream> #include <fstream> #include <vector> #include <algorithm> // remove_if, copy, find_if #include <iterator> // std::o/istream_iterator<> class Reihe // dass ist eine Reihe mit 10 Zahlen { public: static const int ANZ = 10; // falls das nicht compiliert nehme: enum { ANZ = 10 }; typedef const int* const_iterator; const_iterator begin() const { return m_zahlen; } const_iterator end() const { return m_zahlen + ANZ; } friend std::istream& operator>>( std::istream& in, Reihe& r ) { // lese ANZ Zahlen nach r.m_zahlen[] for( int i = 0; i < ANZ; ++i ) in >> r.m_zahlen[i]; return in; } friend std::ostream& operator<<( std::ostream& out, const Reihe& r ) { // Ausgabe aller Zahlen der Reihe nach 'out' mit " " getrennt std::copy( r.begin(), r.end(), std::ostream_iterator< int >( out, " " ) ); return out; } private: int m_zahlen[ANZ]; }; class ReiheZ // das ist eine Reihe mit Zusatzzahl { public: typedef Reihe::const_iterator const_iterator; const_iterator begin() const { return m_reihe.begin(); } const_iterator end() const { return m_reihe.end(); } int N() const { return m_n; } friend std::istream& operator>>( std::istream& in, ReiheZ& rz ) { // Einlesen einer Reihe 'rz.m_reihe' und Zusatzzahl 'rz.m_n' return in >> rz.m_reihe >> rz.m_n; } private: Reihe m_reihe; int m_n; // Mindestanzahl der Zahlen, die in der zu prüfenden Reihe vorkommen müssen, um sie zu löschen }; struct Matched { explicit Matched( const Reihe& ra ) : m_ra( ra ) {} bool operator()( const ReiheZ& rb ) const { // Hier findet jetzt die Überprüfung statt, ob die Reihe, deren Kopie sich // in 'm_ra' befindet, gelöscht werden soll. // Das ist genau dann der Fall, wenn mindestens 'rb.N()' Zahlen aus 'm_ra' // auch in 'rb' vorkommen. // In diesem Fall wird 'true' zurückgeliefert. int cnt = 0; for( Reihe::const_iterator ia = m_ra.begin(); ia != m_ra.end(); ++ia ) // alle Zahlen in m_ra { // kommt die Zahl '*ia' aus 'm_ra' in 'rb' vor? if( std::find( rb.begin(), rb.end(), *ia ) != rb.end() ) { // .. ja, die Zahl '*ia' wurde in 'rb' gefunden if( ++cnt >= rb.N() ) { // es wurden 'rb.N()' Zahlen aus 'm_ra' in 'rb' gefunden return true; } } } return false; } private: Reihe m_ra; }; struct Entscheider { explicit Entscheider( const std::vector< ReiheZ >& b ) : m_b( &b ) {} bool operator()( const Reihe& r_aus_a ) const { // true; falls irgendeine Reihe aus B die aktuelle Reihe 'r_aus_a' aus A löscht return std::find_if( m_b->begin(), m_b->end(), Matched( r_aus_a ) ) != m_b->end(); } private: const std::vector< ReiheZ >* m_b; }; int main() { using namespace std; const char* aName = "A.txt"; const char* bName = "B.txt"; const char* ergName = "Aneu.txt"; std::vector< Reihe > a; // alle Reihen std::vector< ReiheZ > b; // alle Reihen mit Zusatzzahl { ifstream datei( aName ); // Reihen einlesen und in Container 'a' speichern copy( istream_iterator< Reihe >( datei ), istream_iterator< Reihe >(), back_inserter( a ) ); cout << a.size() << " Reihen aus '" << aName << "' gelesen " << endl; } { ifstream datei( bName ); // Reihen mit Zusatzzahl einlesen und in Container 'b' speichern copy( istream_iterator< ReiheZ >( datei ), istream_iterator< ReiheZ >(), back_inserter( b ) ); cout << b.size() << " Reihen mit Zusatzzahl aus '" << bName << "' gelesen " << endl; } // alle Reihen aus 'a' entfernen, die dem Kriterium entsprechen a.erase( remove_if( a.begin(), a.end(), Entscheider( b ) ), a.end() ); ofstream erg( ergName ); // Ergebnis nach 'erg' schreiben; nach jeder Reihe ein 'newline' "\n" copy( a.begin(), a.end(), ostream_iterator< Reihe >( erg, "\n" ) ); cout << a.size() << " Reihen nach '" << ergName << "' geschrieben " << endl; return 0; }Wobei noch zu erwähnen ist, dass ich den Algorithmus dahingehend geändert habe, dass ich nur einmal über alle Reihen aus A laufe; das geschieht in
remove_if( a.begin(), a.end(), ...und dann für eine bestimmte Reihe aus A in allen Reihen aus B nachsehen ob eine passt. das geschieht hier
bool Entscheider::operator()( const Reihe& r_aus_a ) const { // true; falls irgendeine Reihe aus B die aktuelle Reihe 'r_aus_a' aus A löscht return find_if( m_b->begin(), m_b->end(), Matched( r_aus_a ) ) != m_b->end();Und ob eine Reihe passt (matched) oder nicht entscheidet sich in Matched (s.Code)
Weiter habe ich Reihe und ReiheZ als eigenständige Klassen definiert; das ist sauberer als die erste Lösung mit den typedefs.
Sei der Inhalt der Datei A.txt
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 60und von B.txt
1 2 3 11 12 13 99 99 99 99 3 51 62 99 99 99 99 99 99 99 99 1Dann erzeugt das Programm eine Datei Aneu.txt mit diesem Inhalt
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 50Gruß
Werner
-
Es gibt noch eine Optimierungsmöglichkeit bei der main-Funktion. Misha wird's wohl nix nützen, aber vielleicht interessiert sich jemand dafür.
main() optimiert:
int main() { using namespace std; const char* aName = "A.txt"; const char* bName = "B.txt"; const char* ergName = "Aneu.txt"; vector< ReiheZ > b; // alle Reihen mit Zusatzzahl { ifstream datei( bName ); // Reihen mit Zusatzzahl einlesen und in Container 'b' speichern copy( istream_iterator< ReiheZ >( datei ), istream_iterator< ReiheZ >(), back_inserter( b ) ); cout << b.size() << " Reihen mit Zusatzzahl aus '" << bName << "' gelesen " << endl; } ifstream a( aName ); ofstream erg( ergName ); // alle Reihen aus 'a' entfernen, die dem Kriterium entsprechen, und Rest nach 'erg' abspeichern remove_copy_if( istream_iterator< Reihe >( a ), istream_iterator< Reihe >(), ostream_iterator< Reihe >( erg, "\n" ), Entscheider( b ) ); return 0; }Gruß
Werner
-
@Werner
In diesem Fall spielt es keine Rolle, aber wenn möglich sollte man die range-insert Methoden eines Containers dem copy-Algo vorziehen. In diesem Fall muss man dann noch auf "c++'s most vexing parse" achten:ifstream datei( bName ); // man beachte die Extraklammern vector< ReiheZ > b( (istream_iterator< ReiheZ >( datei )), istream_iterator< ReiheZ >()); // oder besser: istream_iterator< ReiheZ > beg( datei ); vector< ReiheZ > b( beg, istream_iterator< ReiheZ >());
-
HumeSikkins schrieb:
In diesem Fall spielt es keine Rolle, aber wenn möglich sollte man die range-insert Methoden eines Containers dem copy-Algo vorziehen.
Hallo Hume,
Wohl dem, der eine Umgebung hat, wo das auch kompiliert.

Ich bin immer noch etwas MS-VC6-verseucht. Aber Du hast völlig recht.Gruß
Werner
-
Werner Salomon schrieb:
Wohl dem, der eine Umgebung hat, wo das auch kompiliert.

Ich bin immer noch etwas MS-VC6-verseucht. Aber Du hast völlig recht.Ah, fehlende Member-Templates in der Standardlib-Impl. Gute alte Zeiten

Hier ist ausnahmsweise mal nicht die schwache Template-Unterstützung des VC6 schuld (der VC6 unerstützt Member-Templates, sofern sie innerhalb der Klassendefinition definiert werden), sondern die Tatsache, dass für den VC6 keine neue Version der Dinkumware-Library lizenziert wurde. Stattdessen wurde eine alte Version (bereits seit dem VC4 dabei???), ohne solche "fancy features", mitgeliefert.Hm, aber warum langweile ich dich eigentlich damit...

-
Danke Werner!vielen dank!