1Danke
ERLEDIGT
JA
JA
ANTWORTEN
11
11
ZUGRIFFE
1245
1245
EMPFEHLEN
-
Hallo,
wie angedroht kommt auch schon mein nächstes Thema
Dieses mal versuche ich aus einer Textdatei Werte einzulesen.
Das einlesen mache ich mittels:
Code c:1 2 3 4 5
int a; double b, c, d; // puffer = Zeile aus Textdatei sscanf(puffer,"%i,%lf,%lf,%lf\n",&a, &b, &c, &d);
puffer ist dabei ein char Array und beinhaltet jeweils eine Zeile aus einer Textdatei.
Eine Zeile der Textdatei hat das Format:
Code :1
1,2.456,44.5558.16,55544
Das Problem daran ist nun, dass aus irgendeinem Grund bei mir das "," als Trennzeichen einer Fließkommazahl genommen wird und nicht wie üblich der ".".
Da die Textdateien aber vorgegeben sind muss ich den "." als Trennzeichen einer Fließkommazahlen behandeln. Ich verstehe auch überhaupt nicht wieso (wie ja doch normal) der Punkt nicht erkannt wird
Ändere ich die Textdatei in
Code :1
1,2,456,44,5558,16,55544
dann funktioniert alles und ich bekomme a=1 b= 2.456 c=44.5558 und d=16.55544. Aber wie gesagt: Format der Textdateien ist gegeben und ich kenne es auch von anderen Sprachen (Java,...) nur so das "." als Trennziffer erkannt werden. Laut API soll das ja auch bei C so sein. Seltsam, nicht wahr
Hoffe ihr könnt mir wieder einmal helfen
Viele Grüße und noch einen schönen Rest-Sonntag,
WingManGeändert von WingMan81 (27.09.09 um 16:12 Uhr)
-
27.09.09 17:14 #2
- Registriert seit
- May 2006
- Ort
- There is no place like 127.0.0.1
- Beiträge
- 3.516
Jaja, das liebe sscanf. Das hat mir auch schon den ein oder andern Arbeitstag versüßt

