Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Nur Eingabe von Zahlen erlauben

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] [ 2 ] [ 3 ]
015
16.05.2003, 04:30 Uhr
Hans
Library Walker
(Operator)


Hallo zusammen,

hier mal eine Version zur Eingabeüberprüfung von mir.


C++:

/* Datei: nurzahl.c
   Ein Programm mit einer Routine, die nur Zifferneingaben erlaubt;
   für das C/C++ Forum

*/


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int zahlein();

int main()
{
  int a;

  printf ("Bitte Zahl eingeben. ");
  a=zahlein();
  printf ("\nDie Zahl ist: %d\n",a);

  return 0;
}

int zahlein()
{
  int c,w;

  w=0; /* In w "entsteht" die Zahl, die eigegeben wird. */
  do
   {  /* Lesen eines Zeichens aus der Standardeingabe, also der Tastatur */
      c = fgetc(stdin);

      /* Wenn c ein '\n' ist, die Schleife beenden */
      if (c=='\n')
              break;

      if ( !isdigit(c)) /* Wenn das Zeichen keine Ziffer ist, einen Fehler melden */
         { printf ("Fehler!\a %c ist keine Ziffer.\n", c);
           continue; /* Schleife von vorne beginnen, ohne den Rest ab zu arbeiten */
         }
      /* Anzeigen des Zeichens indem es in die Standardausgabe geschrieben wird */
      putc(c, stdout);

      /* Eingegebene Ziffer zur Zahl hinzu fügen (siehe Text) */
      w=w*10+(c-'0');
   } while (c);

  return w;
}


Sie ist nicht perfekt, aber sie meckert alles an, was keine Ziffer ist, und ignoriert es für die Zahl, die eingegeben wird. Wer also z.B. 305 eingeben will, stattdessen aber 3e0r5 eingibt, erhält folgende Ausgabe:

D: \borland\CommandLine\own>nurzahl
Bitte Zahl eingeben. 3e0r5
3Fehler! e ist keine Ziffer.
0Fehler! r ist keine Ziffer.
5
Die Zahl ist: 305

D: \borland\CommandLine\own>


Man kann zwischen den Ziffern also fast jeden Müll eingeben, erhält am Ende aber nur die Zahl, die sich aus den eingegebenen Ziffern ergibt.

Und nun die ausführliche (und hoffentlich für alle verständliche) Erklärung zu diesem Gebilde:


C++:
/* Eingegebene Ziffer zur Zahl hinzu fügen (siehe Text) */
      w=w*10+(c-'0');



Um an die Zahl zu kommen, die eingegeben wird, wird die jeweilige Zahl mit 10 multipliziert, und der Zahlenwert, der zuletzt eingegebenen Ziffer addiert. Um an den Ziffernwert zu kommen, wird vom Ziffernzeichen der Wert des ASCII-Codes '0' abgezogen.

Beispiel: Es wird die Zahl 123 eingegeben:

Im ersten Durchlauf der Schleife wird die '1' eingetippt. Der Wert von w ist noch 0; er wird mit 10 multipliziert, wodurch sich jetzt noch nichts ändert. In c steckt der ASCII-Code von '1'; durch die Aktion (c-'0') wird aus dem ASCII-code der Zahlenwert 1. Dieser wird jetzt zu w addiert, wodurch w=1 wird.

Im zweiten Durchlauf der Schleife wird die '2' eingetippt. Der Wert von w ist jetzt 1; er wird mit 10 multipliziert, wird jetzt also zu 10. In c steckt der ASCII-Code von '2'; durch die Aktion (c-'0') wird daraus der Zahlenwert 2. Dieser wird jetzt zu w addiert, wodurch w=12 wird.

Im dritten Durchlauf der Schleife wird die '3' eingetippt. Der Wert von w ist jetzt 12; er wird wieder mit 10 multipliziert, damit also zu 120. In c steckt jetzt der ASCII-Code von '3'; aus dem zuerst wieder der Zahlenwert 3 gemacht wird (c-'0'). Dieser wird jetzt zu w addiert, wodurch wir haben 123.

Okay, ich geb's ja zu, das ist "Hardcore-C" und setzt voraus, das der Rechner mit ASCII-Code arbeitet, aber das tun wohl die meissten PC's...
-----
Diese Erläuterung hatte ich zuerst im Quellcode, hab sie aber der besseren übersicht wegen heraus genommen.

Ach ja, @Heiko:

Zitat:
Was bist du eigentlich für einer.
Informatikstudent bzw. anderer Student, ehrlich arbeitender Bürger...

Was ich für einer bin? - Gute Frage. - Nächste Frage.
Sagen wir mal so: ich bin einer, der ein E(lektro)technikstudium mit Schwerpunkt IT abgebrochen hat, aber mit dem, was er im Studium gelernt hat, ein paar nützliche Dinge zu tun versucht, z.B. durch hilfreiche Beiträge in diesem Forum.

