Fehler beim zweiten Schleifendurchlauf.



  • Beim zweiten Schleifendurchlauf hatte ich zunächst den Fehler, dass der Code nicht auf die Eingabe wartet. Jetzt bekomme ich den Fehler "Vom RangeChecks-Instrumentationscode wurde ein Arrayzugriff außerhalb des Bereichs erkannt."

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

    void clearfunction(char eingabestring[100], char ersterTeil[50], char zweiterTeil[50]) {
    memset(eingabestring, 0, sizeof(eingabestring));
    memset(ersterTeil, 0, sizeof(ersterTeil));
    memset(zweiterTeil, 0, sizeof(zweiterTeil));
    eingabestring[0] = '\0';
    ersterTeil[0] = '\0';
    zweiterTeil[0] = '\0';
    }

    int main(void){

    char eingabestring[100];
    char ersterTeil[50];
    char zweiterTeil[50];
    int operantenstelle;
    int operantenzahl;
    int erstezahl;
    int zweitezahl;
    int resultat;
    char* plus;
    char* minus;
    char* durch;
    char* mal;
    int frage;
    
    printf("-----simpler Taschenrechner-----\n");
    
    do{
        clearfunction(eingabestring, ersterTeil, zweiterTeil);
    
        printf("Gib deine Rechnung ein: ");
        
        fgets(eingabestring, 100, stdin);
    
        plus = strchr(eingabestring, '+');
        minus = strchr(eingabestring, '-');
        mal = strchr(eingabestring, '*');
        durch = strchr(eingabestring, '/');
    
        if (plus != NULL) {
            printf("Das erste Vorkommen des Zeichens '+' befindet sich an der Stelle: %ld\n", plus - eingabestring + 1);
            operantenstelle = plus - eingabestring;
            operantenzahl = 1;
        }
        if (minus != NULL) {
            printf("Das erste Vorkommen des Zeichens '-' befindet sich an der Stelle: %ld\n", minus - eingabestring + 1);
            operantenstelle = minus - eingabestring;
            operantenzahl = 2;
        }
        if (mal != NULL) {
            printf("Das erste Vorkommen des Zeichens '*' befindet sich an der Stelle: %ld\n", mal - eingabestring + 1);
            operantenstelle = mal - eingabestring;
            operantenzahl = 3;
        }
        if (durch != NULL) {
            printf("Das erste Vorkommen des Zeichens '/' befindet sich an der Stelle: %ld\n", durch - eingabestring + 1);
            operantenstelle = durch - eingabestring;
            operantenzahl = 4;
        }
    
        strncpy_s(ersterTeil, eingabestring, operantenstelle);
        ersterTeil[operantenstelle] = '\0';
        strcpy_s(zweiterTeil, eingabestring + operantenstelle + 1);
        zweiterTeil[strlen(zweiterTeil) - 1] = '\0'; // Nullterminator am Ende entfernen
    
        printf("erster Teil: %s\n", ersterTeil);
        printf("zweiter Teil: %s\n", zweiterTeil);
    
        erstezahl = atoi(ersterTeil);
        zweitezahl = atoi(zweiterTeil);
    
        printf("erste Zahl: %i\n", erstezahl);
        printf("zweite Zahl: %i\n", zweitezahl);
    
        switch (operantenzahl) {
        case 1: resultat = erstezahl + zweitezahl; break;
        case 2: resultat = erstezahl - zweitezahl; break;
        case 3: resultat = erstezahl * zweitezahl; break;
        case 4: resultat = erstezahl / zweitezahl; break;
        }
    
        printf("das resultat ist: %i\n", resultat);
        printf("Möchtest du noch einmal rechnen? 1 für JA und 2 für NEIN");
        
        scanf_s("%i", &frage);
    
    } while (frage == 1);
    
    return 0;
    

    }



  • @bajram sagte in Fehler beim zweiten Schleifendurchlauf.:

    void clearfunction(char eingabestring[100], char ersterTeil[50], char zweiterTeil[50]) {

    Achtung: Diese Deklaration ist identisch zu

    void clearfunction(char eingabestring[], char ersterTeil[], char zweiterTeil[])
    

    und auch identisch zu

    void clearfunction(char *eingabestring, char *ersterTeil, char *zweiterTeil)
    

    Das heißt, die Länge, die du da angibst, wird ignoriert. Man übergibt solchen Funktionen den Pointer und die Länge. (bei mehrdimensionalen Arrays wird nur die hinterste Länge ignoriert)

    Stelle Warnungen in deinem Compiler an! Dann sollte sowas rauskommen wie:

    test.c:4:32: warning: 'sizeof' on array function parameter 'eingabestring' will return size of 'char *' [-Wsizeof-array-argument]
        4 | memset(eingabestring, 0, sizeof(eingabestring));
          |                                ^
    

    Außerdem darfst du dem memset schon vertrauen, du musst danach nicht nochmal die einzelnen Elemente auf 0 setzen. Du brauchst aber normalerweise gar nicht den gesamten Speicherbereich zu nullen, die 0 ist der Terminator, es reicht also, wenn die 0 am Ende ist. Aber wozu musst du hier überhaupt irgendwas clearen?!

    Das ist allerdings nur der erste offensichtliche Fehler (anderen Code nicht überprüft). Insgesamt hast du VIEL ZU VIELE Variablen im Scope deines Main. Versuche dich auf die nötigen Variablen in main zu beschränken und ggf. Code in Funktionen zu verschieben, wenn du da andere Variablen brauchst.

    Der Code mit Zeichen suchen und Ausgeben der Position des Vorkommens ist sehr repetitiv (4x fast das gleiche). Wäre ein Kandidat für eine Funktion.

    Wozu hast du operantenzahl? Du könntest im switch auch gleich ein Switch auf den Operator selbst (ein char!) machen. (außerdem ist es der Operand mit d)

    Generell könntest du auch direkt nach dem Einlesen mit fgets eine Funktion aufrufen, die den Eingabestring verarbeitet, z.B. so oder so ähnlich:

    void rechne(const char *eingabestring) {
        int a, b;
        char op;
        if (3 == sscanf(eingabestring, "%d %[-+*/]%d", &a, &op, &b)) {
            printf("Die erste Zahl ist %d, der Operator ist %c und die zweite Zahl ist %d\n", a, op, b);
            // hier ein switch (op) { case '+': ... und so weiter }
        } else {
            printf("Falsche Eingabe\n");
        }
    }
    


  • @bajram
    Bitte formatiere deine Beiträge besser. So macht es einen schlampigen Eindruck und verringert die Chancen Antworten zu bekommen. (Ich z.B. sehe mir schlecht formatierte Beiträge manchmal gar nicht weiter an.)

    Informationen über die Syntax kannst du finden wenn du nach Markdown suchst (Google, ...). Ansonsten kannst du auch einfach die Buttons über dem Eingabebereich verwenden.



  • @bajram sagte in Fehler beim zweiten Schleifendurchlauf.:

    Beim zweiten Schleifendurchlauf hatte ich zunächst den Fehler, dass der Code nicht auf die Eingabe wartet.

    Den hast du doch immer noch.

    Das liegt daran, dass nach dem scanf_s("%i", &frage); das '\n' von der Entertaste in der Eingabe liegt.
    Dies wird vom fgets() gelesen und als Ende der Eingabe gewertet.

    Man könnte jetzt nach dem scanf_i() noch Zeichen lesen,
    einfacher wäre es aber auf die Frage zu verzichten, die Schleife zu verlassen wenn eingabestring zu kurz ist.
    (Dieses "Möchtest du nochmal?" nervt auf Dauer)
    ACHTUNG: fgets() legt das'\n' in dem String mit ab.


Anmelden zum Antworten