Nein im Ernst. Ich bin dazu übergegangen, diese Hilfsfunktionen nicht zu verwenden, stattdessen mittels Pointer über die Zeile zu sausen und bedingungsbehaftet dann die Werte in Strukturen oder simple Variablen zu parsen. Das ist zwar nicht so elegant wie sscanf aber zuverlässig:
Code cpp:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/* Zeiger auf den Anfang der Zeile */ char *p = puffer; char *part = puffer; char value[4][20]; int i = 0; do{ if(*p == ',') { *p = 0; strcpy(value[i], part); i++; p++; part = p; continue; } p++; if(*p == 0) break; } while(p != NULL);
Anschließend kannst du mit value[0] - [3] alles tun, was du willst. Es ist außerdem noch relativ schnell. Sicherlich kann man dies auch noch optimieren.Grüße
--
Qualität des Codes wird in WTF's/Min gemessen: Je mehr, desto schlechter der Code ;-)
-
Hi,
vielen Dank für Deine Antwort! Ich werde das auf jeden Fall auch mal so austesten, aber verstehen möchte ich doch ganz gern warum meine Lösung nicht so funktioniert wie sie es doch eigentlich sollte.
Das ganze für mich ja mehr eine Übungsaufgabe und weniger für einen Produktiveinsatz gedacht, daher suche ich natürlich weiter nach der Auflösung
Aber wie gesagt: Vielen Dank für Deine Antwort!
VG,
WingMan
-
Welche Formate bei der Ein- und Ausgabe verwendet werden, hängt von der gesetzten „Locale“ ab. Diese kann mit setlocale geändert werden. Einen Punkt als Dezimaltrennzeichen erhält man beispielsweise mit der Locale "C".
Grüße, Matthias„Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Aktuelles Coding Quiz: #17 - Wörter kreuz und quer
-
27.09.09 21:18 #5
- Registriert seit
- May 2006
- Ort
- There is no place like 127.0.0.1
- Beiträge
- 3.516
Danke für den Hinweis mit der Locale. Daran habe ich gar nicht gedacht. Noch ein Grund mehr, auf glibc-Funktionen zu verzichten, wenn man multi-linguale Applikationen entwickelt und darin Zeilen parsen muss. Vielen Dank, nun weiß ich wenigstens den Grund für mein Gefühl, es zu Fuss implementieren zu müssen.
Grüße
--
Qualität des Codes wird in WTF's/Min gemessen: Je mehr, desto schlechter der Code ;-)
-
28.09.09 08:18 #6
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
Hi.Ich finde zu ziehst die falschen Schlüsse. Das heißt nur, das man in Konfigurationsdateien bzw. Datendateien die Standardlocale verwenden sollte und nicht lokalisierte Daten abspeichert.
Abgesehen davon ist deine Funktion fehlerhaft. Wie sollte denn p plötzlich NULL sein können (vor allem nachdem du es schon x-mal verwendet hast)? Außerdem kann es passieren, dass du über das Ende des Strings hinaus liest. Ein schönes Beispiel dafür, das man doch lieber die Funktionen der C Bibliothek (richtig) anwenden sollte bevor man sich was selber bastelt.
@WingMan81: Um herauszufinden welche Locale gerade aktiv ist, kannst du setlocale aufrufen:
GrußIf at first you don't succeed, try again. Then quit. No use being a damn fool about it.
-
Hallo,
vielen Dank für die Antworten! Das setlocal() wirkt wahre Wunder
Es funktioniert nun alles so wie es soll!
Viele Grüße
WingMan
-
28.09.09 14:18 #8
- Registriert seit
- May 2006
- Ort
- There is no place like 127.0.0.1
- Beiträge
- 3.516
Geschenkt. Brauch man nicht drüber zu diskutieren. Was mach ich aber mit Daten-Dateien, die bereits lokalisiert gespeichert wurden?
Ebenfalls geschenkt. Als Schleifen-Abbruch-Bedingung hätte ich ebenso 1 wählen können.Abgesehen davon ist deine Funktion fehlerhaft. Wie sollte denn p plötzlich NULL sein können (vor allem nachdem du es schon x-mal verwendet hast)?
Mag sein, das ich was übersehe. Aber ich prüfe dochAußerdem kann es passieren, dass du über das Ende des Strings hinaus liest.
Code cpp:1
if(*p == 0) break;
Sollte das nicht genügen, wenn ich davon ausgehen darf, das der puffer Null-terminiert ist? Was übersehe ich?Grüße
--
Qualität des Codes wird in WTF's/Min gemessen: Je mehr, desto schlechter der Code ;-)
-
28.09.09 14:31 #9
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
Du könntest die Daten entsprechend konvertieren.
Oder du hättest es auch einfach vernünftig programmieren können...
Du springst über die Abfrage mit continue drüber. Schlechter Programmierstil break und continue zu benutzen obwohl absolut nicht notwendig.
GrußIf at first you don't succeed, try again. Then quit. No use being a damn fool about it.
-
28.09.09 19:05 #10
- Registriert seit
- May 2006
- Ort
- There is no place like 127.0.0.1
- Beiträge
- 3.516
So besser?
Code cpp:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/* Zeiger auf Puffer-Anfang setzen */ char *p = puffer; char *part = puffer; /* Result-Puffer */ char value[4][20]; /* Count-Variable */ int i = 0; /* Solange Ende des Null-terminierten Puffers nicht erreicht */ while(*p != 0) { /* Wenn Komma gefunden */ if(*p == ',') { /* Terminiere Teil von part bis Komma */ *p = 0; /* Kopiere Teil in Result-Variable */ strcpy(value[i++], part); /* Setze neuen Part-Anfang aktuelle Position + 1 (nach 0-Terminator) */ part = p+1; } /* Inkrementiere Zeiger */ p++; }
Das war einfach so schnell hingeschludert als Möglichkeit das Problem zu lösen. Zugegeben, es ist nicht sehr schön. Aber es hat mein Problem damals gelöst.Grüße
--
Qualität des Codes wird in WTF's/Min gemessen: Je mehr, desto schlechter der Code ;-)
-
28.09.09 19:58 #11
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
If at first you don't succeed, try again. Then quit. No use being a damn fool about it.
-
„Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Aktuelles Coding Quiz: #17 - Wörter kreuz und quer
Ähnliche Themen
-
Pattern von Fließkommazahlen
Von Duckemai im Forum Algorithmen & Datenstrukturen mit JavaAntworten: 5Letzter Beitrag: 10.08.10, 16:25 -
Rechnen mit Fließkommazahlen
Von Thomas Darimont im Forum JavaAntworten: 3Letzter Beitrag: 06.03.06, 08:07 -
zufallszahl zwischen 2 Fließkommazahlen
Von Philipp_Frank im Forum PHPAntworten: 6Letzter Beitrag: 20.10.05, 23:07 -
Fließkommazahlen
Von c-hilgert im Forum C/C++Antworten: 2Letzter Beitrag: 09.06.04, 10:02 -
sscanf in C#
Von jccTeq im Forum .NET ArchivAntworten: 3Letzter Beitrag: 25.03.04, 15:59





Zitieren

Login






