C Prorammierung- Bereichsüberschreitung verhindern bei Rechnerprogramm



  • Hallo Leute,

    Bin ein C-Neuling und bitte euch deswegen um Hilfe, ich hoffe, dass ich mein Problem verständlich genug darlege. 🙂
    Ich habe ein Problem, und zwar verstehe ich nicht wie eine Bereichsüberschreitung in C verhindert werden kann.
    Ich versuche gerade einen Short Int Rechner zu programmieren, der zwei Zahlen zusammenrechnet. Das Rechenprogramm an sich ist soweit geschrieben, nun möchte ich mit einer Funktion, nennen wir sie check(), beim einlesen einer Zahl prüft, ob der Bereich von Short Int überschritten wird. Der Bereich ist in diesem Fall, logischerweise wegen Short Int, für positive Zahlen 32767 und negative Zahlen -32768.

    Das Grundprinzip hinter der Prüfung, soweit ich das mit bisherigen nachschlagen verstanden habe, ist die zu prüfende Zahl in einen String einzulesen und in einer Schleife die Zahl kontrollieren zu lassen.

    Mein bisher geschriebener Code der Funktion lautet wie folgt. Wenn 1 returned wird, ist die Zahl im gültigen Bereich. Wenn 0 returned wird, dann ist die Zahl ungültig und muess erneut eingegeben werden.

    short int check(char s[])	//Zu prüfende Zahl, wird in String eingelesen		
    {
      short int index = 0;							//Index-Variabel die Stelle des Strings repräsentiert
    
      if((s[index]=='+')||((s(s[index]=='-')) index++;
    	  if(strlen(s)>5) return(0);
    	  if(s[index+0]<'3') return(1);
    	  if(s[index+0]>'3') return(0);
    	  if(s[index+1]<'2') return(1);
    	  if(s[index+1]>'2') return(0);
    	  if(s[index+2]<'7') return(1);
    	  if(s[index+2]>'7') return(0);
    	  if(s[index+3]<'6') return(1);
    	  if(s[index+3]>'6') return(0);
    	  if(s[index+4]<'7') return(1); //Hier bin ich mir nicht sicher, ob es noch eine extra Kondition für den Min. Wert braucht, der ja '8' (-32678) und nicht '7' (+32678) ist an letzter Stelle.
    	  return(1);
    }
    

    Der Test im Hauptprogramm würde dann, vor der jeweiligen Zahl, wie folgt sein:

    do
    {
    printf("Bitte Zahl eingeben:\n");
    scanf("%d", &zahl1);
    if(!check(zahl1)
    {
     printf("Ungueltige Zahl! Ausserhalb des Wertebereichs! Maximale positive Zahl: 32767, Maximale negative Zahl: -32768!")
    }
    else
    {
    zahl1=atoi(zahl1)  //Konvertiert String in Int Zahl zurück(Oder habe ich das falsch verstanden?)
    }
    }while(!check(zahl1))
    

    Oder mein Zweiter Vorschlag, bei welchem anstatt 1 oder 0, direkt in der Funktion zur Neueingabe aufgefordert wird. Jedoch wäre es mir lieber das Problem mit der oben genannten Funktion zu lösen, oder wäre es so doch einfacher?:

    while(s < INT_MIN || s > INT_MAX)  //s steht in diesem Fall für die eingegebene Zahl, INT_MIN für -32768 INT_MAX für 32767
    {
    printf("Ungueltige Eingabe, Bereich überschritten! Bitte Zahl erneut eingeben!")
    scanf("%d", s);
    }
    return s;
    

    Vielen Dank für die Erklärung!

    Mfg Ethic


  • Mod

    Ich habe mir jetzt nicht alles durchgelesen. Die Idee mit dem Umwandeln in String klingt jedenfalls furchtbar umständlich. Das ist doch eine Problemstellung die man mit Mathematik lösen kann. Du musst dir Gedanken machen, welche Bedingungen bei welcher Rechenoperation im Voraus gegeben sein muss, damit es nicht zu einem Überlauf kommen kann. Und dann prüfst du da drauf. Du musst dir die Gedanken noch nicht einmal selber machen, das haben schon andere getan, guck mal hier:
    http://msdn.microsoft.com/en-us/library/ms972705
    Der Artikel ist zwar für C++, aber die ganze Theorie gilt genau so auch für C, bloß für die SafeInt-Klasse musst du von C++ nach C übersetzen, sofern du sie denn nutzen möchtest.



  • Zur Konvertierung von einem String in ein int gibt es strtol() (STRing TO Long)

    Zum einen passt ein short in ein long und du kannst die Grenzen mit Hilfe des long überprüfen. Und wenn die Zahl auch nicht mehr in ein long passt, kannst du das auch feststellen.

    If the correct value is out of the range of representable values, LONG_MAX or LONG_MIN is returned, and the global variable errno is set to ERANGE.

    Mit atoi() kannst du das nicht feststellen.



  • Ethic schrieb:

    zahl1=atoi(zahl1)  //Konvertiert String in Int Zahl zurück(Oder habe ich das falsch verstanden?)
    

    Ja, hast du. Das funktioniert natürlich so nicht.
    Man kann auch scanf die Arbeit machen lassen, aber dazu muss man auch den Rückgabewert auswerten.
    Statt

    do
    {
    printf("Bitte Zahl eingeben:\n");
    scanf("%d", &zahl1);
    if(!check(zahl1)
    {
    

    also in etwa

    int zahl1;
    do
    {
    printf("Bitte Zahl eingeben:\n");
    }
    while( 1!=scanf("%d", &zahl1) || zahl1<SHRT_MIN || zahl1>SHRT_MAX );
    

    Wie du siehst hat short int eigene Grenzen und nicht die von dir verwendeten INT_MAX/INT_MIN, auch fehlt natürlich noch das Eingabepufferlöschen.


Anmelden zum Antworten