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 ]
010
14.05.2003, 22:52 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


genau das habe ich doch mit hilfe des ascii codes gemacht


C++:
//diese funktion liefert true wenn der übergebenen string(chararray) eine Nummer ist sonst false
bool isNumber(char* c){
int i,pointflag=0;
    if (c[0]==45 || c[0]==43) i=1;else i=0;     //check ob der user ein + oder - eingegeben hat in ascii 45 und 43      
    for (i=i;i<(int)(strlen(c));i++){  //für jedes Zeichen des strings              
     if (c[ i ]==46 && pointflag) return false; //wenn es ein punkt ist und bereits ein punkt gefunden wurde, dann fehler
     if ((c[ i ]<48) || (c[ i ]>57) ) //wenn es keine zahl ist (zahlen gehen in ascii von 48 bis 57 wobei 48 die 0 ist und 57 die 9
         if (c[ i ]==46) pointflag=1; else return false; //dann schau nach ob das ein punkt ist
    
    }
return true;
}



jetzt scanst du einfach einen string (bzw.chararray) ein und schaust nach ob der user eine Nummer eingegeben hat (mittels isNumber);
wenn ja kannst du mit hilfe von atof den string in eine Nummer umwandeln

jetzt alles klar?
--
...fleißig wie zwei Weißbrote

Dieser Post wurde am 14.05.2003 um 22:52 Uhr von Heiko editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
15.05.2003, 08:24 Uhr
virtual
Sexiest Bit alive
(Operator)


@Heiko
Generell ist die Verwendung von Literalen den ASCII Codes vorzuziehen (es sei dann, man hat irgendeinen Contest wer schreibt das kürzeste Programm ). also 45 => '+' (oder war es '-') und so weiter. Das erhöht nicht nur die lesbarkeit, sondern macht den Code auch portabler (nämlich zu Computern, die kein ASCII haben). Auch diese Abfrage:

C++:
if ((c[ i ]<48) || (c[ i ]>57) )


Läßt sich mittels isdigit nicht nur lesbarer, sondern in manchen Fällen auch performanter gestalten mit:

C++:
if (isdigit(c[i]))


Lesbarer sollte sofort einleuchten, aber permanter? - isdigit wird auf manchen Systemen als inline mit genau der gleichen Implementation bereitgestellt, wie Deine if Abfrage (dann also kein Unterschied), auf anderen System aber kann isdigit auch so implementiert sein, daß einfach ein lookup in ein Array gemacht wird, so daß das isdigit so expandieren könnte (nur skizze):

C++:
bool isdigit_array[256] = { false, false, ... , true /* '0' */, ..., true /* '9' */, ..};

if (isdigit_array[c[i]])


Also so nur 2x Pointer dereferenzieren, im Gegensatz zu 2x Dereferenzieren und 2x Vergleichen...
Es gibt jeodch wie gesagt keine Garantie, wie das isdigit genau implementiert ist; wohl kaum jedoch langsamer als die Deinige variante.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
15.05.2003, 12:10 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


@virtual
oh schöne funktion dieses isdigit ,kannte ich mal wieder nicht.

mal wieder eine dumme frage:
was ganau ist inline-Implementation? (immer diese Fachbegriffe von den ich kein Plan habe)



Gruss Heiko
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
15.05.2003, 12:52 Uhr
virtual
Sexiest Bit alive
(Operator)


Inline bedeutet soviel wie: Rufe nicht die Funktion auf, sondern füge deren Body an Stelle des Funktionsaufrufs direkt ein. Wird ganz gerne bei simplen Methoden gemacht:

C++:
[b]inline[/b] void func()
{
   printf("Blabla\n");
}

void test()
{
   func();
}


kann dann vom Compiler zu

C++:
void test()
{
   printf("Blabla\n");
}


Expandiert werden. Allerdings ist dies kein Muß für den Compiler, nur eine Empfehlung. In einigen Fällen kann der Compiler gar kein inline berücksichtigen, zB bei virtuallen Methoden, oder dann, wenn die Methode als Callback verwendet wird und daher ein Pointer auf sie benutzt wird.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
15.05.2003, 13:01 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)


@virtual
Wenn ich das richtig verstanden habe ist das also sowas ähnliches wie ein makro. leuchtet mit dann zumindestens ein dass das schneller ist.
Was passiert denn, wenn du was inline definierst und das dann aus irgenwelchen gründen nicht möglich ist das inline auszuführen?
Um es anders auszudrücken, ist es besser einfach überall inline vorzuschreiben?
Wenns geht dann gut wenn nicht dann halt eben nicht oder was hätte das für nachteile?

und was genau ist dann eine virtualle Methode (sollte dir bei deinem Nick ja nicht schwer fallen zu erkären)

Gruss Heiko
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
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
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: