Bibliotheksfunktion atoi?


  • Mod

    bandchef schrieb:

    Wie soll ich das aber jetz in einer while-schleife formulieren, falls leerzeichen drin sind? Da sind ja z.B. die ersten Stelle zu überspringen da eben Leerzeichen... Das wär ja dann sowas wie eine if-Abfrage, oder? Ich kann aber doch keine if-Abfrage in den Kopf einer while-schleife schreiben, wie soll denn das gehen?

    😕 Was ist denn wohl das was im Kopf der while-Schleife steht?

    Hier mal ein bisschen Code für den Anfang. Den Rest überlasse ich aber bewusst dir. Lass erstmal solchen Kram wie Hexzahlen, Überläufe und ähnliches außen vor. Bring erst einmal die grundlegenden Sachen zum Laufen!

    int my_atoi ( const char * string )
    {
      // Discard leading whitespace
      while(isspace(*string)) ++string;
    
      // Check sign
      int sign=1;
      if (*string=='-') 
        {
          sign=-1;
          ++string;
        }
    
      // Hier dein Code
    }
    


  • Lasse die Standardbbliotheksfunktionen für dich arbeiten:

    int my_atoi(char * astring)
    {
        int i = 0, j = 0, potenz, zahl = 0, zaehler, zeichen;
        char *string=malloc(strlen(astring)+1);
        sscanf(astring,"%s",string); /* das hier entfernt führende+endende Leerzeichen und sonstige "Whitespaces" */
        while(isdigit(string[i]) != 0)
        {
        potenz = 1;
        zaehler = strlen(string);
            for(j=i; j<(zaehler-1); j=j+1)
            {
               potenz = potenz * 10;
            }
            zeichen = string[i];
            zahl = zahl + (potenz * (zeichen - '0'));
            i = i + 1;
        }
        free(string);
        return zahl;
    }
    


  • Ach noch was, hatten wir schon beim letzten mal:

    char* string_eingeben(char string[]) MUSS wissen wie viel Platz in string ist. Sonst kannst du deinen gesamten Speicher überschreiben.
    (Kann man eigentlich etwas rot blinkend hervorheben?)

    Diese Fehler sind mit der Grund dass Viren und Würmer ein System befallen können. Gewöhn dir das jetzt an.



  • Wie sage ich das ihm wieviel Platz der String hat?


  • Mod

    Wutz schrieb:

    Lasse die Standardbbliotheksfunktionen für dich arbeiten:

    Dann kannst du auch gleich strtol benutzen. Das macht es dann auch einfacher, solche Sachen wie Überlaufe abzufangen (denn atoi muss laut Standard dann INT_MAX bzw. INT_MIN zurückgeben). Dies ist übrigens wirklich, wie atoi oft implementiert wird (zumindest laut Google Code Search).



  • int my_atoi(char * astring)
    {
        int i = 0, j = 0, potenz, zahl = 0, zaehler, zeichen;
        char *string=malloc(strlen(astring)+1);
        sscanf(astring,"%s",string); /* das hier entfernt führende+endende Leerzeichen und sonstige "Whitespaces" */
        while(isdigit(string[i]) != 0)
        {
        potenz = 1;
        zaehler = strlen(string);
            for(j=i; j<(zaehler-1); j=j+1)
            {
               potenz = potenz * 10;
            }
            zeichen = string[i];
            zahl = zahl + (potenz * (zeichen - '0'));
            i = i + 1;
        }
        free(string);
        return zahl;
    }
    

    Warum ist da jetzt eigentlich ein Pointer oben in der Deklarationsliste der funktion? Versteh ich nicht...



  • Vielleicht hilfreich:
    http://de.wikipedia.org/wiki/Zeiger_(Informatik)#Zeigeroperationen

    Und dein Schleifenkopf könnte zB. so aussehen:

    while (*string != '\0' && *string >= '0' && *string <= '9')
    


  • Mein Code bisher:

    int my_atoi(char string[])
    {
    	int i = 0, j = 0, potenz, sign, zahl = 0, zaehler, zeichen;
    
    	while(isspace(string[i]) != 0)
    	{
    		i = i + 1;
    	}
    
    	while(isdigit(string[i]) != 0)
    	{
    		potenz = 1;
    		zaehler = strlen(string);
            for(j=i; j<(zaehler-1); j=j+1)
            {
                potenz = potenz * 10;
            } 
    		zeichen = string[i];
    		zahl = zahl + (potenz * (zeichen - '0'));
    		i = i + 1;
    	}
    	return zahl;
    }
    

    Die erste while-Schleife prüft mir jetzt auf die führenden Leerzeichen. Jetzt muss ich halt die Leerzeichen irgendwie wegbringen und meine Zahlenreihenfolge irgendwie verschieben. Ihr wisst was ich meine, oder? Wie aber mach ich das jetzt?



  • Warum ist da jetzt eigentlich ein Pointer oben in der Deklarationsliste der funktion? Versteh ich nicht...

    Weil es unschön (oh Gott.. hoffentlich trete ich jetzt niemandem damit auf den Fuß ;)) ist arrays zu übergeben. Normalerweise übergibt man bei zB. strings einfach einen Pointer auf sein erstes Element.



  • Guck dir das mal an, wenn Du was nicht verstehst frag 😉
    (Ach ja, auf INT_MAX und INT_MIN wird hier keine rücksicht genommen)

    #include <stdio.h>
    
    int my_atoi(char *string)
    {
      int val = 0, sign = 1;
      while (*string == ' ' || *string == '\t') // leerzeichen und tabs weg 
        ++string; // pointer wird um ein element verschoben
      if (*string == '-') // signed ?
      {
        sign = -1;
        ++string;
      }
      while (*string != '\0' && *string >= '0' && *string <= '9')
      {
        val = val * 10; // zahl wird im dezimalsystem "geshiftet"
        val += *string - '0'; // zB. '1' hat immer den wert von '0' + 1
        ++string;
      }
      return val * sign; // *sign sollte klar sein
    }
    
    int main()
    {
      char buffer[0x100];
    
      fgets(buffer, sizeof(buffer), stdin);
      printf("%i", my_atoi(buffer));
    
      return 0;
    }
    


  • Hm, Leute!

    Kann mir vielleicht jemand stückchenweise durch mein Problem helfen?

    Mein Code lautet jetzt so:

    int my_atoi(char string[])
    {
    	int i = 0, j = 0, potenz, sign, zahl = 0, zaehler, zeichen;
    
    	while(isspace(string[i]) != 0)
    	{
    		i = i + 1;
    	}
    
    	while(string[i] != '\0' && string[i] >= '0' && string[i] <= '9')
    	{
    		potenz = 1;
    		zaehler = strlen(string);
            for(j=i; j<(zaehler-1); j=j+1)
            {
                potenz = potenz * 10;
            } 
    		zeichen = string[i];
    		zahl = zahl + (potenz * (zeichen - '0'));
    		i = i + 1;
    	}
    	return zahl;
    }
    

    Ich weiß da jetzt echt nicht mehr wirklich weiter...


  • Mod

    bandchef schrieb:

    Jetzt muss ich halt die Leerzeichen irgendwie wegbringen und meine Zahlenreihenfolge irgendwie verschieben. Ihr wisst was ich meine, oder? Wie aber mach ich das jetzt?

    Warum? Du weißt doch schon, von wo aus deine Zahl losgeht. Was für einen Unterschied macht es, wo das ist?



  • bandchef (238 Beiträge) schrieb:

    Kann mir vielleicht jemand stückchenweise durch mein Problem helfen?

    Machst du gelegentlich auch mal was selber?



  • Man sieht doch, dass er es versucht hat. Dann soll er lieber fragen, als dass er einfach rät wie es funktioniert.



  • bandchef schrieb:

    Hm, Leute!

    Kann mir vielleicht jemand stückchenweise durch mein Problem helfen?

    ..

    Ich weiß da jetzt echt nicht mehr wirklich weiter...

    Also hättest Du dir alle hier geposteten Codes gründlich durchgelesen sollte das ganze wirklich kein Problem mehr darstellen.. ich meine.. ich hab dir die Aufgabe sozusagen komplett gelöst? ^^

    Lies dir den Code einfach mal genau durch, Schritt für Schritt, und versuche nachzuvollziehen was genau passiert. Wenn dann eine konkrete Frage kommt können wir die auch beantworten 😉



  • bandchef schrieb:

    Wie sage ich das ihm wieviel Platz der String hat?

    Du hattest da ein Problem mit Array als return-Wert! http://www.c-plusplus.net/forum/279679-20
    Da hatte ich was von EVA gesagt. Das hast du zumindest gelesen.
    Aber da waren auch noch ein Codebeispiele zu diesem Thema: einmal mit fgets und einmal deine modifizierte Eingabefunktion.



  • Also Leute,

    Ich hab jetzt folgenden Code:

    int my_atoi(char string[])
    {
    	int i = 0, j = 0, potenz, sign, zahl = 0, zaehler, zeichen;
    
    	while(isspace(string[i]) != 0)
    	{
    		i = i + 1;
    	}
    
    	while(string[i] != '\0' && string[i] >= '0' && string[i] <= '9')
    	{
    		potenz = 1;
    		zaehler = strlen(string);
            for(j=i; j<(zaehler-1); j=j+1)
            {
                potenz = potenz * 10;
            } 
    		zeichen = string[i];
    		zahl = zahl + (potenz * (zeichen - '0'));
    		i = i + 1;
    	}
    	return zahl;
    }
    

    Diese Funktion geht jetzt schon mal soweit, auch wenn man führende Leerzeichen eingibt. Für Leerzeichen die nach der Zahl kommen geht sie dann schon leider nicht mehr...



  • bandchef schrieb:

    ... Für Leerzeichen die nach der Zahl kommen geht sie dann schon leider nicht mehr...

    Dann ist die Zahl ja auch vorbei und du bist fertig.

    Du kannst auch statt

    while(string[i] != '\0' && string[i] >= '0' && string[i] <= '9')
    

    folgendes

    while(isdigit(string[i]) != 0)
    

    schreiben, da alles andere als Zahlen dich nicht mehr interresieren.
    ('\0' ist kein digit, also bricht die Schleife da auch ab)



  • Der Ansatz ist ja schonmal ok, und offensichtlich hast Du mit Pointern noch nie gearbeitet, sehe ich das richtig? Also das ist eigentlich ganz einfach und lohnt wirklich! Lies dir am besten mal etwas dazu durch und probiers aus, das ist nicht schwer 😉 (Auch wenn es am Anfang vielleicht so scheint)

    Und zu deiner Schleife:
    Du machst immer noch Dinge die nicht notwändig sind!
    Man kann (siehe vorher geposteter Code) auch immer erst "links shiften" (also * 10 im Dezimalsystem) wenn man eine neue Zahl findet. Also:

    while ..
    {
      zahl = zahl * 10; //oder auch zahl *= 10;
      zahl = zahl + (string[i] - '0'); // oder auch zahl += string[i] - '0';
      i = i + 1; // oder auch i += 1; oder ++i; oder i++;
    }
    

    Würde also zB. folgendes passieren:
    -in string steht "123"
    -zahl ist 0

    1. Durchlauf
    0 * 10 = 0 // zahl bleibt 0
    0 + 1 = 1 // zahl ist jetzt 1

    2. Durchlauf
    1 * 10 = 10
    10 + 2 = 12

    3. Durchlauf
    12 * 10 = 120
    120 + 3 = 123

    fertig 😃

    Desweiteren wird die Variable "sign" nirgendwo verwendet.
    Sieh dir noch mal den anderen code an und komplettier das 😉



  • Hm, wenn man mal eine Nacht drüber geschlafen hat, dann gehts gleich viel besser 🙂 Hier mal mein neuer Code. So wie es schein funktioniert dieser jetzt auch für alle Möglichkeiten, sprich mit/ohne Vorzeichen und/oder mit/ohne führende/folgende Leerzeichen. Pointer glaub ich ab ich soweit auch korrekt angewendet. Eine Frage hab ich dann noch: Dieses ++string, hab ich mir aus euren Code-Beispielen abgeguckt. Dieses Teil schaltet ja die Stellen im String weiter. Ich denke, das ist soviel wie mein vorheriges i=i+1 wie ich noch keine Pointer verwendet habe. Was aber verbirgt sich dahinter? Wenn ich ++i (Prä/Postfix) schreibe, dann bedeutet das ja i=i+1. Was ist dann aber das äquivalten zu ++string? string = string + 1; geht nicht hab ich ausprobiert, genausowenig geht *string = *string + 1;. Könnt ihr mich da aufklären?

    #include<stdio.h>
    #include<stdlib.h>
    #include<ctype.h>
    #include<string.h>
    
    char* string_eingeben(char *string)
    {
    	int i = 0;
    	char zeichen;
    	zeichen = getchar();
    
    	while(zeichen != '\n')
    	{
    		*string = zeichen;
    		zeichen = getchar();
    		++string;
    	}
    	*string = '\0';
    
    	return string;
    }
    
    int my_atoi(char *string)
    {
    	int i = 0, zahl = 0, sign = 1;
    
    	while(*string == ' ' || *string == '\t')
    	{
    		++string;
    	}
    
    	if(*string == '-')
    	{
    		sign = -1;
    		++string;
    	}
    
    	while(*string != '\0' && *string >= '0' && *string <= '9')
    	{
    		zahl = zahl * 10;
    		zahl = zahl + (*string - '0');
    		++string;
    	}
    	zahl = zahl * sign;
    	return zahl;
    }
    
    int main()
    {
    	char string[100];
    	int zahl;
    
    	string_eingeben(string);
    	zahl = my_atoi(string);
    
    	printf("my_atoi: int-Zahl = %i\n", zahl);
    
    return 0;
    }
    

    EDIT: Oh mann! Bis vor 5 min. hat der obige Code noch funktioniert. Jetzt hab ich irgendwas verändert und jetzt geht nix mehr! Und ihr könn sicher schon vermuten, dass ich es nicht weiß was fuckt...

    EDIT2: Hab den Fehler gefunden. Ich hab sign dummerweise mit 0 initialisiert! Dass, das nix wird war klar... Jetzt geht der Code jedenfalls... Auf zur nächsten Aufgabe... 🙂


Anmelden zum Antworten