Mein erstes Programm



  • - srand(time(0)) nur 1x im Prozess aufrufen, z.B. am Beginn von main()
    - getrandom entschlacken wie beschrieben
    - da es immer wieder vorkommt, einen simplen int inklusive Fehlerbehandlung einzulesen und sich die Leute - wie du - immer wieder wundern, warum scanf das nicht alles inkl. stdin-Leerung auch bei fehlerhaften Eingabe macht, hier mal eine Variante, wie sowas aussehen kann, womit du deine scanf-Aufrufe ersetzen kannst:

    /* liest solange von stdin, bis gültiges int eingegeben wurde;
    ENTER (\n) dient als Eingabeende */
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <limits.h>
    
    int checkInt(long *l, const char *s)
    {
    	char *e;
    	if (*s == '\n') return 0;
    	errno = 0;
    	*l = strtol(s, &e, 10);
    	return (!*e || *e == '\n') && errno != ERANGE && *l >=INT_MIN && *l <= INT_MAX;
    }
    
    int getInt()
    {
    	char str[1000];
    	long longvar;
    	while (fgets(str, 1000, stdin), !checkInt(&longvar, str));
    	return (int)longvar;
    }
    


  • Ich möchte mich bei allen bedanken, jeder Beitrag habe ich zu Herzen genommen und bin eure Ratschläge nachgegangen.

    1. @SeppJ, du hast natürlich recht, das mischen von deutsch und englisch ist keine gute Idee und ich habe jetzt jede Funktion einen passenden Namen gegeben.

    2. Wie @Wutz mir geraten habe ich jetzt nur noch einmal srand in mein Quellcode, es reichte in meinem Fall auch sogar time(NULL) aus. Habe die Funktion getrandom entschlankt und sogar die For-Schleife entfernt und den Fehler wo ich sonst immer hatte, habe ich jetzt nicht mehr. Mein Fehler war, das ich das Programm immer durch eine bash for-Schleife gejagt habe und somit kam immer die gleiche Zufallszahl raus. Im C Programm selbst, funktioniert die Zufallszahl wie gewünscht und ich habe es einfach Falsch Interpretiert und dachte ich habe einen Fehler.

    3. @DirkB, danke für den Link - fflush hab ich schon mal gelesen und muss dies wohl nochmal tun ... 😉

    Danke schon mal an alle bis hier her.

    EDIT:
    So wie es jetzt aussieht habe ich meine Probleme gelöst. Vielen Dank an alle.

    int getrandom(int ma) {
        int random_number;
        random_number = rand() % ma;
        return random_number;
    }
    /* getInt läuft solang bis eine Zahl eingegeben wurde */
    int getInt() {
        int user_result, check;
        while(check != 1) {
            check = scanf("%d", &user_result);
            getchar();
            if(check != 1) {
                printf("Bitte geben Sie nur Zahlen ein. Probiere es noch einmal.\n");
            }
        }
        return user_result;
    }
    

    Der Code ist mit Sicherheit nicht Perfekt, aber es läuft erst mal und ich habe einen guten ersten Einblick bekommen. Als nächstes werde ich versuchen die Ergebnisse in einer Textdatei zu speichern, als eine Art Highscore ... aber jetzt kann erst mal Neujahr kommen und danach packe ich es an.

    Danke für eure Hilfe und Tipps und wünsche alle einen guten Rutsch ....



  • knasan schrieb:

    fflush hab ich schon mal gelesen und muss dies wohl nochmal tun ... 😉

    Vergiß fflush für stdin .

    knasan schrieb:

    Der Code ist mit Sicherheit nicht Perfekt, aber es läuft erst mal

    Tut er nicht.

    Baachte die Warnungen vom Compiler!
    (Wenn du kein bekommst, erhöhe den Warn Level)

    Welchen Wert hat check in Zeile 9?

    Da die Eingabe erst mit der Entertaste übernommen wird, können durchaus mehr als ein fehlerhaftes Zeichen eingegeben worden sein.
    Da kommst du mit einem getchar nicht weit.

    Fehlertolerante Usereingaben sind eine komplexe Angelegenheit und daher für Anfänger eher ungeeignet.



  • Danke für den Hinweis. Ich gebe dir recht, diese Materie ist wirklich nicht einfach und es ist mit Sicherheit nicht falsch wenn man sich damit etwas beschäftigt.
    Mal sehen ob ich dazu Heute noch komme.

    Kann mir jemand ein Howoto nennen wo darauf näher eingeht?
    Meine Abfang Methode habe ich aus dem OpenBook http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/

    Ich werde mein Status wieder auf offen Stellen und nicht mehr so selbstsicher schnell als gelöst makieren.

    Gruß



  • Gut, dass du gleich sagst, wo du dein Unwissen her hast.

    Der Autor hat hier keinen guten Ruf, da das Buch (speziell die Online-Ausgabe) voller Fehler ist.

    Wutz hat schon eine Möglichkeit gepostet.

    Die Frage ist immer, was als gültige Eingabe erkannt werden soll.
    Ist 123xy noch gültig (bis zur 3) oder schon falsch ....



  • Hallo DirkB,

    ich wollte herausfinden ob eine gültige Zahl eingegeben worden ist. Meine jetzige Lösung hat natürlich zwei mir bekannte Probleme

    1. 2a wird noch als gültig erkannt.
    2. Gibt man zwei Zahlen an, ist meine Methode auch Fehleranfällig.

    Ich werde mir die Lösung von Wutz ansehen und melde mich dann nochmal.

    Wegen http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/ hat dieser Syntax oder logische Fehler? Kannst du mir das bitte genauer erläutern? Ich habe hier noch ein Buch von diesem Autor hier "Grundkurs C", sollte ich hiervon auch die Finger lassen oder hilft mir dieses Buch bei C weiter? Ich möchte ja nichts gleich Falsch Lernen, davon habe ich auch nichts.

    Danke


  • Mod

    knasan schrieb:

    Wegen http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/ hat dieser Syntax oder logische Fehler? Kannst du mir das bitte genauer erläutern? Ich habe hier noch ein Buch von diesem Autor hier "Grundkurs C", sollte ich hiervon auch die Finger lassen oder hilft mir dieses Buch bei C weiter? Ich möchte ja nichts gleich Falsch Lernen, davon habe ich auch nichts.

    Beides. Und noch allerlei mehr Arten von Fehlern. Der Autor hat einfach keine tiefgehende Ahnung vom Thema. Das merkt man schon an seinem Portfolio, dass er über alles mögliche Bücher geschrieben hat. Niemand kann ein solch vielseitiger Experte sein. Er ist nur auf einem Gebiet Experte, und zwar da drin, schöne Bücher zu schreiben, die sich gut verkaufen. In denen verbreitet er dann jede Menge gefährliches Halbwissen, dass er sich mal eben schnell irgendwo zusammen gesucht hat.

    Der ganze Verlag hat übrigens den Ruf, hauptsächlich Bücher dieser Art zu verlegen. Schlecht recherchiert, aber gut geschrieben, und dann erfolgreich unter Titeln verkauft, die hauptsächlich Ahnungslose ansprechen, die nicht erkennen können, ob der Inhalt stimmt oder nicht.

    Und ja: Es ist besser, nicht nach diesen Büchern zu lernen, denn du lernst viel falsches, was du hinterher nur mühsam los wirst. Oder du gibst frustriert auf, weil nichts richtig funktioniert.



  • Hi,

    ich habe den Code von Wutz eingefügt und dieser Funktioniert ohne Probleme. Leider verstehe ich den Code noch nicht zu 100%. Ich werde mal versuchen soweit den Code zu erklären so weit ich komme, damit Ihr wisst wo mein Fehler oder Unwissenheit ist. Vielen Dank für eure Mühen.

    int checkInt(long *l, const char *s) {
        char *e;
        if (*s == '\n' ) return 0;
        errno = 0;
        *l = strtol(s, &e, 10);
        return (!*e || *e == '\n') && errno != ERANGE && *l >=INT_MIN && *l <= INT_MAX;
    }
    
    int getInt() {
        char str[1000];
        long longvar;
        while (fgets(str, 1000, stdin), !checkInt(&longvar, str));
        return (int)longvar;
    

    Beides sind Funktionen, checkInt nimmt zwei Parameter an die vom Typ Pointer sind. Der Parameter s ist sogar eine Constante und kann zur Laufzeit nicht verändert werden.

    Es wird wein Pointer auf e erstellt. Ich hoffe das ich es bis hier her alles richtig verstanden habe.

    if (*s == '\n' ) return 0 wenn der Pointer ein Newline ist, dann soll der Ausdruck sofort ein true zurückliefern.

    errno = 0, ich kenne das noch nicht ist eine Variable Zuweisung die Variable wird in errno.h deklariert.

    *l = strtol(s, &e, 10); darauf kann ich mir nichts zusammenreimen und verstehe ich bisher noch nicht, da mir strtol völlig unbekannt ist.

    return (!*e || *e == '\n') && errno != ERANGE && *l >=INT_MIN && *l <= INT_MAX;

    Wenn mir jemand diesen Ausdruck erklären könnte, wäre auch super!

    bei getInt
    Wenn ich es richtig verstehe, wird ein Array erstellt das Maximal 1000 Zeichen beinhalten kann. Eine Variable longvar die als Rückgabe Zeiger von checkInt dient. Am ende wird der Zeiger als Int Rückgabe konveniert.

    PS: Sie getInt Methode habe ich soweit geändert das man zwei Zahlen und ein Zeichen übergeben kann, somit kann ich in der While Schleife immer sagen welche Aufgabe es sich gehandelt hat.
    Wegen die Bücher, ich habe etwas in Web gefunden, kann ich danach gefahrlos Lernen? https://de.wikibooks.org/wiki/C-Programmierung

    Danke für Eure Antworten und Hilfe



  • knasan schrieb:

    Beides sind Funktionen,

    Ja

    knasan schrieb:

    checkInt nimmt zwei Parameter an die vom Typ Pointer sind.

    Fast. Der Typ ist Pointer auf long bzw. Pointer auf char

    knasan schrieb:

    Der Parameter s ist sogar eine Constante und kann zur Laufzeit nicht verändert werden.

    Der Pointer kann verändert werden, aber nicht das, worauf er zeigt. (bzw wird dieses zugesichert und de Compile kann reagieren)

    knasan schrieb:

    Es wird wein Pointer auf e erstellt.

    Es wird ein Pointer auf char mit dem Namen e erstellt.

    knasan schrieb:

    Ich hoffe das ich es bis hier her alles richtig verstanden habe.

    Entscheide selber

    knasan schrieb:

    if (*s == '\n' ) return 0 wenn der Pointer ein Newline ist, dann soll der Ausdruck sofort ein true zurückliefern.

    Wenn de rPointer auf ein Newline zeigt, dann wird ein false zurück gegeben

    knasan schrieb:

    errno = 0, ich kenne das noch nicht ist eine Variable Zuweisung die Variable wird in errno.h deklariert.

    Wenn du weißt, dass sie errno.h deklariert ist, solltest du auch wissen, wozu sie da ist.

    knasan schrieb:

    *l = strtol(s, &e, 10); darauf kann ich mir nichts zusammenreimen und verstehe ich bisher noch nicht, da mir strtol völlig unbekannt ist.

    Die Standard Library von C ist so klein, dass man durchaus alle Funktionen kennen kann. Wenn nicht, hilft ein Blick in eien Referenz oder Online Hilfe.
    http://www.cplusplus.com/reference/cstdlib/strtol/?kw=strtol

    knasan schrieb:

    return (!*e || *e == '\n') && errno != ERANGE && *l >=INT_MIN && *l <= INT_MAX;

    Wenn mir jemand diesen Ausdruck erklären könnte, wäre auch super!

    Wenn du die Referenz zu strtol durchgelesen und verstanden hast, sollt dir dieser Ausdruck auch klar werden.
    Es wird geprüft ob das Zeichen nach der Zahl das Stringende oder ein Newline ist und ob kein Fehler bei der Wandlung aufgetreten ist.

    knasan schrieb:

    PS: Sie getInt Methode habe ich soweit geändert das man zwei Zahlen und ein Zeichen übergeben kann, somit kann ich in der While Schleife immer sagen welche Aufgabe es sich gehandelt hat.

    Du hättest sie auch zweimal aufrufen können.

    knasan schrieb:

    Wegen die Bücher, ich habe etwas in Web gefunden, kann ich danach gefahrlos Lernen? https://de.wikibooks.org/wiki/C-Programmierung

    Es bleibt der Versuch eines Online-Tutorials.



  • Jetzt ist mir einiges klarer.
    Ich lag leider manchmal leicht daneben ...
    Danke für den Link - diesen kannte ich noch nicht.


Anmelden zum Antworten