Punkt und Komma in bei Zahlenformaten
-
Hi,
ich muss eine Datei auslesen. Diese enthält Zahlen in unterschiedlichen Zahlenformaten: manchmal wird ',' (Komma) und manchmal '.' (Punkt) als Dezimaltrennzeichen verwendet.
Ich muss die Zahlen lesen und als in einem Double-Feld speichern. Gibts da eine saubere Lösung?
Ansonsten würde ich das so machen:- Zahl als String einlesen
- Prüfen, ob ',' enthalten ist, falls ja -> ersetzten durch '.'
- Veränderten String in double konvertierenZum Konvertieren des String in Double verwende ich atof(). Kann sich das Programm unterschiedlich verhalten, wenn es auf Rechnern gestartet wird, das andere Ländereinstellungen hat?
Gruss,
Karl
-
Zum Konvertieren des String in Double verwende ich atof(). Kann sich das Programm unterschiedlich verhalten, wenn es auf Rechnern gestartet wird, das andere Ländereinstellungen hat?
ja, da atof ja mit diesen den string formatiert!
-
Gibt es keine Möglichkeit unabhängig von Ländereinstellungen von String nach Double zu konvertieren. Was passiert da, wenn Punkt oder Komma gesetzt werden?
Karl
-
Du kannst das locale selbst setzen. Siehe dazu auch http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=stricmp#Answ
-
Karl Blau schrieb:
Gibt es keine Möglichkeit unabhängig von Ländereinstellungen von String nach Double zu konvertieren. Was passiert da, wenn Punkt oder Komma gesetzt werden?
Karl
Funktion selber schreiben ist das sicherste. Ist ja auch nicht sonderlich schwer.
-
Naja, ich dachte halt, es gibt da eine trickreiche Sache, die das Ganze automatisch macht.
Dann werde ich mir mal sowas selber schreiben.
Meine Idee wäre die Funktion auf folgender Ebene zu realisieren: Punkt oder Komma suchen; erster Teil als Vorkomma-Anteil und zweiter Teil als Nachkomma-Anteil auffassen; Double-Wert aus den beiden Anteilen zusammenbasteln [atoi(Vorkomma)+atoi(Nachkomma)/Kommastellen].Probleme:
Hmm was mache ich aber, wenn die Zahl '3.000,20' vorliegt, d.h. wenn Tausendertrennpunkt verwendet wird? Dann kommt die Funktion durcheinander.
Dann gibt es bestimmt noch Sonderfälle, die betrachtet werden müssen.Das wird ein Spass
Karl
-
also ich würde einfach im string die kommata durch punkte ersetzen und dann atof() anwenden.
Karl Blau schrieb:
Hmm was mache ich aber, wenn die Zahl '3.000,20' vorliegt, d.h. wenn Tausendertrennpunkt verwendet wird?
da tausender-trennzeichen immer vor dem dezimalpunkt auftreten, kannst du ja das letzte im string vorkommende trennzeichen als dezimalpunkt interpretieren und die anderen als trennzeichen. aber auch nur, wenn das letzte trennzeichen sich von den anderen trennzeichen unterscheidet!
ich hab da mal was geschrieben, das zu funktionieren scheint:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define TRENNZEICHEN ".,'´" static char *my_strchr (char *str, char *chars) { char *cp1,*cp2; for(cp1=str; *cp1; cp1++) for(cp2=chars; *cp2; cp2++) if(*cp1==*cp2) return cp1; return NULL; } char *my_strrchr (char *str, char *chars) { char *cp1,*cp2,*str_end,*chars_end; str_end = str + strlen(str) - 1; chars_end = chars + strlen(chars) - 1; for(cp1=str_end; cp1>=str; cp1--) for(cp2=chars_end; cp2>=chars; cp2--) if(*cp1==*cp2) return cp1; return NULL; } double doofe_zahl_konvertieren (const char *zahl_str) { char zahl[100], *dezimalpunktp, *trennzeichenp, *cp; strcpy(zahl,zahl_str); /* mutmaßliches trennzeichen finden */ trennzeichenp=my_strchr(zahl,TRENNZEICHEN); if(trennzeichenp) { /* mutmaßlichen dezimalpunkt finden */ dezimalpunktp=my_strrchr(zahl,TRENNZEICHEN); if(*dezimalpunktp==*trennzeichenp) /* dezimalpunkt eigentlich auch ein trennzeichen */ dezimalpunktp=NULL; while(cp=my_strchr(zahl,TRENNZEICHEN)) { strcpy(cp,cp+1); if(dezimalpunktp && cp<dezimalpunktp) --dezimalpunktp; } if(dezimalpunktp) { memmove(dezimalpunktp+1,dezimalpunktp,strlen(zahl)-(dezimalpunktp-zahl)+1); *dezimalpunktp='.'; } } return atof(zahl); } void main (void) { char buf[256]; gets(buf); printf("%f\n",doofe_zahl_konvertieren(buf)); }
-
Und wieso ne eigene Funktion schreiben? Wieso nicht locale setzen?
-
Ich wuerde die string-such funktion nehmen, welche the last sucht.
wenn er ein komma findet, schauen ob es nach dem komma noch einen punkt hat.
wenn ja, komma loeschen, wenn nein, komme zu punkt. da du jetzt einen
Iterator hast (z.B. it) musst du nur noch von begin() zu it suchen,
und kannst alle punkte oder kommas loeschen ohne sorgen.std::string bla="123.45"; float a; std::istringstream(bla)>>a;
Alternative zu atof.
Bei boost gibt es auch was gutes.Ghost