String in Integer umwandeln und ausgeben ohne Library



  • 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.



  • Kompletter Code inkl.

    `putstring

    getstring

    copystring

    appendstring `

    wär mal toll.



  • #ifdef V1_Aufgabe_1
    
    // brauch ich doch nicht mehr, vorsichtshalber da lassen.
    int eigenestrlen(char *str) {
    
        int leng;
        int i;
        for (i=0; str[i] != 0; i++)
            {
                leng++;
            }
            return(leng);
        }
    
    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;
      }
    
    unsigned short int meinAtoi(char *zahlenstrahl)
    {
      unsigned short int i = 0;
    
            while(*zahlenstrahl){
                i = i*10+(*zahlenstrahl) - '0';
                zahlenstrahl ++;
            }
    return i;
    }
    
    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;
    }
    
    }
    
    void emain()
    
    {
        unsigned short int zahl1;
        unsigned short int zahl2;
        unsigned short int 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) == -1);
    
        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_2);
    
            END;
    }
    
    #endif // V1_Aufgabe_1
    

    Ihr könnt mir glauben, dass die Aufgabe mich an meine nervliche Belastungsgrenze geführt hat ... 😃

    Habe zwar Java Vorkenntnisse aber wir fangen in der Uni jetzt mit Mikrocontroller programmierung an und ich versuche mich schonmal in die Aufgaben einzuarbeiten.

    Programmiert wird über Qt-Creator mit einem externen .bat Programm, um dort alles einzugeben.



  • Swordfish schrieb:

    inkl.

    `putstring

    getstring

    copystring

    appendstring`

    🙄

    verano123 schrieb:

    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;
        }
    }
    

    warum str[0]=' '; ?
    du setzt kein Zeichenkettenende ( '\0' )?
    warum 4 ... 1 und nicht 3 ... 0 ? (dann gehört an str[4] ein '\0' )

    verano123 schrieb:

    // ...
        copystring("Addition beider Zahlen ist:\n",string_2);
        appendstring(string_1, string_2);
        putstring (string_2);
    
            END;
    }
    

    Wozu? Du hast doch schon die beiden Zahlen addiert und das Ergebnis steht in result (das Du dann per meinitoa(result,string_1); in Zeile 111 als Zeichenkette in string_1 abgelegt hast), also string_1 ausgeben und gut iss?



  • Ich kann da nicht mehr mitlesen 😮

    Ich bin zwar kein C Profi, sondern eher Hobbyprogger und habe ein wenig rumgespielt:

    #include <stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #include <ctype.h>    
    unsigned long int my_atoi (char *ergebnis)
    {
    	unsigned long int r=0;
    	int i = sizeof(ergebnis),j,k=1;
    	for (j = i; j >= 0; j--)
    	{
    		r = ((ergebnis[j]-48) * k) + r;
    		k = 10 * k;
    	}
    	return r;
    }
    int main(void)
    {   
        char ergebnis[15];
    //
        unsigned long int zahl;
    //
        sprintf (ergebnis,"%s", "987654321"); // Hier musste die Eingabe proggen
    //    zahl = atoi(ergebnis);
        zahl = my_atoi(ergebnis);
        printf("%li\n",zahl);
        return 0;
    }
    

    Diese Lösung scheint zu funzen..... Jetzt musste nur noch die Eingabe hinbekommen


  • Mod

    Dein Programm hat mehrere Fehler/Schwächen:
    -Fehlende const-correctness.
    -Die Längenermittlung in Zeile 8 ist falsch. So geht das nicht in C. Noch einmal angucken, wie das mit den C-Strings und Arrays geht.
    -Selbst wenn man die Länge korrekt ermitteln würde, wäre das komplett unnötig, wegen der Natur von C-Strings.
    -Magic Numbers.
    -Rechnung kann erheblich gekürzt werden und kann ohne Zwischenwerte auskommen.
    -Merkwürdige Bezeichnerwahl. ergebnis ?


  • Mod

    Um dem Elend mal ein Ende zu machen (ungetestet):

    unsigned long my_atoi(const char* str)
    {
      // Man beachte: Laut Aufgabenstellung nur positive Zahlen ohne Vorzeichen
    
      unsigned long value = 0;
      while(*str)
      {
        value *= 10;
        value += *str++ - '0';
      }
      return value;
    }
    


  • Danke.

    Aber atoi war ja eigentlich gelöst und die (beiden letzten) Versionen vom TO sind besser als die von Hobbyprogger.

    Das Elend ist bei itoa.



  • #include <stddef.h>
    #include <stdbool.h>
    
    bool itoa( char * dst, size_t dst_size, unsigned number )
    {
    	unsigned tmp = number;
    	size_t i = 0;
    
    	do ++i; while( tmp /= 10 );
    
    	if( i >= dst_size )
    		return false;
    
    	dst[ i-- ] = '\0';
    
    	do dst[ i-- ] = '0' + ( number % 10 );
    	while( number /= 10 );
    
    	return true;
    }
    

    ?

    // edit: die verf***** 0 !!


Anmelden zum Antworten