mikrocontroller.net

Forum: PC-Programmierung wie carriage return in C-Prog erkennen?


Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich schreibe gerade ein C-Programm, dass pro Zeile 10 int-Werte auslesen 
soll.
Wenn mehr als 10 Werte pro Zeile drinstehen, sollen nur die ersten 10 
genommen werden.
Wenn z.B. nur 7 Werte drinstehen, sollen die 7 Werte ausgelesen werden 
und danach mit dem Auslesen abgebrochen werden.
Zum Auslesen der int-Werte nutze ich fscanf() und für die Erkennung von 
carriage return die Funktion strchr().

Kann strchr() überhaupt das Zeichen '\n' erkennen? Oder benötige ich da 
eine ander Funktion?

Danke schon mal im Voraus
Simon

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klar kann es das. Was ist denn dein eigentliches Problem?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vorschlag: zeeilenweise in ein char-Feld einlesen (Länge prüfen!)
und dann daraus per sscanf die Werte holen.
Dann liefert sscanf als Rückgabewert die Anzahl der korrekt
abgearbeiteten Formatumwandlungen (wenn also z.B. im Formatstring
"%d%d%d%d%d%d%d%d%d%d" für 10 Werte steht, aber nur 7 vorhanden sind,
liefert sscanf als Rückgabewert 7).

Ansonsten kann man auch den Formatstring so hinfummeln, daß
fscanf nicht über das Zeilenende hinausliest, aber das ist etwas
aufwendiger und hinterher nicht schön lesbar.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon schrieb:
> Hallo zusammen,
> ...
> Zum Auslesen der int-Werte nutze ich fscanf() und für die Erkennung von
> carriage return die Funktion strchr().
> ...

Das ist mir jetzt nicht ganz plausibel.
fscanf liest aus einem FILE*, strchr sucht in einem String.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> Vorschlag: zeeilenweise in ein char-Feld einlesen (Länge prüfen!)
> und dann daraus per sscanf die Werte holen.

Das kann ich nur unterstützen.
Will man eine auch nur halbwegs robuste Leseschleife, führt praktisch 
kein Weg an dieser Sequenz vorbei.
  while( fgets( .... ) ) {
    // mach was mit dem String, zb mittels sscanf auseinandernehmen
  }

fscanf kann man eigentlich nur dann vernünftig einsetzen, wenn die Datei
 von einem anderen Programm erzeugt wurde
 und dessen Satzaufbau nicht variabel ist (also nicht: 10,
                                           können aber auch 7 sein)
 und der Satzaufbau exakt bekannt ist

In allen anderen Fällen ist das viel zu gefährlich. Vor allen Dingen 
dann, wenn ein menschlicher Benutzer am Datenfile rumfuhrwerken kann 
(oder soll), sind Fehler vorprogrammiert.

Autor: Simon (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
der Vorteil an fscanf() ist, dass man bei dieser Funktion schnell die 
Anzahl der auszulesenden Wert anpassen kann:

for (n=0; n<ANZAHL_WERTE; n++)
{
  fscanf (pFile, "%d", &Wert[n]);
}

Die andere Methode mit fgets() einen String aus der Datei auszulesen und 
mit sscanf() aus diesem String die Werte auszulesen ist wahrscheinlich 
sicherer, aber es ist auch aufwendiger, die Anzahl der auszulesenden 
Werte pro Zeile abzuändern:
sscanf (string,"%d %d %d...",&Wert[0],&Wert[1],&Wert[2],...);

Gibt es bei sscanf() auch die Möglichkeit, das Auslesen über eine 
for-Schleife wie oben zu machen?

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> aber es ist auch aufwendiger, die Anzahl der auszulesenden
> Werte pro Zeile abzuändern:

Muss man nicht so machen.

Man könnte die eingelesene Zeile z.b. mit strtok nach Trennzeichen 
(hier vermutlich Leerzeichen) zerlegen lassen und die resultierenden 
Fragmente in einer Schleife jeweils einem einzelnen atof vorwerfen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon schrieb:

> Die andere Methode mit fgets() einen String aus der Datei auszulesen und
> mit sscanf() aus diesem String die Werte auszulesen ist wahrscheinlich
> sicherer

Spätestens dann, wenn Fehlerbehandlung beim Einlesen zum Thema wird, 
geht es oft gar nicht mehr anders (=auf eine vernünftige Art und Weise)

> Man könnte die eingelesene Zeile z.b. mit strtok nach Trennzeichen
> (hier vermutlich Leerzeichen) zerlegen lassen und die resultierenden
> Fragmente in einer Schleife jeweils einem einzelnen atof vorwerfen.

Yep.
Eine andere Möglichkeit:
Nicht umsonst haben Funktionen wie strtol, strtod und dergleichen auch 
immer eine Möglichkeit mitzuteilen, wo sie mit dem Lesen aufgehört 
haben. Das kann man auch oft schön benutzen um einen String zu parsen 
ohne ihn vorher in Tokens zerlegen zu müssen.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das ginge mit *scanf auch, aber wenn man schon weiß, daß es
ganze Zahlen sind, ist strtol sicher die bessere Wahl.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon schrieb:
> ...
> sscanf (string,"%d %d %d...",&Wert[0],&Wert[1],&Wert[2],...);
> ...

Da gehören keine Leerzeichen rein.
Sonst müssen auch im Eingabestrom welche sein und \t
beispielsweise würde das Lesen sofort abbrechen.

Mit %d%d%d... wird korrekt gelesen, egal ob mit Leerzeichen
oder Tab getrennt.

Autor: zwieblum (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schon mal was von regex gehört?

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, Regex. Haudrauf, immer feste.

Zitat aus der GNU-Doku:
— Function: ssize_t getdelim (char **lineptr, size_t *n, int delimiter, 
FILE *stream)

    This function is like getline except that the character which tells 
it to stop reading is not necessarily newline. The argument delimiter 
specifies the delimiter character; getdelim keeps reading until it sees 
that character (or end of file).

    The text is stored in lineptr, including the delimiter character and 
a terminating null. Like getline, getdelim makes lineptr bigger if it 
isn't big enough.


Was willst du mehr? Den Quelltext der Routine gibts frei.
Ansonsten kann man in C ganz wunderbar unbestimmt lange Zeilen lesen, 
indem man rekursiv und mit dem Stack arbeitet.

Autor: zwieblum (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was mach'st mit dem stacklimit ? :-)

mal ehrlich: filegröße bestimmen, speicher holen, file in eime sitz 
laden, dann parsen, gut ist's.

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jo, je nach File.
mmap() wär noch simpler.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man könnte auch mit Lex/Yacc einen Parser aufsetzen

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.