String in Integer umwandeln und ausgeben ohne Library



  • Moin moin Zusammen.

    Ich habe gerade mit C angefangen und bräuchte etwas hilfe bei einer Aufgabenstellung.

    Habe das Internet schon durchforstet und auch Lösungen gefunden, die ich einfach nicht verstehe und hoffe auf jemanden, der es mir erklären könnte bzw bei der Aufgabe helfen kann.

    Es geht explizit darum, dass ich einen String (char []) in einen Integerwert umwandeln soll.

    Klar, wäre kein Problem, wenn ich atoi benutzen könnte.

    Folgendes darf ich benutzen:

    putstring
    getstring
    copystring
    appendstring

    Die Aufgabenstellung:

    2 Positive Dezimalstellen (max. 4 Stellen) und dies erfolgt über die Funktion getstring().

    Es soll überprüft werden, ob es die ASCII Zeichen '0'-'9' enthält, wenn ja
    -> umwandeln der Werte in den entsprechenden Integer-Wert (unsigned short int).

    Die beiden Werte sollen dann in eine andere Integerzahl gespeichert werden und dann wieder per putstring() ausgegeben werden. Naja, wieder umwandeln in ASCII.

    Bis jetzt hab ich es so ausprobiert:

    int checknumbers (char* string) {
      int i;
      for (i = 0 ; string[i]!='\0';i++) {
        if (string[i] < '0' || string[i] > '9') {
          putstring("Bitte erneute eingabe der Zahl: nicht im Zahlenbereich:\n");
          return -1;
          }
        }
    
      return 1;
      }
    
    int checklength (char* string) {
      int i;
      for (i = 0;string[i]!='\0';i++){
        if (i > 3) {
        putstring("Bitte erneute eingabe der Zahl: nicht im Zahlenbereich:\n");
            return -1;
    
          }
        }
    
      return 1;
      }
    
    void emain()
    
    {
        long int zahl1;
        long int zahl2;
        long int ergebnis;
        char string_1[100];
        char string_2[100];
    
        INIT_BM_WITHOUT_REGISTER_UI;
    
        do {
    
        putstring("Bitte 1. Zahl eingeben:\n");
        getstring(string_1);
        }
        while (checknumbers(string_1)== - 1 || checklength(string_1) == -1);
            zahl1=stringtoi(string_1);
    
        do {
        putstring("Bitte 2. Zahl eingeben:\n");
        getstring(string_2);
    
        } while (checknumbers(string_2)== -1 || checklength(string_2) == -1);
    
        zahl2=stringtoi(string_2);
    
        ergebnis= zahl1 * zahl2;
    
        itostring(ergebnis, string_1);
    
        copystring("Produkt beider Zahlen ist:\n",string_2);
        appendstring(string_1, string_2);
        putstring (string_2);
    
        END;
    }
    

    Einen einzelnen Integerwert, könnte ich umwandeln.
    Einfach

    if (i>=0 && i<=9) { 
    c1 =  '0' + i;
    }
    

    Nur wie wandel ich einen String in den Integerwert und zurück?
    Könnte mir das jemanden versuchen zu erklären?

    Viele Grüße und sorry falls die Frage lächerlich ist. Aber ich habe gerade eine Blockade 👎


  • Mod

    Allgemein:
    https://de.wikipedia.org/wiki/Stellenwertsystem
    Also wie in der Grundschule: Du hast Einer, Zehner, Hunderter, Tausender, ...



  • Deine Antwort hat mir bedingt weitergeholfen.

    Musste erstmal verstehen, wie die ASCII umwandlung funktioniert.

    int umwandlung(char *string)
    {
        int ergebnis = 0; // Initialisierung des Ergebn.
        int i = 0;
    
        for (i = 0; string[i] != '\0'; ++i)
            ergebnis = ergebnis*10 + string[i] - '0';
    
        return ergebnis;
    }
    
    do {
    
        putstring("Bitte 1. Zahl eingeben:\n");
        getstring(string_1);
        }
        while (checknumbers(string_1)== - 1 || checklength(string_1) == -1);
            zahl1=umwandlung(string_1);
    
    do {
        putstring("Bitte 2. Zahl eingeben:\n");
        getstring(string_2);
    
        } while (checknumbers(string_2)== -1 || checklength(string_2) == -1);
    
        zahl2=umwandlung(string_2);
    

    Mir hat das Programm auch ganze Zeit einen Fehler rausgehauen, weil ich i in der Schleife deklariert habe...

    Jetzt noch die Umwandlung wieder von Integer in ASCII.

    Kann ich es genau so machen wie mein Beispiel im ersten Post?

    if (i>=0 && i<=9) {
    c1 =  '0' + i;
    }
    


  • Die Abbruchbedingung der Schleife in umwandlung ist ungünstig.

    Du darfst ja nur Umwandeln, wenn du auch Ziffern im String hast.

    Kennst du den Modulo-Operator % ?



  • Klar aber welchen Sinn hätte Modulo hier?

    Der Aufruf der Methode lässt ja nur Ziffern zu, durch die Do-While schleife bzw ASCII-Werte '0' - '9' bzw 48-57.



  • verano123 schrieb:

    Klar aber welchen Sinn hätte Modulo hier?

    Modulo ist für die andere Richtung, int -> String interessant.



  • void emain()
    

    Was hat das mit Standard C zu tun?
    Um die Antwort gleich mit zu liefern: nichts.

    Da hat wohl ein Lehrer wieder mal auf der faulen Haut gelegen (wie war doch das Schröder-Zitat nochmal?) und zusätzlich keine Ahnung von C; da kommen dann solche sinnfreien Aufgabenstellungen heraus.



  • Wutz schrieb:

    void emain()
    

    Was hat das mit Standard C zu tun?
    Um die Antwort gleich mit zu liefern: nichts.

    Ist das denn vom Standard verboten?

    Ein

    #define emain main
    

    oder

    int main()
    {
      emain();
    }
    

    reicht doch.

    Da ja auch noch die Definitionen von INIT_BM_WITHOUT_REGISTER_UI und END offen sind, ist ja klar, dass beim Code noch etwas fehlt.

    Wutz schrieb:

    Da hat wohl ein Lehrer wieder mal auf der faulen Haut gelegen (wie war doch das Schröder-Zitat nochmal?) und zusätzlich keine Ahnung von C;

    Das ist was anderes.
    Und weil ich es gerade noch in einem anderen Forum gefunden habe:

    DirkB schrieb:

    Noch was anderes:

    Die Funktionen getstring, copystring und appendstring wirst du von
    deinem Tutor/Professeor/IT-Lehrer bekommen haben.

    So wie die aufgerufen werden, geht das heutzutage gar nicht mehr, weil
    sie einen Bufferoverflow generieren können.
    Da gehört die Länge des Zielbereichs mit angegeben.

    Vor 30 bis 20 Jahren war man da noch nicht so sensibel.

    Wutz schrieb:

    da kommen dann solche sinnfreien Aufgabenstellungen heraus.

    Gibt es denn sinnvolle Anfängeraufgaben?



  • So, habe mich mal an daran versucht itoa als Methode zu schreiben und bin kläglich am scheitern.

    So hatte ich mir das Gedacht:

    char meinItoA(int num, char* str)
    {
        int i = 0;
    for (i = 0; num != '\0';i++)
            str[i] = '0'+1;
            return *str;
    
    }
    

    sobald der Compiler bei str[i] ankommt, bricht das Programm ab.

    Was habe ich mir dabei gedacht?

    Nun, ich schreibe eine Methode, die die Zahl durchläuft und dann die einzelnen Zahlen im String umwandelt in das ASCII Zeichen.
    Hoffe auf eine Hilfe, die es mir erklärt.

    Wo und wieso sollte ich Modulo anwenden?

    Edit:

    Okay, den Sinn von Modulo habe ich jetzt verstanden. Aufgrund der Größe der Zahl muss ich %10 benutzen oder?
    123 z.b.
    3 = nummer[2]
    2 = nummer[1]
    1 = nummer[0]

    Stimmt das so?

    Lg



  • Das Edit stimmt.

    num != '\0' ist Quatsch (auch wenn das Ergebnis stimmt)

    Du musst aus 123 dann 12 und dann 1 und dann 0 machen.
    Aber das ist Grundschulrechnen.



  • indem ich einmal &10 und danach /10 mache ?

    und warum ist num != '\0' quatsch? Ich möchte doch bis zum Ende laufen lassen.

    char meinItoA(int num, char* str)
    {
        int i = 0;
        int teilen;
    for (i = 0;i<= num ;i++)
            teilen = num%10;
            num = num/10;
            str[i] = teilen+48;
            return *str;
    
    }
    


  • '\0' ist das Zeichen mit dem Wert 0.
    Bei einem C-String markiert dieses Zeichen das Stringende.
    (Aber dieses Stringendezeichen hast du noch vergessen einzubauen.)

    Du willst aber Werte haben und keine Zeichen.

    Deine jetzige Abbruchbedingung ist aber großer Müll.

    Statt 48 schreibst du besser '0' (ohne Backslash) das hat zwar auch den ASCII-Wert 48, ist aber viel besser lesbar.


  • Mod

    verano123 schrieb:

    und warum ist num != '\0' quatsch? Ich möchte doch bis zum Ende laufen lassen.

    Ein Integer ist keine Zeichenkette. Du bist verwirrt mit den beiden unterschiedlichen Teilen der Aufgabe.



  • Okay, das mit != '\0' weiß ich jetzt. Nur für den String.

    48 zu '0' geändert.

    Trotzdem schaffe ich es nicht die Methode zum laufen zu bringen.
    Programm spuckt mir zwar keinen fehler aus, aber das ergebnis ist einfach falsch.

    int checknumbers (char* string) {
      int i;
      for (i = 0 ; string[i]!='\0';i++) {
        if (string[i] < '0' || string[i] > '9') {
          putstring("Bitte erneute eingabe der Zahl: nicht im Zahlenbereich:\n");
          return -1;
          }
        }
    
      return 1;
      }
    
    int checklength (char* string) {
      int i;
      for (i = 0;string[i]!='\0';i++){
        if (i > 3) {
        putstring("Bitte erneute eingabe der Zahl: nicht im Zahlenbereich:\n");
            return -1;
    
          }
        }
    
      return 1;
      }
    
    int meinAtoi(char *string)
    {
       unsigned short int ergebnis = 0;
        int i = 0;
            for (i = 0; string[i] != '\0'; ++i)
            ergebnis = ergebnis*10 + string[i] - '0';
    
        return ergebnis;
            }
    
    char meinItoA(int num, char* str)
    {
        int i = 0;
        int teilen;
    for (i = 0;i <= num ;i++)
            teilen = num%10;
            str[i] = teilen+'0';
            return *str;
    
    }
    
    unsigned short int zahl1;
        unsigned short int zahl2;
        unsigned short  result;
        char string_1[100];
        char string_2[100];
    
        INIT_BM_WITHOUT_REGISTER_UI;
    
        do {
    
        putstring("Bitte 1. Zahl eingeben:\n");
        getstring(string_1);
        }
        while (checknumbers(string_1)== - 1 || checklength(string_1) == -1);
            zahl1=meinAtoi(string_1);
    
       do {
        putstring("Bitte 2. Zahl eingeben:\n");
        getstring(string_1);
    
        } while (checknumbers(string_1)== -1 || checklength(string_1) == -2);
    
        zahl2=meinAtoi(string_1);
    
        result= zahl1 + zahl2;
    
        meinItoA(result,string_1);
    
        copystring("Addition beider Zahlen ist:\n",string_2);
        appendstring(string_1, string_2);
        putstring (string_1);
        END;
    

    Er liest zwar beide Zahlen ein, aber spuckt mir aber nicht die Rechnung aus, sondern nur die letzte Eingabe.

    copystring("Addition beider Zahlen ist:\n",string_2);
    appendstring(string_1, string_2);
    

    Wird auch komplett ignoriert. Ich komme einfach gerade so nicht mehr weiter.
    Über eine Lösungshilfe wäre ich echt dankbar...



  • Das bezog sich auf dein itoa

    DirkB schrieb:

    '\0' ist das Zeichen mit dem Wert 0.
    Bei einem C-String markiert dieses Zeichen das Stringende.
    (Aber dieses Stringendezeichen hast du noch vergessen einzubauen.)

    DirkB schrieb:

    Deine jetzige Abbruchbedingung ist aber großer Müll.

    Wofür steht i?
    Wofür steht num?
    Wie ändern sich diese in der for -Schleife?
    Was hat das miteinander zu tun?
    Welche Zeilen sollen in die for-Schleife?
    Warum gibst du nur das erste Zeichen zurück?

    verano123 schrieb:

    Programm spuckt mir zwar keinen fehler aus, aber das ergebnis ist einfach falsch.

    Dann stell den Compiler besser ein. Du musst den Warnlevel höher stellen.

    meinAtoi soll ein int zurück geben. ergebnis ist aber ein unsigned
    Da muss der Compiler warnen.



  • okay, ich habe es nochmal versucht zu bearbeiten und langsam Dampft der Kopf 🙂

    Stringendezeichen eingebaut. Erstmal gedauert, bis ich das verstanden habe.

    char meinItoA(int num, char* str)
    {
        int i = 0;
        int teilen;
    for (i = 0; str[i] != '\0' ;i++){
            teilen= num%10;
            num = num/10;
            str[i] = teilen+'0';
    
    }
    return *str;
    }
    
    unsigned short int meinAtoi(char *string)
    

    return statement außerhalb der for-schleife gepackt. Erst später aufgefallen...

    num steht für den Wert, der übergeben wird. Also die Addition der 2 Integerwerte aus der Main.

    i steht dafür, damit ich den Array komplett durchlaufe. 0 ++ 1 ++ 2 ++3 ++4 Stelle usw.

    Ich tu mich hier echt schwer, langsam nurnoch durchzublicken. C-Buch ist bestellt und hoffe, dass ich damit besser vorran komme.

    Was ich einfach nicht verstehe, dass er nur das 2te Zeichen nimmt.

    5+6 = 11 eigentlich,
    er spuckt mir weiterhin nur 1 aus.
    5+7 = 13
    er spuckt mir 3 aus.

    copystring("Addition beider Zahlen ist:\n",string_2);
        appendstring(string_1, string_2);
    

    wird weiterhin ignoriert.



  • verano123 schrieb:

    Stringendezeichen eingebaut. Erstmal gedauert, bis ich das verstanden habe.

    char meinItoA(int num, char* str)
    {
        int i = 0;
        int teilen;
    for (i = 0; str != '\0' ;i++){
            teilen= num%10;
            num = num/10;
            str[i] = teilen+'0';
    
    }
    return *str;
    }
    

    *Nein, du hast das offensichtlich nicht verstanden.
    Ein C-String ist ein Array, bei dem die Elemente die Zeichen enthalten.
    Das Ende wird durch das Zeichen '\0' (mit dem Wert 0) gekennzeichnet.

    Wir haben hier Integer TO ASCII: Umwandlung eines Integerwertes in eine Darstellung von Zifferzeichen.

    Wenn du einen String selber zusammenbauen willst, dann musst du auch dieses Zeichen selber setzen.
    Bei dir wäre das nach der for-Schleife ein str[i] = '\0'; *

    Deine Umwandlung muss weitergehen, solange num noch einen Wert hat.

    num ist der Wert, der umgewandelt werden soll. (es ist hier egal wo der Wert her kommt)
    i ist der Index im Array, an dem die gerade berechnete Ziffer steht.
    num wird durch das teilen immer kleiner, bis es 0 ist. i wird inkrementiert.
    Deren Vergleich ist ziemlich sinnfrei.

    verano123 schrieb:

    Was ich einfach nicht verstehe, dass er nur das 2te Zeichen nimmt.

    5+6 = 11 eigentlich,
    er spuckt mir weiterhin nur 1 aus.
    5+7 = 13
    er spuckt mir 3 aus.

    Das ist nicht das zweite Zeichen, sondern das Letzte.
    Arbeite den Algorithmus mal auf einem Blatt Papier durch, dann siehst du, warum das erste Zeichen im String die Einer-Stelle ist.

    verano123 schrieb:

    copystring("Addition beider Zahlen ist:\n",string_2);
        appendstring(string_1, string_2);
    

    wird weiterhin ignoriert.

    Welcher Paramter ist Quelle und welcher Ziel?
    Da du ein Stringliteral nicht ändern darfst müsste copystring(Quelle, Ziel) sein.
    Bei appendstring auch. D.h das Resultat steht in string_2.

    In deinem Programm steht aber putstring (string_1); .

    Aber solange meinItoA den string_1 nicht richtig befüllt, kannst du nicht beurteilen, ob das ignoriert wird.



  • putstring
    getstring
    copystring
    appendstring

    Was sind denn das für Funktionen? Kenn ich nicht von Standard-C.


  • Mod

    EOP schrieb:

    putstring
    getstring
    copystring
    appendstring

    Was sind denn das für Funktionen? Kenn ich nicht von Standard-C.

    Das sind wahrscheinlich gut gemeinte (aber schlecht gemachte) Hilfsfunktionen, die der Lehrer seinen Schülern zur Verfügung gestellt hat. Weil die Standardfunktionen ja so kompliziert sind. Damit sie sich auch ja nicht dran gewöhnen, wie es richtig ginge, und später dann fleißig gets & Co. benutzen, weil es dem entspricht, was sie kennen.



  • So, ich bin nochmal ganz von vorne an die Aufgabe gegangen und habe alles umgeschrieben.

    Man, was ein Akt...

    Ich habe die itoa Funktion neugeschrieben und umgeändert.

    void meinitoa(unsigned short int uwert, char* str)
    {
    unsigned short int startwert;
    unsigned short int i;
    
       startwert = uwert;
        str[0] = ' ';
    
     for (i=4; i>=1; i--) { //läuft rückwärts 0000 -> 0001->0002->0003->0004->0005> usw usw usw...
         //da max. 4 Stellen, kann ich es ab i=4 laufen lassen.
    
        // modulo rechnen und 48 bzw '0' von ascii wird addiert.
        str[i]=(startwert % 10) +'0';
        startwert /= 10;
    }
    
    }
    

    Ansich funktioniert der Code jetzt wunderbar. Klar, nicht schön.

    12+5 = 0017
    5+6 = 0011 usw usw.

    Nicht Ideal aber es klappt.

    Wenn ich jetzt aber Werte über 4 Stellen ( siehe for schleife i=4 ) eingebe, übernimmt er diese. Ändere ich jetzt aber den Rücklaufwert für i auf z.b. 10, berechnet er es komplett ohne Fehler.

    Das verstehe ich nicht ganz, wieso er das macht, da ich eigentlich über die beiden Methoden checklength und checknumbers eine Begrenzung drinnen habe.

    wenn ich z.b. 10000 eingebe, bittet er mich um eine erneute Eingabe, innerhalb des Wertebereichs aber im Hintergrund übernimmt er die höhere Zahl.


Log in to reply