2016-06-21 11 views
2

Dies ist eine erweiterte Frage dieses: Is std::string suppose to have only Ascii charactersWie der Benutzer zwingen kann/O zur Eingabe von ASCII-String

Ich mag eine einfache Konsolenanwendung erstellen, die von dem Benutzer als Satz von Zeichen einen Eingang nehmen. Diese Zeichen umfassen 0->9 Ziffern und a->z Buchstaben.

Ich beschäftige mich mit Eingabe unter der Annahme, dass es eine Ascii ist. Zum Beispiel verwende ich etwas wie: static_cast<unsigned int>(my_char - '0'), um die Nummer als unsigned int zu erhalten.

Wie kann ich diesen Code plattformübergreifend machen? Wie kann ich sagen, dass ich möchte, dass die Eingabe immer Ascii ist? Oder ich habe viele Konzepte verpasst und static_cast<unsigned int>(my_char - '0') ist nur ein schlechter Weg?

P.S. In Ascii (mindestens) Ziffern haben Sequenz Reihenfolge. Bei anderen Kodierungen weiß ich nicht, ob sie es haben. (Ich bin mir ziemlich sicher, dass sie sind, aber es gibt keine Garantie, nicht wahr?)

+3

[FYI] 'static_cast (my_char - '0')' funktioniert garantiert in allen Zeichensätzen, die C++ verwendet. – NathanOliver

+0

@NathanOliver mmm Ich vermutete das .. Allerdings war es nur ein Beispiel .. Ich werde noch eins hinzufügen. Danke –

+1

@NathanOliver: Aber nicht in allen Zeichensätzen, die der Benutzer eingeben kann. In MOST-Zeichensätzen ist der ASCII-Zeichenbereich derselbe. Aber das stimmt nicht in ALLEN Zeichen. ZB verwendet EBCDIC nicht die gleichen "char" -Werte für ASCII-Nummern ("0" ist 0x30 in ASCII, aber ist 0xF0 in EBCDIC), und EBCDIC verwendet keine sequenziellen Bereiche für alle ASCII-Buchstaben. Sie müssen also den Eingabe-Zeichensatz bei der Verarbeitung berücksichtigen. 'std :: string' kennt nur' char' Werte, aber nicht was sie darstellen. –

Antwort

2

, wie der Benutzer/OS zur Eingabe

eine ASCII-Zeichenkette zwingen kann

Sie können nicht, es sei denn, Sie der Benutzer angeben kann die numerischen Werte einer solchen ASCII-Eingabe.

Es hängt alles davon, wie die Anschluss Implementierung std::cin Tastenanschläge übersetzt wie 0 auf eine bestimmte Anzahl dienen verwendet, und was Sie erwarten, dass die Zahl der Toolchain angepasst damit für '0' intrinsische Übersetzung ist.

Sie sollten keine ASCII-Werte explizit erwarten (z. B. mit magischen Zahlen), aber char Literale, um portablen Code bereitzustellen. Die Annahme, dass my_char - '0' den tatsächlichen Ziffernwert ergibt, gilt für alle Zeichensätze. Die C++ Standard Zustände in [lex.charset]/3, der

Der Basissatz Ausführungszeichen und der Grundausführung Breitzeichensatz treffen jeweils alle Mitglieder der Grundquellenzeichensatz enthalten, sowie Steuerzeichen repräsentieren alert Backspace und Carriage Return sowie ein Nullzeichen (jeweils ein Null-Wide-Zeichen), dessen Darstellung alle Null-Bits aufweist. Für jeden grundlegenden Ausführungszeichensatz dürfen die Werte der Elemente nicht negativ und voneinander verschieden sein. Sowohl in den grundlegenden als auch in den ausführenden Zeichensätzen muss der Wert jedes Zeichens nach 0 in der obigen Dezimalziffernliste um eins größer sein als der Wert des vorherigen Zeichens. [...]

Hervorhebung von mir

+0

'Wie kann der Benutzer/OS zwingen, eine ASCII-Zeichenfolge einzugeben' - Sie können - ein Sturmgewehr kaufen und hinter ihnen stehen. Sie neigen dann dazu, einzugeben, was Sie von ihnen verlangen. –

+0

@EdHeal Ich bin kein Fan des Stils _columbine massacre_, um Benutzer zu zwingen. :-P ... Obwohl der Benutzer in diesem Fall völlig unschuldig ist, kann er eingeben, was er will, es ist der Code, der dafür verantwortlich ist, diese Eingaben korrekt zu interpretieren. –

+0

Bearbeitet, um den Cite aus dem Standard – NathanOliver

1

Sie können nicht überprüfen, zwingen oder sogar, dass vorher. "Böser Benutzer" kann immer eine UTF-8 kodierte Zeichenfolge in Ihre Anwendung schleichen, ohne Zeichen über U + 7F. Und diese Zeichenfolge ist auch Ascii-codiert.

Unabhängig von der plattformspezifischen Maßnahme können Benutzer auch eine UTF-16LE-codierte Datei pipen. Oder /dev/urandom

Ihre Fehler Zeichenfolge Codierung mit einigen magischen Eigenschaft eines Eingabestreams - und es ist nicht. Es ist gut, Kodierung, wie JPEG oder AVI, und muss genau auf die gleiche Weise gehandhabt werden - lesen Sie eine Eingabe, stimmen Sie mit Format überein, berichten Sie über Fehler beim Analysieren des Misserfolgs.

Wenn Sie nur ASCII akzeptieren möchten, lesen Sie den Eingangsstrom Byte für Byte und werfen/beenden Sie mit Fehler, wenn Sie jemals ein Byte mit dem Wert außerhalb der ASCII-Domäne finden.

Wenn Sie jedoch später auf ein Terminal stoßen, das Daten mit einer inkompatiblen Codierung wie UTF16LE bereitstellt, haben Sie keine andere Wahl, als eine Erkennung (basierend auf der Byte-Reihenfolge) und eine Konvertierungsroutine zu schreiben.