scanf-Eingabe überprüfen beim C-Programm?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Man kann bei scanf angeben, welche Zeichen erlaubt sind. Das geschieht ähnlich wie bei printf wo man führende Nullen und Anzahl der Nachkommastellen einstellen kann.

Genaues findet man in der C Referenz zum Befehl: http://www.cplusplus.com/reference/cstdio/scanf/

Möchtest Du aber das selber prüfen und entsprechend darauf reagieren anstatt nur ungültige Eingaben zu verweigern und den Code dann trotzdem weiter laufen zu lassen, kannst Du die Eingabe als einen String machen und den dann Byte für Byte prüfen bevor die Eingabe dann mit atoi() oder anderen Funktionen in eine Zahl umgewandelt wird.

Dazu nimmt man einfach einen pointer vom typ char der auf den String zeigt. Dann braucht man nur noch eine FOR-Schleife die zwischen 0 und Stringgröße (strlen() ) läuft. Bei jedem durchlauf inkrementiert man den pointer (pointer ++;) um auf das nächste Zeichen weiter zu schalten.

Hier kann man dann mit der Funktion "isdigit()" heraus finden, ob es eine Ziffer ist oder nicht und mit weiteren if-Abfragen z.B. ein Komma in einen Punkt umwandeln

if (*pointer == ',')
  *pointer = '.';

Das ist gerade bei Programmen die auf PCs mit deutschen Einstellungen laufen sehr nützlich da sonst alle Nachkommastellen abgeschnitten werden weil scanf oder andere Funktionen einen DezimalPUNKT erwarten und das Komma für die Trennung von zwei seperaten Ziffernfolgen halten.

Findet man eine "Echte Null" (Zeichen '\0'), dann kann man die FOR-Schleife abbrechen da das Stringende erreicht wurde.

Woher ich das weiß:Berufserfahrung
Commodore64  24.03.2021, 19:10

P.S.:

mit "toupper()" oder "tolower()" kann man Buchstaben (z.B. bei HEX) so umwandeln, dass man nur ein mal prüfen muss ob das Zeichen zwischen 'A' und 'F' liegt, also ein gültiges HEX-Zeichen ist.

Auch kann man so leicht das D, H oder B erkennen um herauszufinden ob die Eingabe in DEZ, HEX oder BIN erfolgt, dann kann der User auch "123d" oder "123dez" schreiben. Das erkannte Zeichen überschreibt man einfach mit einer '\0' und bricht die Schleife ab. Damit wird dann alles nachfolgende abgeschnitten, da '\0' das Stringende signalisiert. In einer Variable merkt man sich dann ob das DEZ, HEX oder BIN weiter verarbeitet werden soll.

0
Commodore64  24.03.2021, 19:16
@Commodore64

Aufpassen muss man nur darauf, dass ein "D" sowohl Teil einer HEX Zahl sein kann als auch DEZ symbolisieren kann. Hier mit prüfen ob das nächste Zeichen ( *(pointer+2) ein 'Z'" ist, also Teil von "DeZ" ist. Ist weder H noch B vorhanden, immer als DEZ behandeln und ggf. vor der Eingabe den Hinweis ausgeben, dass man mit "h" oder "b" am Ende auf HEX bzw. BIN umschalten kann.

0

wie meinst du das , du kannst angeben wie die interpretation laufen soll , also die formatierung .

z.b.

  printf ("Enter your age: ");
  scanf ("%d",&i);

hier werden nur zahlen interpretiert .

https://www.cplusplus.com/reference/cstdio/scanf/

Mit der Formatierung %[···] (statt %s) kannst du angeben, welche Zeichen gültig sind. So kannst Du ein optionales Vorzeichen und eine 12er-Zahl als String einlesen:

char sign[2]="", input[32]="";
if (2==scanf("%1[+-]%31[0-9yz]", sign, input))
    ...

Danach ist sign garantiert "+", "–" oder "", und input enthält nur die Zeichen '0'-'9', 'y' und 'z'. Sobald ein anderes Zeichen eingegeben wird, bricht die Eingabe ab. Gewöhnlich passiert das bei <Return>, aber du kannst dieses Zeichen auch extra lesen und schauen, ob es wirklich ein Whitespace ist oder ein Eingabefehler vorliegt:

char sign[2]="", input[32]="", end=' ';
if (2<=scanf("%1[+-]%31[0-9yz]%c", sign, input, &end))
{
    if (!isspace(end))
    {
        printf( "Eingabefehler: '%c' ist nicht 0-9, y oder z", end);
    }
    else
        ...
}

Mit strtol(input, NULL, 12) kannst Du die Eingabe dann in einen long umwandeln. Die Ausgabe zur Basis 12 (long⇒String) musst Du aber selbst programmieren.