Hab folgende Anforderung und stehe noch auf dem Schlauch...
Anforderung:
mehrere Textdateien zusammenfassen wobei die Texte so in die Zieldatei
übernommen werden daß zu jedem Zeilenanfang jeweils der ursprüngliche
Dateiname aufgeführt wird.
Beispiel:3 (bzw. x Files) einzelne Textdateien
Dateiname: ABC.TXT
Dateiinhalt:
24.05.1988 Tne.
Keine Info
27.08.1988 zweifach Frnt
Dateiname: 33TVB.TXT
Deateiinhalt:
30.01.2016 Follow up
1.05.2017 Tne.
Dateiname: X2789TLM.TXT
Dateiinhalt:
nicht verfügbar
Silverdot 246+!
27.6.1988 zweifach stint
Ergebnis Zusammenfassung in Neue Datei Output.TXT
Dateiname: Output.TXT
Dateiinhalt:
ABC.TXT 4.05.1988 Tne.
ABC.TXT Keine Info
ABC.TXT 27.08.1988 zweifach Frnt
33TVB.TXT 30.01.2016 Follow up
33TVB.TXT 1.05.2017 Tne.
X2789TLM.TXT nicht verfügbar
X2789TLM.TXT Silverdot 246+!
X2789TLM.TXT 27.6.1988 zweifach stint
Programmauswahl Parameter Abfrage
- Verzeichnis der Source Files
- Verzeichnis Target File
- Target File Name
Übernahme Parameter
- mit oder ohne Dateiname
- Falls ja Dateiname übernehmen Abfrage
- Startzeichen des Dateiname z.B. ab 2. Zeichen ect.
- Übernahme File extension J/N
Wenn ja mit dot Übernahme
Dank im voraus
Warum in C? Ist C Teil der Anforderung? Für solche Aufgaben eignet sich
jede Scriptsprache (Python, Perl, Matlab, Basic, Tcl) besser als C.
Schon allein wegen der Zeichensätze, die Textdateien haben können.
Wenn's in C sein muß: Versuch erst einmal ein Programm zu schreiben.
Funktionalitäten in Funktionen zusammenfassen. Nicht wie ein langes
Skript.
Es soll in C sein, wenn es mit den Zeichensätzen Probleme gibt dann muß
ich diese halt lösen bzw in der Parameterabfrage den Zeichensatz
vorgeben.
Der abgebildete Code funktioniert bereits nach Compilierung wenn die txt
Files und der outputfile im Programmverzeichnis liegen. Mit dem Code
lassen sich die Texte bereits aus verschiedenen Dateien in der
output.txt zusammenfassen.
Es fehlt
1. noch der Source Dateiname in den einzelnen Zeilen der output.txt
2. die Parameter Abfrage
3. Auswahl der Übernahme Parameter
Walter T. schrieb:> Warum in C? Ist C Teil der Anforderung? Für solche Aufgaben eignet sich> jede Scriptsprache (Python, Perl, Matlab, Basic, Tcl) besser als C.> Schon allein wegen der Zeichensätze, die Textdateien haben können.>> Wenn's in C sein muß: Versuch erst einmal ein Programm zu schreiben.> Funktionalitäten in Funktionen zusammenfassen. Nicht wie ein langes> Skript.
Es soll in C sein, wenn es mit den Zeichensätzen Probleme gibt dann muß
ich diese halt lösen bzw in der Parameterabfrage den Zeichensatz
vorgeben.
Der abgebildete Code funktioniert bereits nach Compilierung wenn die txt
Files und der outputfile im Programmverzeichnis liegen. Mit dem Code
lassen sich die Texte bereits aus verschiedenen Dateien in der
output.txt zusammenfassen.
Es fehlt
1. noch der Source Dateiname in den einzelnen Zeilen der output.txt
2. die Parameter Abfrage
3. Auswahl der Übernahme Parameter
Ja ist unter Linux aktuell Fedora 27
die einzelnen Dateinamen aufzulisten ist nicht das Ziel,
Ziel ist es die Source Dateinamen am Zeilenanfang der output.txt mit dem
Text auszugeben wie im Beispiel angegeben.
Wilfried G. schrieb:> Es soll in C sein
Warum? Ist es eine Hausaufgabe?
Wenn es ein ernsthaftes Programm ist, würde ich, bevor ich irgendeine
Funktionalität hinzufüge, erst einmal refaktorieren und das Ganze in
einzelne Funktionen aufteilen. Funktionieren hin oder her: Ich könnte
auf Anhieb noch nicht einmal sagen, ob die main() wirklich nie ein
Speicherleck produziert.
Walter T. schrieb:> Wilfried G. schrieb:>> Es soll in C sein>> Warum? Ist es eine Hausaufgabe?>> Wenn es ein ernsthaftes Programm ist, würde ich, bevor ich irgendeine> Funktionalität hinzufüge, erst einmal refaktorieren und das Ganze in> einzelne Funktionen aufteilen. Funktionieren hin oder her: Ich könnte> auf Anhieb noch nicht einmal sagen, ob die main() wirklich nie ein> Speicherleck produziert.
Hier mein Problem:
A) Einlesen erste Datei (1.Source)
Nimm Dateiname und schreibe ihn in ein File Namens output.a in erste
freie Zeile
Nimm den Dateiinhalt und schreibe ihn nach dem letzten bereits
vorhandenen Text mit vorangestellten Leerzeichen, bei
Zeilenüberlauf
beginne die Neue Zeile mit dem Dateinamen (1.Source) und ergänze
die
weitere Textübernahme
Das ganze sooft wiederholen bis der kompl. Texte von 1.Source nach
output.a übernommen wurde.
B) Einlesen der zweiten Datei (2.Source)
analog zu A)
C) usw. bis alle txt Dateien eingelesen wurden...
und nun zur Kernfrage wie bekomme ich den Dateinamen in das Targetfile
output.a?
Auch ich würde dir raten das nicht unbedingt in C zu machen, IMHO ist C
zwar immer noch eine wirkungsvolle Programmiersprache auch wenn es gerne
zu einer C Vs C++ Grundsatz Diskussion hier verkommt. Aber für dein
Anwendungsfall sind Script sprachen einfach das mittel der Wahl.
Wie auch immer wenn du auf C bestehst, solltest du Dein Programm in
Funktionen zerlegen und refaktorieren, hier ein paar Tipps
1.) Globale Variablen sind immer ein Anzeichen eines schwachen Design,
es gibt einige wenige ausnahmen, dein Programm tangiert keine davon, das
solltest du also schon mal ändern.
2.) Deine Variablen, entweder du nutzt Deutsche oder Englische Namen,
das Denglisch solltest du lassen, IMHO sollte man englische Bezeichner
wählen wenn das Projekt keine abweichenden Vorgaben hat, das macht es
den Internationalen Kollegen später leichter sich auf dein Programm zu
Konzentrieren. Auch die Bezeichnung deiner Variablen dient vorallen "to
confuse the Russian", hier mal meinen Senf dazu:
1
char*in_path="./inp/";// macht dein Code kaputt wenn es nicht mit Slash endet
2
char*out_path="./out/output.txt";// ist kein Path sondern eine Datei
3
intfd;// klingt nach lehrbuch aber da Du zwei davon hast würde ich die fdin und fdout nennen
4
intfd2;// Superidee den Input fd2 zu nennen das gibt ein richtigen Knoten im Kopf
5
ssize_tgelesen;// in english please
6
ssize_tschreiben;
7
charbuf[1];// XXX: Array von eins Why? das wäre ein char besser noch du machst es größter da zu nachher mehr.
3.) dein while (1) Konstrukt sieht wüst aus, zumal du mit den if dann
doch sofort den Exit definiert hast. darf ich vorschlagen das so zu
machen
1
while((infolder=readdir(dir))){;
2
if(strncmp(infolder->d_name,".",1)==0||
3
strncmp(infolder->d_name,"..",2)==0){
4
/* skipp current entry */
5
continue;
6
}
7
printf(" entry %s\n",infolder->d_name);
8
9
/* TODO append your code */
10
11
}
4.) für das zusammenbauen des Path aus in_path und infolder->d_name
solltest du eine Funktion schreiben, diese kann dann auch gleich noch
ein paar Plausibilität Prüfungen machen. Im ideal Fall guckst du dir
hierfür auch mal die Funktion snprintf und asprintf an, beide könnten
die Helfen dein String eleganter zu erstellen als dein strcat. Generell
gilt es bei C String Funktionen ohne Längen Prüfung zu vermeiden, also
strncat statt strcat und so weiter. Eine der größten Schwachen von C und
ein stetiger quell von Bufferoverflows sind diese nicht Längen
prüfenden Stringfunktionen.
5.) mit deinen do-while loop zum lesen und schreiben tust du deinen
System echt keinen gefallen.
1
2
do{
3
gelesen=read(fd,buf,1);
4
printf("buf = %s\n",buf);
5
6
schreiben=write(fd2,buf,1);
7
}while(gelesen>0);
Dein System ließt jedes mal einen kompletten Block a 4K oder so ein um
dort ein Byte raus zu Operieren dir es zu übergeben und dann schreibst
du wieder ein einzelnes Byte in eine andere Datei. das Heißt dein System
vollzieht für jedes einzelne Byte, 2 mal den Kontext switch zwischen
Userland und Kernel. Im worst case Flushed auch noch irgendwas den Read
cache und du ließt die Bytes aus dem Sektor der Datei vielfach.
Ich würde vermuten das Hier dein Code so schwach ist das dich jedes
script schneller ist. Gib deinen Buffer ( remember char *buf[1] ) etwas
mehr Größe und ließ die Dateien in größeren Blocken (1024 oder so), das
macht dein Code gleich viel Effizienter, allerdings heist das du musst
denn Teil etwas umstellen, zum Beispiel muss dein code damit klarkommen
das der letze readcall weniger als 1024 Bytes liefert.
imonbln schrieb:> [...]
Volle Zustimmung meinerseits! Das nenne ich mal eine zutreffende und
gleichzeitig geduldige Erklärung - das kommt schon an einen Karlheinz
Buchegger dran.
Bin ich eigentlich der einzige, der PNs vom TO mit dem gleichen Text wie
im Forum bekommt?
Walter T. schrieb:> imonbln schrieb:>> [...]>> Volle Zustimmung meinerseits! Das nenne ich mal eine zutreffende und> gleichzeitig geduldige Erklärung - das kommt schon an einen Karlheinz> Buchegger dran.>>> Bin ich eigentlich der einzige, der PNs vom TO mit dem gleichen Text wie> im Forum bekommt?
Ja, recht hat er, es hilft mir aber nicht das Problem zu lösen, PN#s
gingen nur an WT.
Wer dichtet mir den Code so um das er wasserdicht wird und den Filenamen
mit ausgibt? Ich stehe wie gesagt auf dem Schlauch bzw auf der
Leitung...
Wilfried G. schrieb:> Wer dichtet mir den Code so um das er wasserdicht wird und den Filenamen> mit ausgibt?
Hilfreiche Hände findest Du immer noch am besten am Ende Deiner eigenen
Arme. Mustergültige Tipps hast Du ja schon bekommen (nicht von mir - ich
meine natürlich imonbln (Gast) ).
Walter T. schrieb:> Wilfried G. schrieb:>> Wer dichtet mir den Code so um das er wasserdicht wird und den Filenamen>> mit ausgibt?>> Hilfreiche Hände findest Du immer noch am besten am Ende Deiner eigenen> Arme. Mustergültige Tipps hast Du ja schon bekommen (nicht von mir - ich> meine natürlich imonbln (Gast) ).
Meine Finger sind schon wund, vieleicht brauch ich mal ein paar Tage
Pause..
Kein Problem. Du kannst Deinen überarbeiteten Ansatz auch in ein paar
Wochen vorstellen. Ich genehmige mir für meine Freizeitprojekte durchaus
auch ab und an einige Wochen Pause.