Blutiger Neuprogrammierer braucht dringendst Hilfe (String to Integer)



  • Schönen guten Tag zusammen,
    ich bin neu hier im Forum und brauche dringend Hilfe.

    Vor einem Monat hab ich ein Informatik Studium begonnen in dem wir C lernen und alle vierzehn Tage ein Praktikum bestehen müssen um zur Prüfung zugelassen zu werden. Ich habe vorher noch nie programmiert und im letzten Monat meine ersten Gehversuche gemacht. Das erste Praktikum (Hello World) ging sehr leicht von der Hand aber das zweite pustete mir alle Vögel raus. Morgen habe ich die letzte Gelegenheit dieses Praktikum zu bestehen. Im ersten Teil müssen wir zwei Funktionen schreiben und in main einbinden. Die erste soll einen char in einen Integer umwandeln und die zweite soll das ganze mit einem String machen.

    Im zweiten Teil sollen diese Int werte auch noch als binär, octa und hexa ausgegeben werden, aber so weit bin ich noch garnicht.

    Als Anfänger fehlt mir irgendwo die Übersicht um das das Problem zu finden.
    Hier mein Code für den ersten Teil:

    *link entfernt, siehe unten*
    Es war nicht genug Platz in der Breite da um den Code hierhin zu kopieren, ich hoffe so ist das auch okay.

    Vielen Dank schonmal,
    ManTis



  • int ctoi ( char c)
    {
        int i;                                           /*eine weitere Variable*/
    
        i = c - '0';                                     /*i is jetzt das Ergebnis vom ASCII Wert von c minus ASCII Wert von 0*/
    /****************************/
        if (c=='-')                                      /*Für die Sring to Integer Funktion: falls dort das erste Array ein */                           
        {                                                /* - ist, wird das Endergebnis mal -1 genommen damit es negativ ist */
            i= -1;
        }
    /****************************/
        if ( i<-1 || i>9)                                /* Nur Zahlen zwischen Null und 9 sind korrekte Eingaben */
        {                                                /* ansonsten wird i mit -2 ausgegeben und int der String to Integer*/
            i = -2;                                      /* Funktion somit eine Fehlermeldung ausgegeben */
        }
        return i;
    }
    /************************************************************************/
    
    /*************************************/              /*Sring to Integer */
    
    int stoi(char str[])
    {
        int wert =0, ergebnis =0, stelle =0, negation =0;
        for (stelle=0; stelle > 16; stelle= stelle +1)    /* Solange der String weniger als 16 Felder hat, wird jedes  Feld   */
                                                          /* bearbeitet */
            ctoi(stelle);                                
    
        if (str[stelle] == -1)                            /* Falls ctoi ein -1 zurück gibt, wird die Variable "negation" auf */
        {                                                 /* -1 gesetzt um später das Ergebnis negativ zu machen */
            negation =-1;
        }
        if (str[stelle]== -2)                             /* Falls ctoi ein -2 zurück gibt, wird eine Fehlermeldung ausgegeben */
        {
            printf("Sie haben einen falschen Wert eingegeben");
        }
        else negation= 1;                                  /* Gibt ctoi einen normalen Wert zurück, wird die Variable "negation*/
                                                           /* auf 1 gesetzt, um das Ergebnis später positiv zu lassen */
    
        wert = ctoi(stelle);                              
        ergebnis = (wert + ergebnis)*10;                   /* Die einzelnen Stellen Werden zusammengerechnet,   */
                                                           /* das Ergebnis hat eine Null zuviel */
    
        ergebnis= ergebnis*negation;                       /* Das auszugebende Ergebnis wird negativ oder bleibt positiv */
    
        return ergebnis;                                   /* Das Ergebnis wird ausgegeben */
    }
    
    int main(void)
    {
    
    stoi(4559);
    
        printf("%i",stoi(4559)/10);                         /* Das Ergebis wird auf der Konsole ausgegeben, die Null zuviel  */
    }                                                       /* mit geteilt durch 10 wieder korrigiert */
    

    - for-Schleife Z. 25 läuft nie
    - Zeile 27 bewirkt nichts (da der Rückgabewert nicht ausgewertet wird, was soll das überhaupt bewirken?)
    - gutes Design, da eine Funktion in einer anderen wiederverwendet wird
    - Zeile 12 sollte c auswerten und nicht i also

    if ( i<'0' || c>'9' )
    

    - ...
    Ich nehme mal an, dass du keine Standardbibliothekfunktionen benutzen darfst (damit ginge es natürlich schneller, ist aber verbreitete Unsitte und Faulheit der Profs, sich hier nicht vernünftige Aufgabenstellungen auszudenken)



  • Z.27 ctoi(stelle) ich denke, dass du einen char übergeben willst
    du übergibst lediglich die int stelle und nicht den char den du in eine
    Zahl umwandeln willst

    da müsste noch eine Schleife hin, da du ja jeden Buchstaben
    überprüfen/umwandeln willst

    Z.53/55 (4559) das ist kein Array/String



  • Hey vielen Dank euch!

    Z.25 Der for Schleife fehlten die geschweiften Klammern.

    Z.12 habe ich geändert.

    Es stimmt dass wir nicht die entsprechende Standardbibliotheksfunktion benutzen dürfen (atoi?).Das "Design" war auch Teil der Aufgabenstellung. Sehr nett von dir zu Helfen, noch läuft der Code trotzdem nicht richtig.

    Zeile 27: Ich glaube da muss ctoi(str[stelle] stehen.

    Habe den Code in der Dropbox geändert.



  • - Z. 27 -> richtig
    - du musst str rückwärts durchlaufen und am letzten Zeichen starten und am ersten aufhören, d.h. du musst die for-Schleife korrigieren



  • die for-schleife ist falsch

    for(..;x>16;..)

    das heißt, dass wenn x größer als 16 ist wird die Schleife ausgeführt
    in dem Fall wird sie nie ausgeführt



  • So sieht der aktuelle code aus:

    #include <stdio.h>
    
    /*************************************/              /* Char to Integer */
    int ctoi ( char c)
    {
        int i;                                           /*eine weitere Variable*/
    
        i = c - '0';                                     /*i is jetzt das Ergebnis vom ASCII Wert von c minus ASCII Wert von 0*/
    /****************************/
        if (c=='-')                                      /*Für die Sring to Integer Funktion: falls dort das erste Array ein */                            
        {                                                /* - ist, wird das Endergebnis mal -1 genommen damit es negativ ist */
            i= -1;
        }
    /****************************/
        if ( c<-1 || c>9)                                /* Nur Zahlen zwischen Null und 9 sind korrekte Eingaben */
        {                                                /* ansonsten wird i mit -2 ausgegeben und int der String to Integer*/
            i = -2;                                      /* Funktion somit eine Fehlermeldung ausgegeben */
        }
        return i;
    }
    /************************************************************************/
    
    /*************************************/              /*Sring to Integer */
    
    int stoi(char str[])
    {
        int wert =0, ergebnis =0, stelle =0, negation =0;
    
        for(stelle=0; stelle < 16; stelle= stelle +1)    /* Solange der String weniger als 16 Felder hat, wird jedes Feld   */
        {                                                  /* von Feld 16 beginnend bearbeitet */
        ctoi(str[stelle]);
    
        if (str[stelle] == -1)                            /* Falls ctoi ein -1 zurück gibt, wird die Variable "negation" auf */
        {                                                 /* -1 gesetzt um später das Ergebnis negativ zu machen */
            negation =-1;
        }
        if (str[stelle]== -2)                             /* Falls ctoi ein -2 zurück gibt, wird eine Fehlermeldung ausgegeben */
        {
            printf("Sie haben einen falschen Wert eingegeben");
        }
        else negation= 1;                                  /* Gibt ctoi einen normalen Wert zurück, wird die Variable "negation*/
                                                           /* auf 1 gesetzt, um das Ergebnis später positiv zu lassen */
    
        wert = ctoi(str[stelle]);
        ergebnis = (wert + ergebnis)*10;                   /* Die einzelnen Stellen Werden zusammengerechnet,   */
                                                           /* das Ergebnis hat eine Null zuviel */
    
        ergebnis= ergebnis*negation;                       /* Das auszugebende Ergebnis wird negativ oder bleibt positiv */
        }
        return ergebnis;                                   /* Das Ergebnis wird ausgegeben */
    }
    
    int main(void)
    {
    
    int stoi(char str[]);
    
        printf("%i",stoi(4559)/10);
    
                                                            /* Das Ergebis wird auf der Konsole ausgegeben, die Null zuviel  */
    }                                                       /* mit geteilt durch 10 wieder korrigiert */
    

    Wenn ich die for Schleife rückwärts durchlaufen lasse, müsste ich ja bei Feld 16. aber dann funktioniert die Anweisung zum aufaddieren nicht mehr. Der char string soll max 16 Felder lang sein, wenn jetzt eine 4 stellige zahl als 4 chars eingefügt wird, wie wird dann belegt?
    _ _ _ _ _ _ _ _ _ _ _ _ 1 2 3 4 ? oder andersrum
    1 2 3 4 _ _ _ _ _ _ _ _ _ _ _ _
    Puh ich hab langsam echt Konzentrationsschwierigkeiten....glaub ich werfe zuviel durcheinander



  • wenn du rückwärts gehen willst
    stelle= stelle -1

    string[6]="hallo"
    -> 0 1 2 3 4 5 6
    ->[h][a][l][l][o][\0][ ]



  • Ich habe mittlerweile diesen code:

    /*************************************/              /* Char to Integer */
    int ctoi ( char c )
    {
        int i;                                           /*eine weitere Variable*/
    
        if (c=='-')                                      /*Für die Sring to Integer Funktion: falls dort das erste Array ein */
        {                                                /* - ist, wird das Endergebnis mal -1 genommen damit es negativ ist */
            i= -1;
            return i;
        }
        else if ( c<-1 || c>9)                                /* Nur Zahlen zwischen Null und 9 sind korrekte Eingaben */
        {                                                /* ansonsten wird i mit -2 ausgegeben und int der String to Integer*/
            i = -2;                                      /* Funktion somit eine Fehlermeldung ausgegeben */
            return i;
        }
    
        else
        {
        i = c - '0';                                     /*i is jetzt das Ergebnis vom ASCII Wert von c minus ASCII Wert von 0*/
        return i;
        }
    }
    /************************************************************************/
    
    /*************************************/              /*Sring to Integer */
    
    int stoi(char str[])
    
    {
        int  ergebnis =0, stelle =0, negation =0;
    
        while (str[stelle] != '\0')
        {                                               /* Solange das Feld nicht die terminierdene Null ist  */
    
            ctoi(str[stelle]);
    
            if (ctoi(str[stelle]) == -1)                            /* Falls ctoi ein -1 zurück gibt, wird die Variable "negation" auf */
            {                                                 /* -1 gesetzt um später das Ergebnis negativ zu machen */
                negation =-1;
            }
            if (ctoi(str[stelle])== -2)                             /* Falls ctoi ein -2 zurück gibt, wird eine Fehlermeldung ausgegeben */
            {
                printf("Sie haben einen falschen Wert eingegeben");
                return 0;
            }
            else
            {
    
                negation= 1;                                  /* Gibt ctoi einen normalen Wert zurück, wird die Variable "negation*/
            }                                                   /* auf 1 gesetzt, um das Ergebnis später positiv zu lassen */
    
            ergebnis = ergebnis*10 + ctoi(str[stelle]);        /* Die einzelnen Stellen Werden zusammengerechnet,   */
    
            stelle++;
    
            ergebnis= ergebnis*negation;                       /* Das auszugebende Ergebnis wird negativ oder bleibt positiv */
    
        }
        return ergebnis;                                   /* Das Ergebnis wird ausgegeben */
    
    }
    

    Habe also die for durch eine while schleife ersetzt, damit komme ich besser zurecht. Er gibt aber immernoch Fehlermeldungen aus.
    Auch in der main.c :

    int main()
    {
        int stoi(char str[]);
    
        printf("%i",stoi(2344));
    
        return EXIT_SUCCESS;
    }
    

    Meldung: Incompatible Integer to pointer conversion passing 'int' to parameter of type 'char*'

    Wäre sehr nett wenn ihr mir nochmal helfen würdet.



  • Man_Tis schrieb:

    Wäre sehr nett wenn ihr mir nochmal helfen würdet.

    Der größte Fehler ist, dass Du alles Mögliche in einem Rutsch erledigen willst. Hier habe ich Dir ein Beispiel, wo ich jeden Schritt möglichst einzeln vollziehen lasse. Vielleicht wird Dir dann alles ein bisschen klarer:

    #include <stdio.h>
    
    int ctoi (char c)
    {
        int result;
        if (c >= '0' && c <= '9')
        {
            result = c - '0';
        }
        else
        {
            result = -1;
        }
        return result;
    }
    
    int stoi (char* s)
    {
        int result;
        int sign;
        int i;
        char c;
    
        if (*s == '-')
        {
            sign = -1;
            ++s;
        }
        else
        {
            sign = 1;
        }
    
        result = 0;
        while (*s)
        {
            c = *s;
            i = ctoi(c);
            if (i < 0)
            {
                printf ("Sie haben einen falschen Wert eingegeben\n");
                return 0;
            }
            result *= 10;
            result += i;
            ++s;
        }
    
        return sign * result;
    }
    
    int main (void)
    {
        char s[] = "4559";
        int i;
        printf ("%s\n",s);
    
        i = stoi (s);
        printf ("%i\n",i);
    
        return 0;
    }
    

    viele grüße
    ralph



  • Vielen Dank Ralph,

    ich versuche deinen Code zu vertsehen und habe gleich bemerkt dass er viel übersichtlicher ist.

    Du benutzt auch pointer, im umgang damit bin ich nicht gut vertraut, wie gesagt ich fange erts an mich an c zu "gewöhnen".

    Dein code hilft mir sehr weiter.
    Danke und liebe Grüße!
    ManTis



  • Ich hätte sonst nochmal den Code ohne Pointer hier für dich

    #include <stdio.h>
    
    int ctoi ( char c )
    {
        int i;
        i = c - '0';  
        if (c=='-')
        {
            i= -1;
            return i;
        }
        else if ( i<-1 || i>9)
        {
            i = -2;
            return i;
        }
    
        else
        {
        return i;
        }
    }
    
    int stoi(char str[])
    
    {
        int  ergebnis =0, stelle =0, negation =0, summand;
    
        while (str[stelle] != '\0')
        {
            summand=ctoi(str[stelle]);
            if (ctoi(str[stelle]) == -1)
            {
                negation =-1;
    			summand=0;
            }
            else if (ctoi(str[stelle])== -2||(ctoi(str[stelle])==-1&&stelle<0))
            {
                printf("Sie haben einen falschen Wert eingegeben");
                return 0;
            }
    
            ergebnis = ergebnis*10 + summand;
            stelle++;
        }
        return (ergebnis*negation);
    }
    int main()
    {
        printf("%i",stoi("-135"));
    	system("pause");
    
        return;
    }
    


  • Man_Tis schrieb:

    Du benutzt auch pointer, im umgang damit bin ich nicht gut vertraut, wie gesagt ich fange erts an mich an c zu "gewöhnen".

    Der Pointer war die elegante Möglichkeit, mit dem Vorzeichen umzugehen (gehört das überhaupt zur Aufgabe?). So würde das mit Index aussehen:

    int stoi (char s[])
    {
        int result;
        int sign;
        int i;
        char c;
        int s_index;
    
        if (s[0] == '-')
        {
            sign = -1;
            s_index = 1;
        }
        else
        {
            sign = 1;
            s_index = 0;
        }
    
        result = 0;
        while (s[s_index])
        {
            c = s[s_index];
            i = ctoi(c);
            if (i < 0)
            {
                printf ("Sie haben einen falschen Wert eingegeben\n");
                return 0;
            }
            result *= 10;
            result += i;
            ++s_index;
        }
    
        return sign * result;
    }
    

    viele grüße
    ralph



  • WOW Danke spagetti und ralph, ihr seid super! So klappts bestimmt. Das Vorzeichen muss nur sozasagen erkannt werden um auch beim zweiten Teil der Aufgabe Hexa und Octa in negative Zahlen umzuwandeln.

    Ihr seid echt Hilfsbereit!



  • Ich bin zufällig auf diese interessanten Lösungen gekommen und frage mich:

    1. Fehlerhafte Eingabe mit mehreren Minuszeichen (oder Plus und Minus gemischt) in der Zahl.
    2. + muss eigentlich auch erlaubt sein.
    3. Wieso 16 Stellen? Wohl dem der einen 32-bit-Rechner hat, dann gehen kaum 10 Stellen, ein 64-bit-Rechner kann fast 20 Ziffern in int unterbringen. Eigentlich sollte das Programm doch den Überlauf selbst erkennten

    Da es mein erster Beitrag in diesem Forum ist, bitte ich um Nachsicht, wenn ich die Gebrauchsanweisung noch nicht gelesen habe. Hier eine reine C-Lösung aus dem Visual Studio:

    - reine Pointer-Lösung
    - ctoi ist eigentlich überflüssig und testet unnötigerweise das Vorzeichen jedes Mal
    - stattdessen einfach das vorder Nippel (Halbbyte) ausblenden, so ergibt sich der numerische Wert direkt ohne Subtraktion (ist auch viel schneller)

    [code="c"]
    /*A031S_ZeichenInZahl_Minus.c : Einstiegspunkt der Konsolenanwendung*/
    /*Parser: Liest Zeichenkette mit Ziffern ein und erzeugt eine Ganzzahl mit Vorzeichen und Pruefung*/

    #include <stdio.h>
    #include <stdlib.h> /*fuer system*/

    #ifdef __cplusplus
    #define KOMPILIERMODUS "mit C++"
    #else
    #define KOMPILIERMODUS "mit C"
    #endif
    #pragma message(KOMPILIERMODUS)

    int main(void) {
    unsigned char cZahl[80+1]; /*Zeichenkette fester Laenge*/
    unsigned char *cZeiger; /*Zeiger auf die Zeichenkette*/
    long nErgebnis=0; /*Ergebnis*/
    long nVorzeichen=1;
    fprintf_s(stdout,"Zahl wird als Zeichenkette eingelesen: ");
    fscanf_s(stdin,"%80s",cZahl,sizeof(cZahl)-1);
    fprintf_s(stdout,"Sie haben eingegeben: %s\n",cZahl);
    cZeiger=cZahl;
    switch (cZeiger) {
    case '-': nVorzeichen=-1; /*interessanter Fall ohne break*/
    case '+': cZeiger++;break;
    } /*switch*/
    while (*cZeiger!='\0') { /*Zeigertechnik
    /
    if (*cZeiger<'0'||*cZeiger>'9') {
    fprintf_s(stderr,"Falsche Eingabe\n");
    return -1;
    } /*if*/
    nErgebnis=nErgebnis*10+((*cZeiger)&0xF); /*Horner-Schema und numerischer Wert statt Zeichen*/
    if (nErgebnis<0) {
    fprintf_s(stderr,"Zahlenueberlauf\n");
    return -2;
    } /*if*/
    cZeiger++;
    } /*while*/
    nErgebnis*=nVorzeichen;
    fprintf_s(stdout,"Der numerische Wert ist %d\n",nErgebnis);
    system("Pause");
    return 0;
    } /*main*/



  • Gut, ich lerne dazu, hier also der Quelltext noch einmal. Das Herzstück ist die Zeile 32.

    /*A031S_ZeichenInZahl_Minus.c : Einstiegspunkt der Konsolenanwendung*/
    /*Parser: Liest Zeichenkette mit Ziffern ein und erzeugt eine Ganzzahl mit Vorzeichen und Pruefung*/
    
    #include <stdio.h>
    #include <stdlib.h> /*fuer system*/
    
    #ifdef __cplusplus
      #define KOMPILIERMODUS "mit C++"
    #else
      #define KOMPILIERMODUS "mit C"
    #endif
    #pragma message(KOMPILIERMODUS)
    
    int main(void) {
      unsigned char cZahl[80+1]; /*Zeichenkette fester Laenge*/
      unsigned char *cZeiger;    /*Zeiger auf die Zeichenkette*/
      long nErgebnis=0;          /*Ergebnis*/
      long nVorzeichen=1;
      fprintf_s(stdout,"Zahl wird als Zeichenkette eingelesen: ");
      fscanf_s(stdin,"%80s",cZahl,sizeof(cZahl)-1);
      fprintf_s(stdout,"Sie haben eingegeben: %s\n",cZahl);
      cZeiger=cZahl;
      switch (*cZeiger) {
        case '-': nVorzeichen=-1; /*interessanter Fall ohne break*/
        case '+': cZeiger++;break;
      } /*switch*/
      while (*cZeiger!='\0') { /*Zeigertechnik*/
        if (*cZeiger<'0'||*cZeiger>'9') {
          fprintf_s(stderr,"Falsche Eingabe\n");
          return -1;
        } /*if*/
        nErgebnis=nErgebnis*10+((*cZeiger)&0xF); /*Horner-Schema und numerischer Wert statt Zeichen*/
        if (nErgebnis<0) {
          fprintf_s(stderr,"Zahlenueberlauf\n");
          return -2;
        } /*if*/
        cZeiger++;
      } /*while*/
      nErgebnis*=nVorzeichen;
      fprintf_s(stdout,"Der numerische Wert ist %d\n",nErgebnis);
      system("Pause");
      return 0;
    } /*main*/
    


  • Ich kann deine Lösung zwar nicht beurteilen Waldschrat aber sie ist sicherlich sehr gut. Auch dir danke.
    Ausser stdio dürfen wir nur selbstgeschriebene Funktionen benutzten denke ich.
    👍



  • Durchgeknallte C-Programmierer multiplizieren natürlich nicht mit +1 oder -1, sondern bilden das Zweierkomplement persönlich

    /*nErgebnis*=nVorzeichen;*/
      if (nVorzeichen<0) {
        nErgebnis=~nErgebnis+1;
      } /*if*/
    

    stdlib.h ist nur für die Pause im Debug-Modus, sonst hält die Konsole nicht an.

    Einfach weglassen und die vorletzte Zeile löschen.

    Die Präprozessor-Anweisungen am Anfang dienen auch nur dazu, Dir zu zeigen, ob Du mit C oder C++ übersetzt. Können also auch entfallen.



  • Man_Tis schrieb:

    Ich kann deine Lösung zwar nicht beurteilen Waldschrat aber sie ist sicherlich sehr gut.

    Was denn nun? Du kannst sie nicht beurteilen und beurteilst sie dann doch?
    Die Waldschrat"lösungen" sind Schrott und fehlerhaft und für einen Anfänger schädlich weil irreführend.



  • Dann korrigiere ich mich:
    Herr Waldschrat ich habe keine Ahnung ob die Lösung das Problem überhaupt löst.

    Ich bin aufgrund der für einen Anfänger gefühlt hohen komplexität davon ausgegangen dass es "sicherlich" eine sehr gute Lösung ist.


Anmelden zum Antworten