C - Zeilenanfang einer Datei bestimmen
C - Zeilenanfang einer Datei bestimmen
Hallo,
ich möchte mit Hilfe eines C-Programms in einer Datei bestimmte Zeilen finden, diese ergänzen und die Datei anschließend abspeichern.
Wie kann ich in C den Anfang der Zeile ermitteln bzw. die Position des Zeigers auf den Anfang der Zeile setzen?
Benötige z.b. keine Zeilen, die mit #-Anfangen.
Danke & Gruß,
Daniel
ich möchte mit Hilfe eines C-Programms in einer Datei bestimmte Zeilen finden, diese ergänzen und die Datei anschließend abspeichern.
Wie kann ich in C den Anfang der Zeile ermitteln bzw. die Position des Zeigers auf den Anfang der Zeile setzen?
Benötige z.b. keine Zeilen, die mit #-Anfangen.
Danke & Gruß,
Daniel
Oh, yeah!
-
- Beiträge: 1213
- Registriert: 09.11.2007 13:25:57
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Re: C - Zeilenanfang einer Datei bestimmen
Zeilenweise Ein-/Ausgabe von Streams
Dann vllt sowas
Du könntest auf die Zeile(n) auch regex anwenden.
Oder wenn es kleine Dateien sind, komplett einlesen, und mit strtok() und '\n' was machen.
Dann vllt sowas
Code: Alles auswählen
char * Zeile = "";
char * Zeilenanfang =& Zeile[0];
Oder wenn es kleine Dateien sind, komplett einlesen, und mit strtok() und '\n' was machen.
Re: C - Zeilenanfang einer Datei bestimmen
Danke.
Aber welche der beiden Varianten eignet sich denn besser?
(Es handelt sich um eine kleine Datei mit ca. 130 Zeilen)
Aber welche der beiden Varianten eignet sich denn besser?
(Es handelt sich um eine kleine Datei mit ca. 130 Zeilen)
Oh, yeah!
Re: C - Zeilenanfang einer Datei bestimmen
Bei 130 Zeilen würde ich die Variante mit dem kompletten Einlesen der Datei und den Einsatz von Stringfunktionen nehmen. Falls sich dein Suchmuster in einer (oder wenigen) übersichtlichen Regex ausdrücken lässt, gern auch damit.
Das ist zwar nicht so Performant wie die Streamvariante, aber die Performance dürfte hier eher zweitrangig sein, und der Code bleibt übersichtlicher.
Das ist zwar nicht so Performant wie die Streamvariante, aber die Performance dürfte hier eher zweitrangig sein, und der Code bleibt übersichtlicher.
-
- Beiträge: 1213
- Registriert: 09.11.2007 13:25:57
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Re: C - Zeilenanfang einer Datei bestimmen
Hier mal wie ich eine Datei in eine Variable einlesen würde (als Hobby Coder) ohne Fehlerbehandlung
Code: Alles auswählen
#include <stdio.h>
int main(int argc, char * argv[])
{
char * var = NULL, c;
int cnt = -1, len = cnt;
FILE * f = fopen(argv[1],"r");
var = (char *) calloc(var, sizeof(char));
len++;
while((c=getc(f)) != EOF){
cnt++;
var[cnt]=c;
if(len<cnt){
var = (char *) realloc(var,BUFSIZ*sizeof(char));
len += BUFSIZ;
}
}
fclose(f);
printf("%s", var);
free(var);
/* ... */
return 0;
}
-
- Beiträge: 1213
- Registriert: 09.11.2007 13:25:57
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Re: C - Zeilenanfang einer Datei bestimmen
@Duff: Vllt ist es ist in deinem Fall sogar besser, die Zeilen in ein 2D-Array einzulesen
Re: C - Zeilenanfang einer Datei bestimmen
Wenn du mir sagen kannst wie groß man das Array wählen soll.i hat geschrieben:@Duff: Vllt ist es ist in deinem Fall sogar besser, die Zeilen in ein 2D-Array einzulesen
Use ed once in a while!
-
- Beiträge: 1213
- Registriert: 09.11.2007 13:25:57
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Re: C - Zeilenanfang einer Datei bestimmen
So lang wie die Datei Zeilen hat die 1. Dimension mit jeweils ein Zeiger auf ein zweites char Array was die Zeile enthält Das ganze natürlich Dynamisch ...
Jürgen Wolf hat sogar ein eigenes Kapitel dazu Zweidimensionale dynamische Arrays
Jürgen Wolf hat sogar ein eigenes Kapitel dazu Zweidimensionale dynamische Arrays
Re: C - Zeilenanfang einer Datei bestimmen
Aber du hast schon verstanden auf was ich mit meiner ``Metafrage'' hinweisen wollte, oder?i hat geschrieben:So lang wie die Datei Zeilen hat [...]
Man kann das so machen, doch im Normalfall sollte man solche komplizierten Strukuren vermeiden.[...] die 1. Dimension mit jeweils ein Zeiger auf ein zweites char Array was die Zeile enthält Das ganze natürlich Dynamisch ...
Use ed once in a while!
-
- Beiträge: 1213
- Registriert: 09.11.2007 13:25:57
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Re: C - Zeilenanfang einer Datei bestimmen
Metafrage, hm ich habe echt keine Ahnung ...Meillo hat geschrieben: Aber du hast schon verstanden auf was ich mit meiner ``'metafrage' hinweisen wollte, oder?
Re: C - Zeilenanfang einer Datei bestimmen
Zugegeben, es war keine Metafrage. (Memo an mich: Zuerst nachlesen was irgendwelche coolen Fachbegriffe wirklich bedeuten bevor ich sie verwende. )i hat geschrieben:Metafrage, hm ich habe echt keine Ahnung ...Meillo hat geschrieben: Aber du hast schon verstanden auf was ich mit meiner ``metafrage'' hinweisen wollte, oder?
Ich habe nicht gefragt weil ich keine Antwort darauf kenne; ich habe gefragt damit du merkst, dass es ein Problem ist eine *gute* Antwort auf die Frage zu geben.
Wer mag schon wissen wie groß die Dateien sein werden mit denen man das Programm mal verwenden will? Natürlich lässt sich mit malloc() und viel Mehraufwand alles irgendwie dynamisch verwalten, doch meist kann man das mit einem besseren Design vermeiden.
Use ed once in a while!
-
- Beiträge: 1213
- Registriert: 09.11.2007 13:25:57
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Re: C - Zeilenanfang einer Datei bestimmen
Das habe ich mir gedachtMeillo hat geschrieben: Ich habe nicht gefragt weil ich keine Antwort darauf kenne;
Schon klar. Wir haben hier ja schon gut 3 Ansätze.Meillo hat geschrieben: ich habe gefragt damit du merkst, dass es ein Problem ist eine *gute* Antwort auf die Frage zu geben.
Genau das wolle ich mit dem Array eigentlich erreichen., doch meist kann man das mit einem besseren Design vermeiden.
Vllt hast du ja die Zeit hier kurz was besseres zu skizzieren. Damit wir auch was lernen^^
(Ein schicker link würde ja reichen)
PS:
Ich habe die Aufgabe von Duff mal so interpretiert
Ich will auf alle Zeilen zugreifen können und diese ggf wie einen String bearbeiten können.
Das kann ich schlecht on the fly mitten in der Datei machen. Also müssen die Daten in den Speicher es sei denn ich Arbeite mit einer (2.) Ausgabe-Datei. Lese Zeile aus der (orig) Eingabe Datei Bearbeite Zeile Schreibe Zeile in Ausgabe-Datei.
Oder ich lade die Komplette Datei in eine Daten-Strucktur und überschreibe damit später die Datei wieder.
Re: C - Zeilenanfang einer Datei bestimmen
Gerne.i hat geschrieben:Vllt hast du ja die Zeit hier kurz was besseres zu skizzieren. Damit wir auch was lernen^^
Ein schicker Link zu was? Bücher wie man besser programmiert? Diese Links kannst du dir selbst generieren, indem du nach Kernighan und Pike (oder den anderen Unix-Jungs) suchst.(Ein schicker link würde ja reichen)
Bevor man irgendwelche Designüberlegungen macht, sollte man die Anforderungen erst *genau* kennen. Denn kleine Änderungen können große Auswirkungen haben.Ich habe die Aufgabe von Duff mal so interpretiert
Ich will auf alle Zeilen zugreifen können und diese ggf wie einen String bearbeiten können.
Wenn Duff seine Anforderungen genau spezifiziert, schlage ich gerne was vor.
Wenn möglich sollte das Programm natürlich ein Filter werden, für spätere Wiederverwendbarkeit.Das kann ich schlecht on the fly mitten in der Datei machen. Also müssen die Daten in den Speicher es sei denn ich Arbeite mit einer (2.) Ausgabe-Datei. Lese Zeile aus der (orig) Eingabe Datei Bearbeite Zeile Schreibe Zeile in Ausgabe-Datei.
Oder ich lade die Komplette Datei in eine Daten-Strucktur und überschreibe damit später die Datei wieder.
Aber, wie gesagt, mal abwarten wie die Anforderungen *wirklich* sind.
Use ed once in a while!
- schorsch_76
- Beiträge: 2612
- Registriert: 06.11.2007 16:00:42
- Lizenz eigener Beiträge: MIT Lizenz
Re: C - Zeilenanfang einer Datei bestimmen
Nicht ganz Ontopic, aber das wäre eine C++ Lösung für dein Problem im Startpost
Das macht z.b. aus
das hier
Gruß
schorsch
Code: Alles auswählen
#include <iostream>
#include <string>
#include <fstream>
int main(int argc, char** argv)
{
std::string filename = "test.txt";
std::string muster = "muster";
std::string ersatz = "-123-";
std::ifstream ifs(filename.c_str());
if (ifs.is_open())
{
std::string zeile;
while (std::getline(ifs, zeile))
{
std::cout << "Orginal:" << zeile <<std::endl;
size_t pos = zeile.find(muster);
while (pos != std::string::npos)
{
zeile.erase(pos,muster.length());
zeile.insert(pos,ersatz);
pos = zeile.find(muster,pos+ersatz.length());
}
std::cout << "Ersatz:" << zeile <<std::endl;
}
}
return 0;
}
Code: Alles auswählen
zeile nix
Zeile 2
muster1 und muster2
nochwas
Code: Alles auswählen
zeile nix
Zeile 2
-123-1 und -123-2
nochwas
schorsch
-
- Beiträge: 1213
- Registriert: 09.11.2007 13:25:57
- Lizenz eigener Beiträge: GNU General Public License
-
Kontaktdaten:
Re: C - Zeilenanfang einer Datei bestimmen
und genau diese Lösung finde ich zu starr und langweilig
(Auch wenn sie das Probl. imo löst.)
(Auch wenn sie das Probl. imo löst.)
- schorsch_76
- Beiträge: 2612
- Registriert: 06.11.2007 16:00:42
- Lizenz eigener Beiträge: MIT Lizenz
Re: C - Zeilenanfang einer Datei bestimmen
Naja, sie hat keinen Thrill sich um Speicherverwaltung kümmern zu müssen. Keine direkte Pointerarithmetik! naja, Einfach Langweiligi hat geschrieben:und genau diese Lösung finde ich zu starr und langweilig
Gruß
schorsch
P.S.: Das lässt sich einfach auch erweitern, dass es ähnlich wie grep arbeitet
cat text | meinprogi muster -123- > ausgabe.txt
Code: Alles auswählen
#include <iostream>
#include <string>
#include <fstream>
int main(int argc, char** argv)
{
if (argc != 3)
{
std::cout << "Usage: myfilter muster ersatz" << std::endl;
return -1;
}
// now do work
std::string muster = argv[1];
std::string ersatz = argv[2];
//if (ifs.is_open())
{
std::string zeile;
while (std::getline(std::cin, zeile))
{
size_t pos = zeile.find(muster);
while (pos != std::string::npos)
{
zeile.erase(pos,muster.length());
zeile.insert(pos,ersatz);
pos = zeile.find(muster,pos+ersatz.length());
}
std::cout << zeile <<std::endl;
}
}
return 0;
}
Re: C - Zeilenanfang einer Datei bestimmen
Erstmal Danke für die vielen Beiträge.
Ich möchte eigentlich keine fertige Lösung präsentiert bekommen, sondern lieber einen Tipp, welchen der vielen vorgeschlagenen Lösungswege ich denn am besten verwenden sollte.
In einer einfachen Textdatei (es handelt sich um eine Konfigurationsdatei), sollen 2 Zeilen an einer bestimmten Stelle eingefügt werden und 2 vorhandenen Zeilen sollen um weitere Parameter ergänzt werden.
(Habe dies mit sed zwar schon gelöst, würde es aber gerne mit C realisieren, weil ich mir diese Programmiersprache aneignen möchte und dies für mich eine gute und nutzvolle Praxisübung ist)
Ich möchte eigentlich keine fertige Lösung präsentiert bekommen, sondern lieber einen Tipp, welchen der vielen vorgeschlagenen Lösungswege ich denn am besten verwenden sollte.
In einer einfachen Textdatei (es handelt sich um eine Konfigurationsdatei), sollen 2 Zeilen an einer bestimmten Stelle eingefügt werden und 2 vorhandenen Zeilen sollen um weitere Parameter ergänzt werden.
(Habe dies mit sed zwar schon gelöst, würde es aber gerne mit C realisieren, weil ich mir diese Programmiersprache aneignen möchte und dies für mich eine gute und nutzvolle Praxisübung ist)
Oh, yeah!
Re: C - Zeilenanfang einer Datei bestimmen
Loblich.Duff hat geschrieben:Ich möchte eigentlich keine fertige Lösung präsentiert bekommen, sondern lieber einen Tipp, welchen der vielen vorgeschlagenen Lösungswege ich denn am besten verwenden sollte.
Ich würde zeilenweise in sowas wie buffer[BUFSIZ] einlesen. Dort kannst du dann schauen ob es eine entsprechende Zeile ist (direkt mit buffer oder mit strtok() zum Beispiel).In einer einfachen Textdatei (es handelt sich um eine Konfigurationsdatei), sollen 2 Zeilen an einer bestimmten Stelle eingefügt werden und 2 vorhandenen Zeilen sollen um weitere Parameter ergänzt werden.
Ich würde das Programm als Filter implementieren und einen kleinen Shell-Script-Wrapper drumrum bauen der die Ausgabe in eine zweite Datei umleitet und anschließend zurück kopiert.
(Habe dies mit sed zwar schon gelöst, würde es aber gerne mit C realisieren, weil ich mir diese Programmiersprache aneignen möchte und dies für mich eine gute und nutzvolle Praxisübung ist)
Da hast du dir gerade eines der Probleme ausgesucht für die C nicht gerade geeignet ist. (Das ist einer der Gründe warum gibt es awk gibt.)
Implementiere erstmal lieber was mit verketteten Listen und Bäumen und viel Berechnung (z.B. eine Suche im Labyrinth), das ist eher die Welt von C. Das soll aber nicht heißen, dass du dein Programm nicht schreiben sollst.
Use ed once in a while!
- schorsch_76
- Beiträge: 2612
- Registriert: 06.11.2007 16:00:42
- Lizenz eigener Beiträge: MIT Lizenz
Re: C - Zeilenanfang einer Datei bestimmen
Hallo Duff!
An deiner Stelle würd ich das Problem in C in Teilprobleme zerlegen:
a) Wie finde ich den Anfang eines Musters in einer Zeile?
b) Wie lösche ich das Muster aus dem String?
c) Wie füge ich den Ersatz an der Stelle ein?
Vorschlag:
Das ganze wird dann in entsprechende Schleifen gepackt
Gruß
schorsch
An deiner Stelle würd ich das Problem in C in Teilprobleme zerlegen:
a) Wie finde ich den Anfang eines Musters in einer Zeile?
b) Wie lösche ich das Muster aus dem String?
c) Wie füge ich den Ersatz an der Stelle ein?
Vorschlag:
Code: Alles auswählen
int FindeMuster(const char* string, const char* muster)
{
// TODO
}
void LöscheMuster(char* string, int laengfe_zu_loeschen)
{
// TODO
}
void FuegeErsatzEin(char* string, const char* ersatz, int startposition)
{
// TODO
}
Gruß
schorsch
Re: C - Zeilenanfang einer Datei bestimmen
Meillo hat geschrieben:Ich würde zeilenweise in sowas wie buffer[BUFSIZ] einlesen. Dort kannst du dann schauen ob es eine entsprechende Zeile ist (direkt mit buffer oder mit strtok() zum Beispiel).In einer einfachen Textdatei (es handelt sich um eine Konfigurationsdatei), sollen 2 Zeilen an einer bestimmten Stelle eingefügt werden und 2 vorhandenen Zeilen sollen um weitere Parameter ergänzt werden.
Ack, bei Aufgaben, die von Natur aus Zeilenorientiert sind, sollte man das ausnutzen. Mit getline() muss man sich nicht mal mehr um BUFSIZ kümmern, getline() macht intern ein malloc(). Seit Squeeze bzw. Posix2008 gibt's die Funktion auch offiziell und nicht nur für GNUler.
Beware of programmers who carry screwdrivers.
Re: C - Zeilenanfang einer Datei bestimmen
Versuche, die Datei in ein zweidimensionales Array zu lesen (scheitere aber an verschiedenen Stellen).
http://nopaste.debianforum.de/31484
http://nopaste.debianforum.de/31484
Oh, yeah!
- schorsch_76
- Beiträge: 2612
- Registriert: 06.11.2007 16:00:42
- Lizenz eigener Beiträge: MIT Lizenz
Re: C - Zeilenanfang einer Datei bestimmen
Hi Duff,
Zeile 10 entfernt die erste Warnung (main.c:35: warning: assignment from incompatible pointer type)
Zeile 43 entfernt die zweite Warnung (main.c:43: warning: assignment makes integer from pointer without a cast))
Kleine Frage für dich zum Nachdenken: Was machst du wenn eine Zeile mehr als 255 Zeichen hat? Tipp: realloc
Hier ein Code: http://nopaste.debianforum.de/31491
Gruß
schorsch
EDIT:
Zeile 28: matrix=(char**)malloc(zeile * sizeof(int *));
Wie viele Zeilen willst du den reservieren? Hier ist zeile noch 0. Oder schlimmer: Irgendein grosser Wert. Initialisiere immer erst deine Variablen.
EDIT2:
Vermutlich bist du beim ermitteln der Zeilen/Spalten etwas unsicher gewesen oder weist nicht wie man das macht. Deshalb hier mein Beispiel für dich:
Zeile 10
Code: Alles auswählen
char **matrix;
Zeile 43
Code: Alles auswählen
matrix[i]=(char*)fgets(puffer, BUF, f);
Kleine Frage für dich zum Nachdenken: Was machst du wenn eine Zeile mehr als 255 Zeichen hat? Tipp: realloc
Hier ein Code: http://nopaste.debianforum.de/31491
Gruß
schorsch
EDIT:
Zeile 28: matrix=(char**)malloc(zeile * sizeof(int *));
Wie viele Zeilen willst du den reservieren? Hier ist zeile noch 0. Oder schlimmer: Irgendein grosser Wert. Initialisiere immer erst deine Variablen.
EDIT2:
Vermutlich bist du beim ermitteln der Zeilen/Spalten etwas unsicher gewesen oder weist nicht wie man das macht. Deshalb hier mein Beispiel für dich:
Code: Alles auswählen
// Ermittle Anzahl der Zeilen / maximale anzahl der spalten
char c = 0;
j = 0;
while ((c = fgetc(f)) != EOF)
{
// zeile
if (c=='\n')
{
j = 0;
zeile++;
}
if (j > spalte)
{
spalte = j;
}
j++;
}
fseek(f,0,SEEK_SET); // Setze filepointer auf begin
Re: C - Zeilenanfang einer Datei bestimmen
Ok, habe ich hoffentlich verstanden. Da ich in den Zeilen der Matrix die Werte als String bzw. Characters speichern möchte, muss ich auch ein char und kein int angeben.schorsch_76 hat geschrieben: Zeile 10entfernt die erste Warnung (main.c:35: warning: assignment from incompatible pointer type)Code: Alles auswählen
char **matrix;
Hier gilt das Gleiche. Ich gebe an die Zeile der Matrix alle Werte per Referenz auf ein char Array zurück.schorsch_76 hat geschrieben: Zeile 43entfernt die zweite Warnung (main.c:43: warning: assignment makes integer from pointer without a cast))Code: Alles auswählen
matrix[i]=(char*)fgets(puffer, BUF, f);
schorsch_76 hat geschrieben:
Kleine Frage für dich zum Nachdenken: Was machst du wenn eine Zeile mehr als 255 Zeichen hat? Tipp: realloc
Hier ein Code: http://nopaste.debianforum.de/31491
So weit bin ich in dem Programm wohl noch nicht.
Der Rest will noch nicht so...
schorsch_76 hat geschrieben:
EDIT:
Zeile 28: matrix=(char**)malloc(zeile * sizeof(int *));
Wie viele Zeilen willst du den reservieren? Hier ist zeile noch 0. Oder schlimmer: Irgendein grosser Wert. Initialisiere immer erst deine Variablen.
Kannst du mir diese Zeile mal erklären?
(Vorallem, warum ich char** schreiben muss. Danke.
Dass mit den Zeilen verstehe ich noch.schorsch_76 hat geschrieben:
EDIT2:
Vermutlich bist du beim ermitteln der Zeilen/Spalten etwas unsicher gewesen oder weist nicht wie man das macht. Deshalb hier mein Beispiel für dich:
Code: Alles auswählen
// Ermittle Anzahl der Zeilen / maximale anzahl der spalten char c = 0; j = 0; while ((c = fgetc(f)) != EOF) { // zeile if (c=='\n') { j = 0; zeile++; } if (j > spalte) { spalte = j; } j++; } fseek(f,0,SEEK_SET); // Setze filepointer auf begin
Aber wie meinst du das mit den Spalten?
Die Spalten sollen doch als char Array gespeichert werden, oder zähle ich so die Anzahl der Elemente und muss im Array noch das abschließende Terminierungszeichen '\0' anhängen?
Sorry für die vielen Fragen, aber habe noch nicht so ganz den Durchblick!
Hoffe, dass dies bald kommt...
Oh, yeah!
Re: C - Zeilenanfang einer Datei bestimmen
char** entspricht char[][].Duff hat geschrieben:Kannst du mir diese Zeile mal erklären?schorsch_76 hat geschrieben: Zeile 28: matrix=(char**)malloc(zeile * sizeof(int *));
(Vorallem, warum ich char** schreiben muss. Danke.
Aber in C castet man die Rückgabe von malloc() üblicherweise nicht -- im Gegensatz zu C++.
Üblicherweise nimmt man ein Array von Zeilen, bei dem jede Zeile ein Array von char ist. Also anders rum wie du es hier siehst.Die Spalten sollen doch als char Array gespeichert werden [...]
Siehst du, das meinte ich mit der Komplexität dieses Ansatzes. Warum das Programm nicht *erst* zeilenbasierend programmieren (dann brauchst du nämlich nur ein Array, für die eine Zeile). Wenn das läuft und verstanden ist, dann kannst du *immer noch* die kompliziertere Version mit dem 2D-Array angehen.Sorry für die vielen Fragen, aber habe noch nicht so ganz den Durchblick!
Vom Leichten zum Schweren ... wie immer beim Lernen/Üben/Trainieren.
Use ed once in a while!
Re: C - Zeilenanfang einer Datei bestimmen
So meinte ich es. Hatte mich falsch ausgedrückt.Meillo hat geschrieben: Üblicherweise nimmt man ein Array von Zeilen, bei dem jede Zeile ein Array von char ist. Also anders rum wie du es hier siehst.
Meinst du mit zeilenbasiert folgendes:Meillo hat geschrieben: Siehst du, das meinte ich mit der Komplexität dieses Ansatzes. Warum das Programm nicht *erst* zeilenbasierend programmieren (dann brauchst du nämlich nur ein Array, für die eine Zeile).
Eine Zeile einlesen, ausgeben und anschließend die nächste Zeile einlesen?
Oh, yeah!