Hans
---
Edit: Erscheinung verbessert; ist mir jetzt erst aufgefallen, das die Darstellung etwas kaputt war...
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.

Dieser Post wurde am 13.01.2013 um 05:33 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
16.05.2003, 11:39 Uhr
~0xdeadbeef
Gast


inline-Methoden fressen halt Platz, und in Zeiten, in denen Compiler Sprungvorhersage können und Sprünge kaum noch Zeit fressen, macht die inline-Optimierung nur noch bei sehr kleinen Methoden a la

C++:
class A {
protected:
    int i;
public:
    inline int getI() { return i; }
};


Sinn.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
017
17.05.2003, 10:09 Uhr
~Der Computer
Gast


Vielen Dank für die Hilfe, ich kann jedoch die Vorschläge nicht so richtig in mein Programmeinbinden. Es funktioniert dann nicht mehr so. Hier soll dann eine Fehlermeldung kommen, wenn man was anderes als eine Zahl eingibt. Ich hoffe, ich helft mir nochmal, auch wenn ich euch bestimmt schon nerve!
Hier ist mal der komplette Quellcode:


#include <stdio.h>
#include <math.h>
#include <time.h>

main()
{
int i,x,zufallszahl;
char weiter[5];


do
{
printf("\n\t\t Zahlenraten zwischen 1 und 1000");
printf("\n\n\n\n\nBitte geben Sie eine Zahl ein: ");
scanf("%i",&x);
srand(time(NULL));
zufallszahl = rand() % 1000+1;

while(zufallszahl != x)
{

if(zufallszahl<x&&x<1000)
{
printf("\n\n\nIhre Zahl ist zu gross");
}
if(x<1)
{
printf("\n\n\nIhre Zahl liegt unter dem gesuchten Bereich!");

}
if(x>1000)
{
printf("\n\n\nIhre Zahl liegt ueber dem gesuchten Bereich!");

}
if(zufallszahl>x&&x>1)
{
printf("\n\n\nIhre Zahl ist zu klein");

}

printf("\n\nBitte geben Sie erneut eine Zahl ein: ");
setvbuf (stdin, NULL, _IONBF, 0);
setvbuf(stdin, NULL, _IOFBF, BUFSIZ);
scanf("%i",&x);
}

printf("\n\n\n\n");
printf("\nERRATEN!!!");

printf("\n\n\nMoechten Sie fortfahren? ja/nein");
scanf("%s",weiter);
}
while (weiter[0]=='j' || weiter[0 =='J');
}
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
018
18.05.2003, 08:18 Uhr
Hans
Library Walker
(Operator)


Hallo Sara,

so wie ich Dich verstanden habe, kann man Dein Problem nur lösen, indem man sich von scanf verabschiedet, und stattdessen eine andere Art der Zahleneingabe wählt. Denn scanf liefert bei fehlerhaften Eingaben, (in Deinem Fall was anderes als Ziffern) im besten Fall eine Null zurück. Wahrscheinlicher ist aber, dass scanf einfach abbricht, und gar nichts, bzw irgendwas undefiniertes zurück liefert.
Deshalb hier mal eine abgeänderte Version von Deinem Programm. Die meisten Änderungen sind im Quelltext kommentiert. Hier aber folgendes:
Ich hab die Aufrufe von scanf durch Aufrufe der Funktion zahlein() ersetzt, die ich gestern schon gepostet habe. (Ich hoffe, das dadurch auch klar wird, was sie macht, auch wenn das wie noch unklar bleibt.)
Deine Pufferzuordnungen mittels setvbuf() ergeben meiner Ansicht nach nicht viel Sinn, weshalb ich sie auskommentiert habe.
Dann war noch ein logischer Fehler bei Deiner Bereichüberprüfung:

C++:
if(zufallszahl<x && x<1000)
if(zufallszahl>x && x>1)

Wenn man da nämlich 1 bzw. 1000 eingibt, sagt einem das Programm nur, das man eine neue Zahl eingeben soll, aber nichts darüber, ob die eingegebe Zahl zu gross oder zu klein war. (Ist hier zwar nichts schwerwiegendes, kann aber verwirren).
Doch jetzt erst mal das Programm:

C++:
/* Datei: zalnratn.c

   Eine Version des berühmten Zahlenraten Programms von Sara (Der Computer)
   aus dem C/C++ Forum
  
   (mit einer Lösung ihres Problems made by Hans)
*/


#include <stdio.h>
#include <stdlib.h>    /* für rand() und srand() */
#include <ctype.h>   /* für isdigit() in der Funktion zalein() */
#include <time.h>     /* für time() */
/* Weil in diesem Programm keinerlei höhere Mathematik betrieben wird, brauchen
   wir <math.h> nicht. */


/* Prototyp für eine eigene Funktion */
int zahlein(void);

main()
{
  int i,x,zufallszahl;                                        
  char weiter;

  srand(time(NULL)); /* Sollte vor der Schleife stehen, weil es nur einmal
                                beim Programmstart benötigt wird */

  do
  {
    zufallszahl = rand() % 1000+1; /* Erst die Zahl "ausdenken", dann mit raten
                                                  anfangen lassen. (Erscheint mir jeden-
                                                  falls logischer ;-) */

    printf("\n\t\t Zahlenraten zwischen 1 und 1000");
    printf("\n\n\nBitte geben Sie eine Zahl ein: ");
    fflush(stdin); /* Eingabepuffer leeren */
    x=zahlein(); /* Vom Benutzer eine Zahl eingeben lassen */
    i=1;    /* Damit zähle ich jetzt die Eingaben durch den Benutzer */

    while(zufallszahl != x)
    {
      if(zufallszahl<x && x<=1000) /* Hier den Vergleich zu x<[b]=[/b]1000 geändert */
      {                                     /* Siehe Text, was das soll */
         printf("\n%3d ist zu gross", x);
      }
      if(x<1)    
      {
         printf("\n%3d liegt unter dem gesuchten Bereich!", x);
      }
      if(x>1000)
      {
         printf("\n%3d liegt ueber dem gesuchten Bereich!", x);
      }

      if(zufallszahl>x && x>=1)  /* Hier den Vergleich zu x>[b]=[/b]1 geändert */
      {                                 /* Siehe Text, was das soll */
         printf("\n%3d ist zu klein", x);
      }
      printf("\n\nBitte geben Sie erneut eine Zahl ein: ");
      /*
       setvbuf (stdin, NULL, _IONBF, 0);
         setvbuf(stdin, NULL, _IOFBF, BUFSIZ);
      */

      x=zahlein(); /* Vom Benutzer eine Zahl eingeben lassen */
      i++;           /* Eingaben mitzählen */
    }
    printf("\nERRATEN!!!");
    printf("\n(Mit %i Versuchen.)", i);

    printf("\n\n\nMoechten Sie fortfahren? ja/nein");
    fflush(stdin);
    weiter = fgetc(stdin);
  }
  while (weiter=='j' || weiter=='J');

  return 0; /* Damit der Compiler die Warnung
                   Warning W8070 Zalnratn.c 60: Function should return a value...
                   nicht mehr ausgeben muss */

}

/* Funktion zur Eingabe von Zahlen;
    Es werden nur Ziffernzeichen akzeptiert, bei allen anderen Zeichen
    erscheint eine Fehlermeldung.
    Die Funktion erwartet keine Parameter, und gibt eine int-zahl zurück */


int zahlein(void)
{
  int c,w;

  w=0; /* In w "entsteht" die Zahl, die eigegeben wird. */
  do
   {  /* Lesen eines Zeichens aus der Standardeingabe, also der Tastatur */
      c = fgetc(stdin);

      /* Wenn c ein '\n' ist, die Schleife beenden */
      if (c=='\n')
              break;

      if ( !isdigit(c)) /* Wenn das Zeichen keine Ziffer ist, einen Fehler
                             melden */

         { printf ("Fehler!\a %c ist keine Ziffer.\n", c);
           continue; /* Schleife von vorne beginnen, ohne den Rest ab zu
                             arbeiten */

         }
      /* Anzeigen des Zeichens indem es in die Standardausgabe geschrieben
          wird */

      /* putc(c, stdout); */

      /* Eingegebene Ziffer zur Zahl hinzu fügen (siehe Text) */
      w=w*10+(c-'0');
   } while (c);

  return w;
}


Ich hoffe, das kommt Deinen Vorstellungen von der Lösung des Problems nahe, obwohl ich vermute, das ich Deinem Kurs ein wenig vorgreife...

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.

Dieser Post wurde am 18.05.2003 um 08:26 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
019
18.05.2003, 18:32 Uhr
~Der Computer
Gast


Vielen Dank für deine Hilfe. Hast mir sehr geholfen. Ich habe das Ganze jetzt auch verstanden!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
020
25.05.2003, 17:18 Uhr
~Der Computer
Gast


Hy!

Ich habe bei meinem Programm jetzt noch ein winziges Problem. Vielleicht weißt du ja, woran es liegt. Immer wenn ich einen Buchstaben statt einer Zahl eingebe, gibt er mir aus, dass dies keine Ziffer ist und danach kommt immernoch, dass die Zahl '0' unter dem gesuchten Bereich liegt. Gebe ich aber z.B. 33e4 ein, so kommt dies nicht. Ich habe herausgefunden, dass es daran liegt, dass w am Anfang auf '0' gesetzt wird. Ich habe da nämlich einfach mal an den Anfang w=1 geschrieben, dann gab er mir bei Eingabe eines Buchstaben auch erst die normal Meldung mit der Ziffer aus und danach, dass die Zahl 1 zu klein ist.
Wie kann ich es also machen, dass er mir bei Eingabe eines Buchstaben nur die Meldung, dass es keine Ziffer ist, ausgibt und nicht noch, das 0 unter dem gesuchten Bereich liegt?

Sarah
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
021
26.05.2003, 04:19 Uhr
Hans
Library Walker
(Operator)


Hallo Sara(h),

Zitat:
Ich habe bei meinem Programm jetzt noch ein winziges Problem. Vielleicht weißt du ja, woran es liegt. Immer wenn ich einen Buchstaben statt einer Zahl eingebe, gibt er mir aus, dass dies keine Ziffer ist und danach kommt immernoch, dass die Zahl '0' unter dem gesuchten Bereich liegt. Gebe ich aber z.B. 33e4 ein, so kommt dies nicht.

Das hat mit dem Aufbau der Funktion zahlein() zu tun. Die Definition
Code:
[b]int[/b] zahlein(void)
bedeutet nämlich, das diese Funktion einen int-wert zurück gibt, und zwar immer, und egal was man eigegeben hat. Auch wenn Du nur die RETURN-Taste drückst. Das sie dann den Wert Null zurück gibt, liegt wie Du richtig heraus gefunden hast, daran, das w am Anfang auf Null gesetzt wird. Das ist wiederum nötig, damit die Rechnung
Code:
w=w*10+(c-'0');
korrekt ausgeführt wird. Wenn Du in der Funktion w auf 1 belässt wird sie Dir immer falsche Werte liefern. Und zwar solche, die immer um eine Zehnerpotenz grösser sind als das, was Du eingegeben hast. Das kannst Du ganz leicht überprüfen, indem Du anstelle Deines Programms sowas in dieser Art in main() rein schreibst:


C++:
int x;

printf("Bitte geben Sie eine Zahl ein: ");
x=zahlein();
printf ("\nSie haben die Zahl %d eingegeben.\n", x);



Jetzt Fragst Du Dich wahrscheinlich, warum das nun wieder so ist, oder?
Nun, darauf gehe ich jetzt nicht ein, weil das etwas lang ausfallen wird, wie ich mich kenne...
Deshalb jetzt zurück zu Deiner Frage:

Zitat:
Wie kann ich es also machen, dass er mir bei Eingabe eines Buchstaben nur die Meldung, dass es keine Ziffer ist, ausgibt und nicht noch, das 0 unter dem gesuchten Bereich liegt?

Das Problem kannst Du am Besten lösen, indem Du nach dem Aufruf von zahlein() eine Abfrage auf Null einbaust, also:


C++:
...
printf("\n\nBitte geben Sie erneut eine Zahl ein: ");
x=zahlein(); /* Vom Benutzer eine Zahl eingeben lassen */
if (x==0)
    printf("Sie müssen eine Zahl eingeben!\n");



Wenn Du die Abfrage aber so in Dein Hauptprogramm einbaust, wirst Du trotzdem noch weiter die Meldung bekommen, das die Zahl Null unter dem gesuchten Bereich liegt. Das ist aber wahrscheinlich nicht das, was Du willst. Also müssen wir das ganze etwas Trickreicher (aber auch umfangreicher) anstellen, z.B. so:


C++:
do
{ printf("\n\nBitte geben Sie erneut eine Zahl ein: ");
   x=zahlein();
   if (x==0)
      printf("Sie müssen eine Zahl grösser oder gleich 1 eingeben!\n");
} while (x==0);



Das ist zwar wahrscheinlich auch nicht so ganz dass, was du Dir vorstellst, aber was besseres fällt mir gerade nicht ein.

Man könnte zwar die Funktion zahlein() noch etwas erweitern, aber das ist auch nicht unbedingt im Sinne des Erfinders. Ich hatte die Funktion nämlich ursprünglich nur zur Eingabe von Zahlen gedacht. Die Bereichsüberprüfung war als Aufgabe für den Aufrufer vorgesehen, in diesem Fall also das Hauptprogramm.

So, ich hoffe, das hilft jetzt erst mal weiter,

Hans

P.S. Wie schreibst Du Dich denn jetzt richtig, mit oder ohne 'h' am Ende?
---
Edit: cpp-Tags so gesetzt, das der Text auch richtig formatiert wird...
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.

Dieser Post wurde am 13.01.2013 um 05:41 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
022
26.05.2003, 16:41 Uhr
Der Computer



Hy!

Ich schreibe mich ohne h! Werde deine Idee mal ausprobieren. Schonmal vielen Dank!

Sara
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] [ 2 ] [ 3 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: