-
Hallo,
ich möchte gerne drei Double-Variablen hintereinander korrekt einlesen.
Dabei giebt es leider einige Probleme:- cin.fail() reagiert nicht, bei:
- "5000hgh", hier würde einfach "5000" eingelesen und "hgh" kommt gleich in die nächst Variable, wo dann der Fehler auftritt
- "fhzf400", hier wird für das aktuelle Einlesen ein Fehler gemeldet, jedoch gets gleich weiter zur nächsten Variablen, die dann "400" zugewiesen bekommt, der User hat damit keine Changese mehr den ersten Wert zu berichtigen
- Soweit ich das verstanden hab, setzt
(nur) die Fehler-Flags zurück.?Code cpp:1
cin.clear();
cin.get() und cin.sync() hab ich immer wieder an allen möglichen stellen eingesetzt und rausgenommen, wo wäre das jetzt eigentlich sinfoll? - Ich würde gerne das Komma als Dezimaltrennzeichen verwenden, unter Linux funktioniert das mit
undCode cpp:1
cin.imbue(locale("de_DE.uft-8"));
Bei Windows hingegen hilft auch stundenlanges googeln nichts.Code cpp:1
fout.imbue(locale("de_DE.uft-8"));
- Noch was:
eingetlich möchte ich auch das man das Programm zu jeder Zeit per ESC-Druck beenden kann, da es in einer Endlosschleife läuft. Falls irgendwie möglich, sollte zu Anfang das Komandozeilenfenster gecleart werden, nicht bloß runterscrollen oder Leerzeilen schreiben!
Beides selbstverständlich für Linux, Windows, Mac und auch ältere Versionen, sonst macht das ganze für mich keinen Sinn.
Freue mich sehr auf eure Hilfe, weil ich hier mittlerweile am verzweifeln bin,
javaDeveloper2011
- cin.fail() reagiert nicht, bei:
-
16.08.11 16:14 #2
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
Hi.Das ist doch völlig OK, oder nicht?
Das liegt aber dann an deinem Code.
Ja.
sync() wäre sinnvoll wenn du die gepufferte Eingabe löschen möchtest.
Wie willst du denn eigentlich einlesen? Zeilenweise? Dann nimm getline und verarbeite die gelese Zeile mit einem istringstream:
(ist nur ein Beispiel, es hängt davon ab wie du Einlesen willst)Code cpp:1 2 3 4 5 6
while (getline(cin, line)) { istringstream input(line); double d1, d2, d3; if (input >> d1 >> d2 >> d3 && input.peek() == EOF) { } }
Eigentlich sollte es "utf-8" heißen.
Unter Windows heißen die Locales leider etwas anders. Versuch mal "de". Das funktioniert zumindest mit dem MS Compiler.
Dann mußt du unterschiedlichen Code schreiben. Oder z.B. ncurses (PDcurses unter Windows) verwenden.
GrußIf at first you don't succeed, try again. Then quit. No use being a damn fool about it.
-
Hi,
leider werde auch auß deiner antwort noch nicht wirklich schlau.
Natürlich nicht! Der User giebt irgendwas ein, ob er nun dachte dass nam mit Komma Dezimalzahlen trennt, ein Prozent-, oder Euro-Zeichen anhängt, oder sich einfach vertiptt, am Ende haben manche Varialen den wert 0, andere irgend einen ungewollten oder es kommt eine - für den User unverständliche - Fehlermeldung nach der anderen.Das ist doch völlig OK, oder nicht?
bewirkt nur dass die Variablen bei jeklichem Fehler einfach bei 0 bleiben und weiter gemacht wird.sync()
Wie ich einlesen will:
- es erscheint ein Name (der Variablen) in der Promt und danach der Cursor.
- Der User giebt in die gleiche Zeile einen Double-wert ein und drückt Enter
- Falls es kein komplett absolut korrekter double-Wert war, erscheint ne Fehlermeldung und in der Zeile drunter wieder Name + Cursor
- Wenn alles gut ging gets genau so mit der nächsten Variablen weiter.
Ich hab auch mal ein kleines Beispiel in Java geschriben, um zu zeigen wie das Einlesen funktionieren soll, Komma als Dezimltrennzeichen funktioniert, Clear-Screen hab ich jetzt eindgültig aufgegeben und Beenden mit ESC hab ich nichtmal in Java hinbekommen, aber ich denke du weisst, was ich vorhabe:
Code java: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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.text.DecimalFormat; import java.text.ParseException; import java.util.Locale; public class ReadTest{ public static void main(String[] args) { double v1 = 0, v2 = 0; boolean v1_korrekt = false, v2_korrekt = false; DecimalFormat deutschesFormat = (DecimalFormat) DecimalFormat.getInstance(Locale.GERMAN); BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); while(!v1_korrekt){ System.out.print("Variable 1: "); try{ String s = reader.readLine(); try{ v1 = deutschesFormat.parse(s).doubleValue(); v1_korrekt = true; } catch(ParseException ex){ System.err.println("Bitte geben Sie eine gültige Dezimalzahl ein!"); } } catch(IOException ex){ System.err.println(ex.toString()); } } while(!v2_korrekt){ System.out.print("Variable 2: "); try{ String s = reader.readLine(); try{ v1 = deutschesFormat.parse(s).doubleValue(); v2_korrekt = true; } catch(ParseException ex){ System.err.println("Bitte geben Sie eine gültige Dezimalzahl ein!"); } } catch(IOException ex){ System.err.println(ex.toString()); } } System.out.println(v1 + " + " + v2 + " = " + (v1+v2)); System.out.println(v1 + " - " + v2 + " = " + (v1-v2)); System.out.println(v1 + " * " + v2 + " = " + (v1*v2)); System.out.println(v1 + " / " + v2 + " = " + (v1/v2)); } }
javaDeveloper2011
-
17.08.11 08:28 #4
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
Hi.Das hat aber nichts mit dem Einlesen an sich zu tun. Du mußt halt einfach prüfen ob nach dem erwarteten Wert noch ungültige Zeichen kommen.
Du mußt schon prüfen ob überhaupt etwas eingelesen wurde. Scheinbar hast du das nicht gemacht.
Das dürfte recht einfach sein.
Dann lies die Zeile mit getline aus und verabeite diese mit einem istringstream.
s.o.
Schreibe dir eine Funktion die du mit den verschiedenen Variablen aufrufen kannst.
GrußIf at first you don't succeed, try again. Then quit. No use being a damn fool about it.
-
Hallo deepthroat,
ne extra Funktion und getline() waren ne sehr gute Idee.
Ich hab sie auch noch in eine Header-Datei ausgelagert, und will noch Funktionen für andere Datentypen hinzufügen.
der Code:
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
#ifndef DOUBLE_IO_H #define DOUBLE_IO_H #include <iostream> #include <string> #include <sstream> #include <stdlib.h> #include <stdexcept> // Name zur Anzeige bei Eingabeaufforderung // Variable wird nicht-konstant übergeben (per Referenz), aber auch zurückgegeben double& readVar(const std::string& name, double& var) { bool korrekt = false; while(!korrekt){ std::cout << name << ": "; std::string s; std::getline(std::cin, s); bool alleZeichenZahlen = true, erstesKomma = true; // Im string sind erlaubt... for(int i=0; i<s.length(); i++){ // ... Zahlen if(isdigit(s[i])){ continue; } // ... 1 x ',' außer ganz am Anfang oder ganz am Ende else if(s[i] == ',' && erstesKomma && i > 0 && i < s.length()-1){ s[i] = '.'; // atof() akzeptiert nur Punkt als Dezimaltrennzeichen erstesKomma = false; continue; } else{ alleZeichenZahlen = false; break; } } if(alleZeichenZahlen){ var = atof(s.c_str()); korrekt = true; } else{ std::cerr<< "*** Bitte geben Sie eine gueltige Dezimalzahl ein! ***" << std::endl; } } return var; } // Nur Name erforderlich, günstig wenn zuvor keine Variable vorliegt, so wird der Code kürzer double& readVar(const std::string& name) { double d; // Zwar ne lokale variable, die per Referenz übergeben wird, funktioniert aber irgendwie return readVar(name, d); } // Name und // double-Variable zur Ausgabe void writeVar(const std::string& name, const double& var) { std::ostringstream oss; oss << var; std::string s = oss.str(); // Bei ganzen Zahlen try{ s.replace(s.find('.'), 1, ","); // Komma als Dezimaltrennzeichen } catch(std::out_of_range ex){ } std::cout << name << ": " << s << std::endl; } #endif
Das mit Komma statt Punkt hab ich jetzt manuel gelöst, war kaum mehr aufwand und damit erspaare ich mir das ganze mit locals und ihrer portierung.
Meine Frage: In Zeile 51 übergebe ich ne Referenz auf eine nicht-globale Variable, eigentlich doch verboten, aber hier ist es sehr praktisch und funktioniert auch einwandfrei. Kann ich das dann so lassen?
An sonsten wäre da noch die Sache mit den Umlauten, es geht lediglich um einige statische Strings wie "gültig" im oberen Listing \u00FC bewikt beim mingw32-Cross-Compiler leider auch nichts, irgend ne Idee?
Über Vorschläge zu clearscreen und Programm Beenden per ESC freue ich mich natürlich weterhin,
javaDeveloper2011
-
Hallo,
Das mit der Referenz in Zeile 51 halte ich für keine gute Idee, da dies nur solange funktioniert bis der Speicherbereich in der die lokale Variable lag überschrieben wird. Eigentlich ist es hier aber auch nicht notwendig eine Referenz zurück zu geben. Du kannst einfach einen double zurückgeben, dann hast du das Problem nicht.
-
Hi,
hast recht, ich hatte nicht mehr dran gedacht, dass der Compiler trotzdem je nach Parameterzahl die richtige überladene Funktion raussucht, auch wenn ein Mal ein Wert und das andere Mal ne Referenz zurückgegeben wird.
Gruß
-
18.08.11 08:00 #8
- Registriert seit
- Jun 2005
- Beiträge
- 8.168
Hi.
Da sind noch einige Fehler drin.
Insbesondere prüfst du immer noch nicht ob überhaupt etwas eingelesen wurde. Falls cin in einem Fehlerzustand ist, hast du eine Endlosschleife.
Und ich sehe nirgendwo das du auch Gleitkommazahlen in wissenschaftlicher Notation und neg. Zahlen akzeptieren würdest.
\edit:
Du müßtest dem GCC erstmal mitteilen welcher Zeichensatz zur Laufzeit verwendet werden soll. (-fexec-charset)
Wenn du das Programm unter einem deutschen Windows ausführst, ist der aktive Zeichensatz in der Konsole cp850. Das kannst du z.B. mit "chcp 65001" zu UTF-8 ändern (bzw. SetConsoleOutputCP). Du mußt aber noch die Schriftart der Konsole z.B. auf Lucida umstellen (damit Unicode Zeichen auch angezeigt werden können).
Du kannst auch den Eingabezeichensatz (Encoding deiner Datei) angeben (-finput-charset), dann mußt du nicht Escapesequenzen in Stringliteralen benutzen.
GrußGeändert von deepthroat (18.08.11 um 08:27 Uhr)
If at first you don't succeed, try again. Then quit. No use being a damn fool about it.
-
Hi,
Ich prüfe jetzt auch noch ob überhaupt etwas eingegeben wurde, wenn eine gültige Zahl eingegeben wurde, aber es Technisch ein Problem giebt, hilft es mit ja auch nichts zur nächsten Variablen weiter zu gehen. Im Hauptprogramm, dass den Header benutzt gibts sowieso ne Englosschleife, und das ist so gewollt.
Dass extrem große bzw. kleine Zahlen (die mit e drinnen) und negative nicht erlaubt sind finde ich gerade wunderbar, denn die meisten meiner Programme können sowieso nicht sinfoll mit ihnen arbeiten, so entfällt die nachträglich Prüfung auf > 0.
Bevor es wieder Probleme mit der Portierung, ect. giebt lasse ich die Paar umlaute lieber als ue, oe, ae, ... stehen, trotzdem Danke. Wahrscheinlich probiere ich es irgendwann nochmal.
javaDeveloper2011
-
18.08.11 11:45 #10
- 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.
-
Hi,
deshalb wollte ich ja des Beenden mit ESC ermöglichen.
Geht das irgendwie, also es soll immer möglich sein, auch ohne anschließenden ENTER-Druck.
Gruß
-
Ja, mit GetAsyncKeyState() oder GetKeyState() oder (ganz einfach): getch().
Gruss
cwriterIntel inside - Idiot outside :-)
Ich schreibe in C und bin Anfänger.
______________________________
Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
Danke
-
Sieht mir aber leider alles nach Windows-only aus.
-
getch() ist in der conio.h, glaube ich. Hat Linux die nicht?
Intel inside - Idiot outside :-)
Ich schreibe in C und bin Anfänger.
______________________________
Falls ich eines Tages einen guten Beitrag schreiben werde, bitte bewerten und/oder Danke sagen.
Danke
-
Nein, leider nicht.
Ähnliche Themen
-
Korrekt byteweise einlesen
Von Tim Bureck im Forum .NET CaféAntworten: 2Letzter Beitrag: 24.08.10, 19:01 -
Variablen anhängen geht nicht korrekt
Von kannaum im Forum PHPAntworten: 5Letzter Beitrag: 14.09.09, 16:53 -
Werte aus einem vector<double> einlesen und in Map schreiben
Von stevecmr im Forum C/C++Antworten: 15Letzter Beitrag: 15.01.09, 14:43 -
Variablen werden nicht korrekt ausgegeben
Von multimolti im Forum PHPAntworten: 7Letzter Beitrag: 28.03.07, 00:26 -
CSV-Datei korrekt einlesen
Von DanielBodensee im Forum Delphi, Kylix, PascalAntworten: 1Letzter Beitrag: 24.04.04, 22:46



6Danke

Zitieren


Login






