Probleme beim Einbinden von Funktionen



  • Hallo Community,

    ich bin absoluter C - Neuling, muss aber für eine Prüfung ein Programm schreiben.
    Doch dabei bin ich nun auf Probleme gestoßen.
    In diesem Programm soll ein User 10 Ergebnisse von Bowlingwürfen eintragen, welche dann sortiert und ausgewertet werden.
    Die Eingabe des Ergebnisses erfolgt unter main(), sowie auch eine Überprüfung, ob die eingegebene Zahl übehaupt sinnvoll ist (0<=Zahl<=10).
    Eine vorherige Überprüfung, ob die Eingabe überhaupt eine Zahl (vom Typ int) ist, soll in einer weiteren Funktion erfolgen. Sortierung und Auswertung der Ergebnisse erfolgen ebenfalls in je einer eigenen Funktion.
    Allerdings schaffe ich es nicht, das Programm zum laufen zu bekommen; es stürzt direkt nach der Eingabe des ersten Ergebnisses ab.
    Die Unterfunktionen habe ich allerdings alle einzeln getestet und dabei haben sie funktioniert. Nur im Zusammenspiel stürzt mir das Programm ab.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>     //Wird für den Befehl strlen() benötigt
    
    int integer (char eingabe[]);
    int sortierung (int ergebnis[10]);
    void auswertung (int ergebnis[10]);
    
    int main(int argc, char *argv[])
    {
      int wurf;           //Zählvariable für die Nummer des Wurfes
      char *eingabe;      //String variabler Länge zur Speicherung der Tastatureingabe
      int a=0;            //Variable für Integer-Wert des Strings "eingabe"
      int ergebnis[10];   //Array zum Speichern der Wurfergebnisse
      int b=0;            //Variable zur Speicherung des Ergebnisses von integer()
    
      printf("Ergebnisse der W\x081rfe eingeben.\n Fehlwurf mit 0.\n\n");
    
      for (wurf=0;wurf<10;wurf++)
        {
          do
            {
              printf("Geben Sie das Ergebnis des %i. Wurfs ein: ", a+1);
              gets(eingabe);
    
              if (integer(eingabe)==1)
                {
                  a=atoi(eingabe);   
                  if ((a<0)||(a>10))
                    {
                       printf("Dieses Ergebnis kann mit einem Wurf beim Bowling nicht erreicht werden.\nBitte geben Sie eine ganze Zahl von 0 bis 10 ein.\n\n");                 
                    }
                  else
                    {
                      ergebnis[wurf]=a;
                    }                   
                }
              else
                {
                  printf("Diese Eingabe ist nicht korrekt.\nBitte geben Sie eine ganze Zahl von 0 bis 10 ein.\n\n");    
                }             
            }
            while((integer(eingabe)==0)||(a<0)||(a>10));
        }
    
      sortierung(ergebnis);
    
      auswertung(ergebnis);
    
      system("PAUSE");	
      return 0;
    }
    
    //Funktion zur Überprüfung des Datentyps vom String "eingabe"
    int integer (char eingabe[])
    {
      int b=0;                   //Rückgabevariable
      int c;                     //Laufvariable
      int anz_zahl=0;            //Variable für die Anzahl der Zahlen im String "eingabe"
      int d=0;                   //Variable zur Ermittlung der Stringlänge
    
      d=strlen(*eingabe);
    
      for (c=0;c<10;c++)  
        {
          if((eingabe[c]>='0')&&(eingabe[c]<='9'))  
            {
              anz_zahl +=1;                                        
            }                
        }
    
      if (anz_zahl==d)
        {
          b=1;              
        }   
      return b;
    }
    
    //Funktion zur Sortierung des Arrays ergebnis[]
    int sortierung (int ergebnis[10])
    {
      int e;            //Laufvariable für die einzelnen Indizes des Arrays ergebnis[]
      int f;            //zweite Laufvariable für die Indizes des Arrays ergbnis[]
      int temp=0;       //Variable zum Zwischenspeichern einzelner Werte aus dem Array
    
      for (e=0;e<9;e++)                                           
        {
          for (f=e+1;f<10;f++)
            {
              if (ergebnis[e]>ergebnis[f])
                {
                  temp=ergebnis[f];
                  ergebnis[f]=ergebnis[e];
                  ergebnis[e]=temp;                                      
                }                                   
            }
        }
      return (ergebnis[10]);
    } 
    
    //Funktion zur Auswertung des Arrays
    void auswertung (int ergebnis[10])
    {
      int g;             //Laufvariable für das Arry ergebnis[]
      int strikes=0;     //Variable für die Anzahl der Strikes
      int fehlwuerfe=0;  //Variable für die Anzahl der Fehlwürfe
      int gesamt=0;      //Variable für die gesamt erzielte Punktzahl
    
      printf("\nAuswertung Ihrer W\x081rfe: \n\n");
      printf("Sie haben, in aufsteigender Reiehnfolge, folgende Ergebnisse geworfen:\n\n");
      printf("\t");
    
      //For-Schleife zur Ermittlung der Anzahl der Strikes und der Fehlwürfe sowie zur Ausgabe des sortierten Ergebnisses.
      for (g=0;g<10;g++)                                       
        {                                                               
          //Ermittlung der Anzahl der Strikes
          if (ergebnis[g]==10)                                     
            {
              strikes +=1;                     
            }
    
          //Ermittlung der Anzahl der Fehlwürfe
          if (ergebnis[g]==0)                                      
            {
              fehlwuerfe +=1;                      
            }
    
          //Berechnung des Gesamtergebnises
          gesamt +=ergebnis[g];                                    
          //Ausgabe der sortierten Einzelergebnisse
          printf("%i | ", ergebnis[g]);                                       
        }                
    
          printf("\tGesamtpunktzahl: %i", gesamt);
          printf("\n\n\tAnzahl der Strikes: %i \n", strikes);
          printf("\tAnzahl der Fehlw\x081rfe: %i \n\n\n", fehlwuerfe);
    }
    

    Vielen Dank schon einmal für eure Hilfe und Mühe

    MfG Philip



  • d=strlen(*eingabe);
    

    ist falsch, *eingabe ist vom Typ char, strlen erwartet aber (const) char *.
    gets benutzt man auch nicht.



  • OK. Danke für den Hinweis.
    Ich hatte auch schon die Vermutung, dass ich strlen() nicht richtig benutze, deswegen habe ich versucht, die String-Länge einfach durch eine Schleife auszulesen.

    int d=0;
    int i=0;
    
    do
      {
        d +=1;                 
        i++;            
      }
      while (eingabe[i]!='\0');
    

    Das funktioniert nun.

    Auch das gets() habe ich nun durch ein scanf() ersetzt und sieht jetzt wie folgt aus:

    char eingabe[5];
    ...
    scanf("%s", eingabe);
    ...
    

    Und jetzt funktioniert das Programm einwandfrei 😃

    Vielen Dank für die Hilfe 👍

    Es sieht nun insgesamt so aus:

    #include <stdio.h>
    #include <stdlib.h>
    
    int integer (char eingabe[10]);
    int sortierung (int ergebnis[10]);
    void auswertung (int ergebnis[10]);
    
    int main(int argc, char *argv[])
    {
      int wurf;           //Zählvariable für die Nummer des Wurfes
      char eingabe[5];    //String variabler Länge zur Speicherung der Tastatureingabe
      int a=0;            //Variable für Integer-Wert des Strings "eingabe"
      int ergebnis[10];   //Array zum Speichern der Wurfergebnisse
      int b=0;            //Variable zur Speicherung des Ergebnisses von integer()
    
      printf("Ergebnisse der W\x081rfe eingeben.\n Fehlwurf mit 0.\n\n");
    
      for (wurf=0;wurf<10;wurf++)
        {
          do
            {
              printf("Geben Sie das Ergebnis des %i. Wurfs ein: ", wurf+1);
              scanf("%s", eingabe);
    
              if (integer(eingabe)==1)
                {
                  a=atoi(eingabe);   
                  if ((a<0)||(a>10))
                    {
                       printf("Dieses Ergebnis kann mit einem Wurf beim Bowling nicht erreicht werden.\nBitte geben Sie eine ganze Zahl von 0 bis 10 ein.\n\n");                 
                    }
                  else
                    {
                      ergebnis[wurf]=a;
                    }                   
                }
              else
                {
                  printf("Diese Eingabe ist nicht korrekt.\nBitte geben Sie eine ganze Zahl von 0 bis 10 ein.\n\n");    
                }             
            }
            while((integer(eingabe)==0)||(a<0)||(a>10));
        }
    
      sortierung(ergebnis);
    
      auswertung(ergebnis);
    
      system("PAUSE");	
      return 0;
    }
    
    //Funktion zur Überprüfung des Datentyps vom String "eingabe"
    int integer (char eingabe[10])
    {
      int b=0;                   //Rückgabevariable
      int c;                     //Laufvariable
      int anz_zahl=0;            //Variable für die Anzahl der Zahlen im String "eingabe"
      int d=0;                   //Variable zur Ermittlung der Stringlänge
      int i=0;                   //Zählvariable
    
      do
        {
          d +=1;                 
          i++;            
        }
        while (eingabe[i]!='\0');
    
      for (c=0;c<10;c++)  
        {
          if((eingabe[c]>='0')&&(eingabe[c]<='9'))  
            {
              anz_zahl +=1;                                        
            }                
        }
    
      if (anz_zahl==d)
        {
          b=1;              
        }   
      return b;
    }
    
    //Funktion zur Sortierung des Arrays ergebnis[]
    int sortierung (int ergebnis[10])
    {
      int e;            //Laufvariable für die einzelnen Indizes des Arrays ergebnis[]
      int f;            //zweite Laufvariable für die Indizes des Arrays ergbnis[]
      int temp=0;       //Variable zum Zwischenspeichern einzelner Werte aus dem Array
    
      for (e=0;e<9;e++)                                           
        {
          for (f=e+1;f<10;f++)
            {
              if (ergebnis[e]>ergebnis[f])
                {
                  temp=ergebnis[f];
                  ergebnis[f]=ergebnis[e];
                  ergebnis[e]=temp;                                      
                }                                   
            }
        }
      return (ergebnis[10]);
    } 
    
    //Funktion zur Auswertung des Arrays
    void auswertung (int ergebnis[10])
    {
      int g;             //Laufvariable für das Arry ergebnis[]
      int strikes=0;     //Variable für die Anzahl der Strikes
      int fehlwuerfe=0;  //Variable für die Anzahl der Fehlwürfe
      int gesamt=0;      //Variable für die gesamt erzielte Punktzahl
    
      printf("\nAuswertung Ihrer W\x081rfe: \n\n");
      printf("Sie haben, in aufsteigender Reiehnfolge, folgende Ergebnisse geworfen:\n\n");
      printf("\t");
    
      //For-Schleife zur Ermittlung der Anzahl der Strikes und der Fehlwürfe sowie zur Ausgabe des sortierten Ergebnisses.
      for (g=0;g<10;g++)                                       
        {                                                               
          //Ermittlung der Anzahl der Strikes
          if (ergebnis[g]==10)                                     
            {
              strikes +=1;                     
            }
    
          //Ermittlung der Anzahl der Fehlwürfe
          if (ergebnis[g]==0)                                      
            {
              fehlwuerfe +=1;                      
            }
    
          //Berechnung des Gesamtergebnises
          gesamt +=ergebnis[g];                                    
          //Ausgabe der sortierten Einzelergebnisse
          printf("%i | ", ergebnis[g]);                                       
        }                
    
          printf("\tGesamtpunktzahl: %i", gesamt);
          printf("\n\n\tAnzahl der Strikes: %i \n", strikes);
          printf("\tAnzahl der Fehlw\x081rfe: %i \n\n\n", fehlwuerfe);
    }
    


  • plumbum87 schrieb:

    Auch das gets() habe ich nun durch ein scanf() ersetzt und sieht jetzt wie folgt aus:

    char eingabe[5];
    ...
    scanf("%s", eingabe);
    ...
    

    Das ist genauso unsicher wie das gets.

    Midestens ein:

    scanf("%4s", eingabe);
    

    Was soll eigentlich die Funktion integer machen?
    Gib mal eine drei- oder vierstellige Zahl ein und danach einstellige.

    Schau dir mal die Funktion strtol an. Besonders den Parameter endptr
    Der sollte auf eine '\0' zeigen, wenn nur ein Integer übergeben wurde.


  • Mod

    Warum nicht gleich Zahl lesen, wenn man Zahl haben möchte? scanf ist schließlich genau dafür gemacht. Muss sich laut Standard sogar intern so verhalten wie das genannte strtol.

    Ebenso die Zählschleife: Wenn man weiß, dass man strlen nicht richtig benutzt, wie wäre es dann damit, zu gucken, wie man es richtig benutzt, anstatt es selber nachzuprogrammieren?

    Ebenso die Sortierung: Bubblesort? Handgemacht? Wirklich?

    Das ganze Programm könnte man durch Nutzung der Standardbibliothek auf ein viertel der Zeilen kürzen und es wäre dadurch zudem noch wesentlich besser (von den Algorithmen her) und weniger fehleranfällig.



  • Danke für den Tipp für die Eingabe des Stgrings.
    Das werde ich noch einbauen.

    Und Funktion "integer" soll prüfen, ob alle Stellen des Strings mit Zahlen besetzt sind und der String dann mittels atoi() in integer umgewandelt werden kann (ich weiß, dass die Funktion Schwachstellen hat, wenn man z.B. 10,0 eingibt (was ja eine ganze Zahl wäre), aber für diesen Zweck sollte es reichen).
    Beim testen hat sie auch gut funktioniert, auch wenn ich erst eine drei- oder vierstellige Zahl und anschließend eine einstellige eingegeben habe.

    Das reinlesen in strtol() werde ich wohl nicht mehr schaffen (morgen ist Abgabe), aber ich werde es mir dann nochmal ansehen.

    Vielen Dank für Eure Hilfe

    MfG Philip



  • @seppj

    Damit hast du sicherlich recht.
    Aber im Unterricht haben wir wirklich nur die einfachsten Standard-Sachen gemacht und uns eine bereits vordefinierte Funktion auch nicht näher angesehen.
    Unser Prof möchte aber sehen, dass wir das anwenden, was er uns in diesem Grundkurs gezeigt hat.

    Und wenn ich fitter in C wäre, könnte ich sicherlich auch bessere Programme schreiben.



  • plumbum87 schrieb:

    int d=0;
    int i=0;
    
    do
      {
        d +=1;          // Wozu das d? Das hat am Ende den selben Wert wie i ! 
        i++;            // Schon im ersten Durchlauf erhöhst du, ...
      }
      while (eingabe[i]!='\0'); // ... und dann ist der erste Test bei eingabe[1]. Was ist mit eingabe[0]
    

    Das funktioniert nun.

    Tut es nicht, siehe Kommentare

    plumbum87 schrieb:

    int integer (char eingabe[10])  // Von main kommt abe rein Array mit 5 Elementen
    {
      int b=0;                   
      int c;                    
      int anz_zahl=0;            
      int d=0;                   
      int i=0;                   
      
      do
        {
          d +=1;                 
          i++;            
        }
        while (eingabe[i]!='\0');  // siehe oben
    
      for (c=0;c<10;c++)  // Wenn du nur eine Ziffer eingegeben hast, warum überprüfst du zehn Stellen?
    // von main kommt ein Array mit nur fünf Elementen. Du greifst auf undefinierte Bereiche zu.
        {
          if((eingabe[c]>='0')&&(eingabe[c]<='9'))  
            {
              anz_zahl +=1;                                        
            }                
        }
      
      if (anz_zahl==d)
        {
          b=1;              
        }   
      return b;
    }
    

    Damit du C besser verstehst, die komplette Funktion.

    int integer (char eingabe[10]) 
    { int c;
      for (c=0;(eingabe[c]>='0')&&(eingabe[c]<='9');c++) 
        ;  // Leerschleife
    // c steht jetzt an der Stelle, die keine Ziffer mehr enthält
    
    /*
      if (eingabe[c] == '\0') return 1;  // String zuende
      else                    return 0;  // noch andere Zeichen vorhanden
    */
    
    // oder kurz:
      return !(eingabe[c]);  
    }
    

    (Das ist die lesbare Version, allerdings ungetestet)

    Mit Zeiger:

    #include <ctype>  // für isdigit
    ...
    int integer (char *eingabe) 
    { while (isdigit(*eingabe))
         eingabe++;
      return !(*eingabe);  
    }
    

    (Für Anfänger weniger gut lesbar.



  • Stimmt. d und i haben am Ende den gleichen Wert. Da stand ich wohl auf dem Schlauch, als ich das gemacht habe.

    Und die Stellenanzahl, die mit c überprüft wird, habe ich dem Array schon angepasst (das ist mir aufgefallen, das mit d komischerweise nicht).

    Und vielen dank für die ausführliche Schreibweise.
    Die kompakte habe ich jetzt auf den ersten Blick nicht verstanden.



  • plumbum87 schrieb:

    Die kompakte habe ich jetzt auf den ersten Blick nicht verstanden.

    Die Sache mit dem Zeiger oder das return?



  • Um ehrlich zu sein: beides.

    isdigit überprüft doch, ob die eingabe eine Zahl ist (wobei da auch float-zahlen mit gemeint sind) oder irre ich mich da? (bei mir hat isdigit übrigens auch ohne die Einbindung von <ctype> funktioniert 😕 ).
    Ich habe es auch mal mit isdigit probiert, es aber dann wieder verworfen (eben weil es bei mir auch Komma-Zahlen durchgelassen hat, was ich hier nicht gebrauchen konnte).


  • Mod

    digit = Ziffer

    Ziffern und Zahlen sind ganz was unterschiedliches, auch wenn es auf den ersten Blick nicht so aussehen mag.



  • digit = Ziffer

    Ziffern und Zahlen sind ganz was unterschiedliches, auch wenn es auf den ersten Blick nicht so aussehen mag.

    Und wieder etwas gelernt.
    Aber der Unterschied ist bekannt 😉



  • isdigt überprüft, ob das übergebene (einzelne) Zeichen eine Ziffer darstellt. Das was du mit deinem ... >='0')&&( ... machst.

    Das mit den Zeigern kommt noch.

    Bei dem return habe ich ausgenutzt, das in C die Null (0) als "unwahr" bzw. "falsch" betrachtet wird. Alle anderen Werte werden als "wahr" oder "richtig" betrachtet.
    Du kannst einen logischen Wert mit dem Nicht-Operator ! umdrehen. Aus 0 wird 1 und aus allem anderen wird 0.

    Das sich ein C-Programm nach dem Compilieren starten lässt, heißt noch lange nicht das es richtig ist, auch wenn es erstmal funktionieren mag.

    Beachte auch unbedingt die Compilerwarnungen. Behandele sie wie Fehler und beseitige deren Ursache.


  • Mod

    Wenn ich noch einen fiesen Einwurf machen darf: Folgendes sind auch übliche Zahlen: "-123", "-0". Aber nicht "1-2" oder "-". Mit etwas mehr Fantasie auch "012" (10, nicht 12!), "0xAB", aber nicht "08" oder "12x". Es hat schon einen Grund, wieso man das Zahlenparsen normalerweise nicht selber macht 😉 .



  • @DirkB

    Danke für die Erklärung.
    Ich werde es mal ausprobieren (Das Programm ist zwar schon abgegeben, aber es ist gerade so produktiv hier).

    Mein Compiler hat allerdings keine Warnungen ausgegeben, deswegen habe ich es auch so stehen lassen.

    Aber mein Compiler hat auch nichts gesagt, wenn das Programm hinterher nicht funktionierte (z.B. bei strl(*eingabe), was ja definitiv falsch war).

    Vielleicht sollte ich mich doch nach etwas anderem umsehen.



  • @SeppJ

    Wie wahr 😃

    Aber mir war es für dieses Programm zu aufwändig, noch nach den korrekten Befehlen zu suchen (von den zusätzlichen #include ... Befehlen ganz zu schweigen).
    Ich bin z.B. auf isint() gestoßen, was sehr vielversprechend klang, allerdings ist diese Funktion weder bei stdio.h noch bei stdlib.h enthalten. Ich konnte aber keine Info finden, was ich hätte laden müssen (hat da jemand einen Tipp für mich, wo man solche Infos finden kann? Vor ein paar Einträgen wurde ich zu cplusplus.com verwiesen)

    Wenn es später z.B. bei der Arbeit, mal nötig sein sollte, ein richtiges Programm zu schreiben um (was weiß ich...) Maschinenparameter auszulesen oder zu übergeben, werde ich mich da auf jeden Fall noch weiter einarbeiten.



  • Einmal kann man so etwas selber probieren. 😃

    Auch strlen ist nicht verkehrt, da es immer mal notwendig ist, selber durch einen String zu gehen.

    Mann kann den Warnungen ein-/ausschalten, bzw. den WArnlevel ändern.
    Wo und wie hängt aber vom Compiler/IDE ab.


Anmelden zum Antworten