.log Sortieren ??
-
Hey,
ich hätte eine (C++) Frage zu folgender Problemstellung:
Eine *.log Datei (bzw *.txt) beinhaltet mehrere Zeilen mit Einträgen.
Die Struktur ist folgende..4.text text text
2.text text text
1.text text text
2.text2 text2 text2
10.text text textSprich, man hat Einträge, die mit vorangestellten Zahlen gekennzeichnet sind.
Ziel wäre es, diese Einträge einzulesen und nach Zahlen zu gruppieren.
Also, dass folgendes herauskommen sollte:
1.text text text
2.text text text
2.text2 text2 text2
4.text text text
10.text text textMir geht es zunächst einmal nur um die reine Theorie.
Welche Schritte sind auszuführen?
Gibt es da einen Sortieralgorithmus, a la QuickSort mit bestimmten Bedingungen oder ähnlichem??
-
Ich würde die Datei zeilenweise in einen vector<> einlesen, dann diesen sortieren (dafür brauchst du nur eine eigene Vergleichsfunktion, die deine Zahlengruppen auswertet und std::sort()) und wieder ausgeben.
-
Hi,
CStolls Vorschlag ist ein guter Einstieg, weil es erstmal das einfachste und überschaubarste ist.
Der Vollständigkeit halber: Sobald allerdings die Logfiles größer, die Suchkriterien komplizierter und die Performance wichtiger werden, kann das Ganze beliebig kompliziert werden.
Ein Arbeitskollege hier hatte derart hohe Flexibilitätsanforderungen, dass er boost::spirit zur Abbildung der Regeln brauchte und da es sich um bis zu 2 GB großen Logfiles handelte, musste auch statt eines "Alles-rein-Containers" auch ein anderes Konzept mit "Teilschritten" her....Langer Rede kurzer Sinn: Die eine Allgemeinlösung gibt es nicht - aber immer: keep as simple as possible.
Gruß,
Simon2.
-
Danke vielmals für die Vorschläge.
Jetzt liegts an mir, diese umzusetzen.
Bin ja eigentlich ein Netzwerktechniker, brauche jedoch ein solches Programm.
Naja, mal sehen, was nach meinem 2Wochen C++ Crashkurs so alles umsetzbar ist
Bin für alle weitere Vorschläge offen
-
.. wenn Du erst 2Wochen C++ hinter Dir hast, sollte man vielleicht noch erwähnen, dass der dritte Parameter von std::sort einen sogenannte Funktor aufnehmen kann, der Dir hier gute Dienste leistet.
Ein Funktor ist eine Klasse, mit einer Methode ohne Namen. Sieht so ausclass Compare // ein Funktor zum Vergleich zweier Texte { public: bool operator()( const std::string& text1, const std::string& text2 ) { if( /* text1 kleiner text2 */ ) return true; else return false; } };
Ein Objekt diesen typs kannst Du dann an std::sort übergeben. Also etwa
std::sort( von, bis, Compare() );
Zum Vergleich der Texte musst Du in Deinen Fall die Zahl am Anfang auslesen, dazu benutzt man in C++ die Klasse std::istringstream.
Eine alternative Lösung besteht darin die Zahlen gleich beim Einlesen des Log-Files zu speichern. Also etwa in einer Struktur
struct Zeile { int m_nummer; // Zahl am Anfang std::string m_restText; };
Das Prinzip mit sort und Funktor bleibt gleich, lediglich der Typ der verglichen wird, ändert sich von std::string nach struct Zeile.
Gruß
Werner
-
mhh.. klappt alles nicht so wirklich
-
Und wir sollen jetzt raten, was du geschrieben hast? Zeig doch einfach etwas Code - mit einer konkreten Frage (oder Compilermeldung), dann können wir auch weiterhelfen.
-
Nein, sollte keiner raten
Bastel ja noch
-
int main ( ) { int num; vector<string> vect; ifstream quelle; quelle.open("text.log", ios_base::in); // Datei öffnen if (!quelle){ // Datei nicht gefunden cerr << "no file available\n"; // Fehlerausgabe } else { quelle.getline (num, 4) // wie nun richtig an vector übergeben? (mit push_back)
so bin Mittag machen, Mahlzeit!
und danke für alles :p
-
Erstmal: getline() mit einem int zu verwenden geht schonmal nicht - die istream-Methode arbeitet mit char-Arrays, die globale Funktion mit strings.
Zweitens: getline() liest genau eine Zeile ein - um die gesamte Datei zu bekommen, mußt du es in einer Schleife aufrufen.
string zeile; while(getline(quelle,zeile))//das liest so lange, bis es auf Fehler bzw. EOF trifft vect.push_back(zeile);
Drittens: Ja, push_back() ist richtig.
-
beim getline wollte ich tricksen, aber hab gemerkt, dass es 1.nicht geht und 2.schwachsinn war - danke
edit// oja, bestens. hat soweit funktioniert
jetzt mach ich mich mal an das sortieren
-
#include <iostream> #include <string> #include <fstream> #include <vector> #include <algorithm> using namespace std; struct entry { int nr; string log; }; class Compare { public: bool operator()( const entry& en1, const entry& en2 ) { return en1.nr < en2.nr; } }; int main() { ifstream in("log.txt"); string buff; entry neueintrag; vector <entry> log; while(!in.eof()) { getline(in,buff,'.'); neueintrag.nr = atoi(buff.c_str()); getline(in,buff); neueintrag.log = buff; log.push_back(neueintrag); } in.close(); sort(log.begin(),log.end(),Compare()); for(unsigned i=0;i<log.size();i++) { cout << log[i].nr << " " << log[i].log <<endl; } cin.get(); return 0; }
-
ouh, sehr nice.
danke vielmals, war schon fast zu viel des guten..
funzt aber nicht zu 100%
ich bastel mal weiter
-
myFile.open schrieb:
funzt aber nicht zu 100%
wo ist denn das Problem?
Wenn Du fleißig übst, Dich auch in die Geheimnisse der STL einarbeitest, dann kannst Du bald auch solche Programme hinschreiben.
#include <iostream> #include <fstream> #include <string> #include <vector> #include <algorithm> // sort #include <iterator> // i/ostream_iterator<> struct entry { int m_nummer; std::string m_restText; }; // -- Entry lesen std::istream& operator>>( std::istream& in, entry& e ) { return std::getline( in >> e.m_nummer, e.m_restText ); } // -- Entry schreiben std::ostream& operator<<( std::ostream& out, const entry& e ) { return out << e.m_nummer << e.m_restText << std::endl; } class Compare { public: bool operator()( const entry& en1, const entry& en2 ) const { return en1.m_nummer < en2.m_nummer; } }; int main() { std::ifstream quelle( "log.txt" ); if( !quelle.is_open() ) { std::cerr << "Fehler beim Oeffnen der Datei" << std::endl; return -1; } std::vector< entry > log( (std::istream_iterator< entry >( quelle )), (std::istream_iterator< entry >()) ); std::sort( log.begin(), log.end(), Compare() ); std::copy( log.begin(), log.end(), std::ostream_iterator< entry >( std::cout ) ); return 0; }
Du siehst das Lesen, sortieren und ausgeben ist jeweils eine Zeile Code. Die kleinen Helferlein nicht mitgerechnet
Gruß
Werner
-
lässt sich aber leider nicht compilieren.
Hängt in der Zeilestd::vector< entry > log( (std::istream_iterator< entry >( quelle )), (std::istream_iterator< entry >()) );
(Compiler meldet Ausdruckssyntax)
-
lern_ender schrieb:
lässt sich aber leider nicht compilieren.
welchen Compiler benutzt Du?
falls es eine Version 6 einer bekannten großen Softwarefirma ist, so geht es nicht. Ändere dann die Zeile 41 nach
std::vector< entry > log; std::copy( (std::istream_iterator< entry >( quelle )), std::istream_iterator< entry >(), std::back_inserter( log ) );
Gruß
Werner
-
Ich würde nicht die Zeile ändern, sondern die Versionsnummer des Compilers ändern.
-
Artchi schrieb:
Ich würde nicht die Zeile ändern, sondern die Versionsnummer des Compilers ändern.
Würde ich ja gerne. Leider macht mein Chef da nicht mit.
Warum hat der BCB denn damit ein Problem ?
-
Weil er wahrscheinlich nicht gerade sehr ISO-C++-konform zu sein scheint. Verrate uns doch mal deinen Compiler und Versionsnummer...
-
Borland Builder 6 (Build 10.166)