C-Programm / Komma-Problem
-
Hallo!
Bin C-Anfänger, also bitte nicht lachen.
Habe ein Programm in C geschrieben, wo der Benutzer für eine Berechnung Werte mit Komma-Stellen eingeben kann. Man muss aber zwangsweise einen Punkt anstatt des Kommas eingeben, weil das programm sonst verrückt spielt und eine Endlosschleife starten.Lässt sich das irgendwie ändern?
Danke schon mal!
-
Ohne dass du uns den fehlerhaften Code zeigst?
Nein.PS: Das hier ist das C++- und nicht das C-Forum.
-
Die Eingabe überprüfen und eventuell ändern oder eine fehlermeldung ausspucken.
Aber lies erst einmal schön fleißig in deinem buch weiter.mfg tobZel
-
Ich glaube er will darauf hinaus, dass wenn man eine Gleitkommazahl in der Konsole eingibt '47.11' statt '47,11' geschrieben werden muss.
Wenn du das wirklich ändern möchtest, musst du den Wert als Zeichenkette einlesen und manuell das Komma durch einen Punkt ersetzen. Weil die C-Funktionen den Punkt als Trennzeichen zwischen Ganzzahl-Anteil und Nachkomma-Stelle erwarten.
-
Hier mal eine Anregung, wie man das Problem selbst angehen könnte (ich weiss, es fehlt einiges, z.B. die Abfrage, ob bereits ein ',' oder '.' vorgekommen ist, was fatale Folgen für das Endergebnis hätte. Ausserdem sollte man den Fehlerfall bei weitem besser lösen):
#include <stdio.h> #include <string.h> double StrToFloat(const char* input); int main() { // String koennte genausogut eingelesen werden... const char* string = "1,2345"; // Aufruf unserer Konvertierungsfunktion printf("%lf", StrToFloat(&string[0])); getchar(); return 0; } double StrToFloat(const char* input) { /* pos nimmt die aktuelle Position auf, * die gelesen wird */ unsigned int pos = 0; /* Der hoechste moegliche Index von input wird * benoetigt, um die Stellen des input-Strings * rueckwaerts durchlaufen zu koennen (und * ausserdem um die Schleife beim erreichen des Endes * abzubrechen) */ const unsigned long inputmax = strlen(input) - 1; /* Nimmt das Ergebnis der bisherigen Konvertierung auf */ double result = 0.0; /* Nimmt die aktuelle Potenz von 10 auf, die durch * Multiplikation dafür sorgt, dass um die richtige * Dezimalstelle erweitert wird */ double dec = 1.0; /* inputmax + 1, da inputmax den hoechsten Index von * input angibt, die Schleife aber nicht dort Enden * soll, sondern erst, nachdem diese letzte Zahl * Verarbeitet wurde */ while (pos != inputmax + 1) { /* Erster Teil: Sicherstellen, dass an der aktuellen * Position eine Zahl steht oder... */ if ((input[inputmax - pos] < '0' || input[inputmax - pos] > '9') && /* Zweiter Teil: ...der Dezimalpunkt/das Dezimalkomma */ (input[inputmax - pos] != ',' && input[inputmax - pos] != '.')) { printf("Fehler: Aktuelles Zeichen ('%c') ist keine Zahl!\n", input[inputmax - pos]); return 0.0; } else { if (input[inputmax - pos] == '.' || input[inputmax - pos] == ',') { /* Hiermit wird erreicht, dass alle Stellen hinter das * Komma wandern */ result /= dec; /* Muss zurueckgesetzt werden, da das bisher ermittelte * nun hinter das Dezimalkomma geschoben ist und somit * erneut die Ermittlung der Einerstellen beginnt */ dec = 1.0; ++pos; } else { /* 3 * 1 = 3 * 2 * 10 = 20 * 4 * 100 = 400 * --------------- * 423 -> Soviel zur Funktionsweise der Zeile * hier. -'0', um aus ASCII-char eine Zahl zu * machen... */ result += ((input[inputmax - pos] - '0') * dec); /* Auf zur nächsten Stelle... Einer->Zehner->Hunderter-> ... */ dec *= 10.0; /* Zeile auskommentiert, bei Verstaendnisschwierigkeiten einfach * Kommentarzeichen entfernen... */ /* printf("10^%d = %lf\n", pos, result); */ ++pos; } } } return result; }
mfg
proggaholic[edit]
Da der Threat "C-Programm" heisst, habe ich den Code in C aufgesetzt, allerdings sollte dieser Threat dann auch in den richtigen Bereich verschoben werden...
[/edit]
-
Vielen Dank!
Und sorry für die Regelverstöße...
-
Man könnte auch einfach ein passendes locale setzen..
-
Dieser Thread wurde von Moderator/in evilissimo aus dem Forum C++ in das Forum ANSI C verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
proggaholic schrieb:
double StrToFloat(const char* input) { /* pos nimmt die aktuelle Position auf, * die gelesen wird */ unsigned int pos = 0; /* Der hoechste moegliche Index von input wird * benoetigt, um die Stellen des input-Strings * rueckwaerts durchlaufen zu koennen (und * ausserdem um die Schleife beim erreichen des Endes * abzubrechen) */ const unsigned long inputmax = strlen(input) - 1; /* Nimmt das Ergebnis der bisherigen Konvertierung auf */ double result = 0.0; /* Nimmt die aktuelle Potenz von 10 auf, die durch * Multiplikation dafür sorgt, dass um die richtige * Dezimalstelle erweitert wird */ double dec = 1.0; /* inputmax + 1, da inputmax den hoechsten Index von * input angibt, die Schleife aber nicht dort Enden * soll, sondern erst, nachdem diese letzte Zahl * Verarbeitet wurde */ while (pos != inputmax + 1) { /* Erster Teil: Sicherstellen, dass an der aktuellen * Position eine Zahl steht oder... */ if ((input[inputmax - pos] < '0' || input[inputmax - pos] > '9') && /* Zweiter Teil: ...der Dezimalpunkt/das Dezimalkomma */ (input[inputmax - pos] != ',' && input[inputmax - pos] != '.')) { printf("Fehler: Aktuelles Zeichen ('%c') ist keine Zahl!\n", input[inputmax - pos]); return 0.0; } else { if (input[inputmax - pos] == '.' || input[inputmax - pos] == ',') { /* Hiermit wird erreicht, dass alle Stellen hinter das * Komma wandern */ result /= dec; /* Muss zurueckgesetzt werden, da das bisher ermittelte * nun hinter das Dezimalkomma geschoben ist und somit * erneut die Ermittlung der Einerstellen beginnt */ dec = 1.0; ++pos; } else { /* 3 * 1 = 3 * 2 * 10 = 20 * 4 * 100 = 400 * --------------- * 423 -> Soviel zur Funktionsweise der Zeile * hier. -'0', um aus ASCII-char eine Zahl zu * machen... */ result += ((input[inputmax - pos] - '0') * dec); /* Auf zur nächsten Stelle... Einer->Zehner->Hunderter-> ... */ dec *= 10.0; /* Zeile auskommentiert, bei Verstaendnisschwierigkeiten einfach * Kommentarzeichen entfernen... */ /* printf("10^%d = %lf\n", pos, result); */ ++pos; } } } return result; }
Benutzt doch die schönen Funktionen aus dem Standard. Dazu sind sie ja da
double StrToFloat(const char* input ){ double ret; char *tmp; if( (tmp = strchr( input, ',')) ){ *tmp = '.'; } ret = strtod(input, &tmp); if( tmp ){ printf("Fehler bei %s\n", tmp); return 0.0; } else{ return ret; } }
-
TactX schrieb:
... *tmp = '.'; // <---- peng! ... }
stürzt aber ab, wenn du der funktion 'ne stringkonstante gibst.
vielleicht sowas ?double StrToFloat (const char* input ) { double a = 0.0; double b = 1.0; int f = 0; for (;*input;input++) { if (*input == ',') f = 1; else { a = 10.0 * a + *input - '0'; if (f == 1) b = 10.0 * b; } } return a/b; }
-
Spielverderber