PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wieder mal Textdateien ... C++


Ganon
2004-10-18, 18:27:36
Hi.

Ich muss mal wieder etwas mit Textdateien anstellen und zwar in C++.

Dabei habe ich mit dem Bearbeiten von Textdateien in C++ kaum Ahnung. OK. Auslesen und reinschreiben geht noch, in einem gewissen Rahmen, aber das was jetzt kommt weiß ich einfach nicht...

Könnt ihr mir da helfen?

Und zwar geht es darum:

Ich habe eine Textdatei in der Wörter untereinander stehen. So ca. 2000 Wörter.
Jetzt soll da durchnummeriert werden. Und zwar wie folgt:

z.B.

Wort1 :0001:
Hallo :0002:
Huhu :0003:
.
.
.hier stehen eine Menge Wörter
.
Wörter :0803:
.
.Hier auch viele Wörter
.
Ende :1638:

Also zwischen den Doppel-Punkten soll immer die Zeile stehen in der das Wort steht. Und zwar ab Spalte 71. Also das Wort kann von Spalte 1-70 gehen und dann von Spalte 71 bis 76 soll dann die Zahl samt Doppelpunkt stehen. Wenn die Zahl kleiner als 4 Stellen ist, dann muss mit Nullen aufgefüllt werden.

In den zu behandelnden Textdateien steht schon was drinnen, aber falsche Werte. Diese müssen deshalb korrigiert werden. Die falschen Zahlen stehen aber immer von Spalte 71-76.

Kann mir einer Helfen, wie man so etwas anstellt? Zur Verfügung steht Borland C++ Builder 6 Standard.

Ich wäre euch sehr Dankbar. :) Ich verzweifle hier nämlich schon.

Trap
2004-10-18, 19:08:03
Alles was du aus der Standardbibliothek brauchst ist:
ifstream
ofstream
getline
string::substr
setwidth
setfill

HellHorse
2004-10-18, 23:06:17
Muss es C++ sein?

import re, sys

if __name__ == "__main__":

line_number = 1

for line in sys.stdin.readlines() + ["Ende"]:

match = re.search(" :\d{4}:$", line.rstrip())

print "%s :%04d:" % ((match and [line[:match.start()]] or [line.rstrip()])[0], line_number)

line_number += 1

Falls eine Zeile von der Form
irgendetwas :vierstelligezahl:
ist. Wird
irgendetwas :zeilennummer:
ausgegeben, sonst
Zeileninhalt :zeilennummer:
ausgegeben, am Schluss
irgendetwas :Ende:
(habe nicht ganz geschnallt welche Zeilen schon Nummer haben und welche nicht)

Oh, habe ich schon erwähnt, dass ich ein python-n00b bin und jemand wie Xmas das vermutlich in der Hälfte Zeilen Code hinbekommt?

edit:
ich musste doch, dass es mit weniger Code und mehr obfuscation geht ;)

edit2:
ruby ;)

while gets do puts "%s :%04d:" % [$_.rstrip =~ / :\d{4}:$/ ? $` : $_.rstrip , $.] end

Ganon
2004-10-18, 23:40:29
Danke erst mal. :)

@HellHorse

Ja muss leider C oder C++ sein. Was anderes steht leider so nicht zur Verfügung... :(

Trap
2004-10-19, 09:36:33
Man kann das Python-Programm nahezu 1 zu 1 in C++ übersetzen, wenn man von www.boost.org die regex-lib benutzt.

Wenn man keine externe Lib benutzen will ist es auch nicht viel schwerer. Grade da die Spalten schon bekannt sind und man mit string::substr dann die Teile einfach trennen kann. Ich schreib dir aber keine fertige Lösung, auch wenn es nur 10 Minuten dauert...

Ganon@work
2004-10-19, 10:21:22
...ich schreib dir aber keine fertige Lösung, auch wenn es nur 10 Minuten dauert...

Ganz ruhig... ;) Ist ja schon fertig... Es funktioniert ja schon einigermaßen. Aber keine Ahnung ob alles aus der Standard-Bibliothek kommt. ;)

Ist halt nur schnell zusammengehackt. Mir fehlten ja auch nur die Befehle wie setfill, etc.

Der Code ist sicherlich ein Haufen schei**e, aber mit den Probe-Dateien funktioniert es erst mal. Ich muss aber noch dran arbeiten. Ist noch sehr fehleranfällig.

Wie gesagt. Mi Textdateien stehe ich auf Kriegsfuß. ;)


//---------------------------------------------------------------------------

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
#include <fstream>
#include <iostream>
#include <iomanip>
#include <istream>
#include <conio.h>
#include <cstdlib>
#include <sstream>

using namespace std;

int main(int argc, char* argv[])
{
/*
TODO:
- Prüfung ob wirklich alle Zeichen vorhanden sind
- Datei kopieren und entsprechend neue Datei mit angegebenen Namen, bzw.
Werte in Datei ersetzen
- aufräumen ;)
*/
fstream datei(argv[1]);
ofstream datei2(argv[2]);

if(!datei && !datei2)
{
cout << "Fehler beim Öffnen";
getch();
exit(1);
}

string s;
int b=0;
while(!datei.eof())
{
b++;
getline(datei,s);
string Zeile;
string Wort;
Wort = s.substr(0,69);
Zeile = s.substr(70,75);
stringstream Temp;
Temp << ':' << setw(4) << setfill('0') << b << ':';
Temp >> Zeile;
string Ges;
Ges = Wort + Zeile;
datei2 << Ges << "\n";
}
cout << "Fertig";
getch();
return 0;
}

Trap
2004-10-19, 11:36:12
So ähnlich hätte ich es geschrieben.

while(getline(datei,s)) ist besser weil es in allen Fällen die Schleife verlässt, deins nur beim erfolgreichen lesen der kompletten Datei.
Warum nicht direkt string Wort = s.substr(0,69);?
Oder beim stringstream: Temp << Wort << Rest; datei2 << Temp.str() <<"\n";

Außerdem benutzt du substr falsch, die Parameter sind start und länge, nicht start und ende.

Ganon@work
2004-10-19, 11:50:46
Ui,

danke für den Hinweis mit substr... :)

Klar kann man den Rest verkürzen, aber wie gesagt, das war nur ganz fix zusammengeschustert. ;)

Trap
2004-10-19, 12:01:38
Das getline solltest du auf jeden Fall in den Schleifenkopf schreiben, alles andere ist ein Bug der in einer Endlosschleife enden kann. Das ist nicht nur eine kürzere Schreibweise.

Ganon@work
2004-10-19, 12:03:29
Wird gemacht Chef! ;)

Ja, ist klar. Mach ich. :)

Ganon
2004-10-19, 18:06:30
Hi.

So. Jetzt mal etwas entspannter ran gesetzt und noch mal geschrieben. :)


#include <fstream>
#include <iostream>
#include <iomanip>
#include <sstream>

using namespace std;

#define WORTLAENGE 70
#define ZEILENZAHLLAENGE 4

int main(int argc, char* argv[])
{
fstream QuellDatei(argv[1]);
ofstream SavDatei(argv[2]);

if(!QuellDatei || !SavDatei)
{
cout << "Fehler beim Oeffnen" << endl;
exit(1);
}

// Datei bearbeiten
string s;
int ZeileNum=0;
while(getline(QuellDatei,s))
{
ZeileNum++;
string Wort = s.substr(0,WORTLAENGE);
stringstream Temp;
Temp << setw(WORTLAENGE) << setfill(' ') << setiosflags(ios::left) << Wort
<< ':' << setw(ZEILENZAHLLAENGE) << setfill('0')
<< setiosflags(ios::right) << ZeileNum << ':';
SavDatei << Temp.str() << "\n";
}
cout << "Fertig" << endl;
return 0;
}


Wie ist das vom Ablauf her? Das hier ist nicht mehr ganz so Fehleranfällig. Ich kloppe die Werte einfach so in die Datei wie mir gesagt wurde. ;)

substr scheint nur so viel einzulesen, wie es auch Zeichen gibt. Weil s ist immer so groß wie auch das Wort. Finde ich nicht schlecht. ;)