Funktion htoi umstellen



  • #define YES 1
    #define NO 0
    
    int htoi(char s[])
    {
       int hexdigit, i, inhex, n;
    
       i=0;
       if (s[i]== '0')
       {
          ++i;
          if (s[i]=='x' || s[i]=='X')
             ++i;
       }
    
       n=0;
       inhex=YES;
       for (; inhex==YES; ++i;)
       {
          if (s[i] >= '0' && s[i] <= '9')
             hexdigit=s[i] - '0';
          else if (s[i] >= 'a' && s[i] <= 'f')
             hexdigit=s[i] - 'a' + 10;
          else if (s[i] >= 'A' && s[i] <= 'F')
             hexdigit=s[i] - A + 10;
          else
             inhex=NO;
          if (inhex==YES)
             n = 16*n+hexdigit;
       }
       return n;
    }
    

    Ich habe obigen Code geschrieben um eine gannzahlige Zeichenkette mit hexadezimalen Ziffern in den entsprechen ganzzahligen Wert umzuwandeln.
    Nun möchte ich so ändern,dass ich die zulässigen Ziffern (0-9,a-f und A-F) in ein Array tue und dann mit einer Schleife dynamisch überprüfe.Hat jemand eine Idee wie ich das am besten umsetzen kann?



  • Joe1903 schrieb:

    Nun möchte ich so ändern,dass ich die zulässigen Ziffern (0-9,a-f und A-F) in ein Array tue und dann mit einer Schleife dynamisch überprüfe.Hat jemand eine Idee wie ich das am besten umsetzen kann?

    Naja, die Zeichen von 0...f in ein Array packen, dann das gesuchte Zeichen darin lokalisieren und den Array-Index mit 16^n multiplizieren. n ist dabei die Stelle in der Hex-Zahl. Und zum Schluss alle Zwischenergebnisse addieren.

    Davon abgesehen ist das alles irgendwie doof. Dein if-else-Netzwerk ist doch okay so. 🙂



  • Andromeda schrieb:

    Joe1903 schrieb:

    Nun möchte ich so ändern,dass ich die zulässigen Ziffern (0-9,a-f und A-F) in ein Array tue und dann mit einer Schleife dynamisch überprüfe.Hat jemand eine Idee wie ich das am besten umsetzen kann?

    Naja, die Zeichen von 0...f in ein Array packen, dann das gesuchte Zeichen darin lokalisieren und den Array-Index mit 16^n multiplizieren. n ist dabei die Stelle in der Hex-Zahl. Und zum Schluss alle Zwischenergebnisse addieren.

    Davon abgesehen ist das alles irgendwie doof. Dein if-else-Netzwerk ist doch okay so. 🙂

    Könntest du mal die Schleife schreiben?Habs net so kapiert.



  • Joe1903 schrieb:

    Könntest du mal die Schleife schreiben?

    Beispielsweise so:

    int getHexDigitValue (char c)
    {
        static char *hex = "0123456789abcdef";
        int s;
        for (s=0;;s++)
        {
            if (hex[s] == c)
                return s;    // gefunden
            if (!hex[s])
                return -1;  // nicht gefunden
        }
    }
    

    Ziemlich umständlich, eh? Und das ist nicht einmal alles.
    Dein alter Code ist definitiv besser.



  • Andromeda schrieb:

    Joe1903 schrieb:

    Könntest du mal die Schleife schreiben?

    Beispielsweise so:

    int getHexDigitValue (char c)
    {
        static char *hex = "0123456789abcdef";
        int s;
        for (s=0;;s++)
        {
            if (hex[s] == c)
                return s;    // gefunden
            if (!hex[s])
                return -1;  // nicht gefunden
        }
    }
    

    Ziemlich umständlich, eh? Und das ist nicht einmal alles.
    Dein alter Code ist definitiv besser.

    Oh ja.Was ist mit A-F? Und mit s müsste ich jetzt die Berechnung machen oder (n=c[s]*16^n?)



  • Joe1903 schrieb:

    Oh ja.Was ist mit A-F?

    Es gibt die Funktion tolower aus ctype.h

    Joe1903 schrieb:

    Und mit s müsste ich jetzt die Berechnung machen

    Ja.

    Joe1903 schrieb:

    oder (n=c[s]*16^n?)

    Nein, denn c[s] ist ein Zeichen

    Der Operator ^ ist in C nicht die Potenz.
    Du kannst auch das Zwischenergebnis mit 16 multiplizieren (oder um 4 Bits nach links schieben).



  • Joe1903 schrieb:

    Oh ja.Was ist mit A-F?

    Du kannst die Zeile "if (hex[s] == c)" in "if (hex[s] == tolower(c))" abändern. Dann frisst er das auch.

    Joe1903 schrieb:

    Und mit s müsste ich jetzt die Berechnung machen oder (n=c[s]*16^n?)

    Du fügst z.B. ein weiteres Argument ein, also diese Signatur: "int getHexDigitValue (char c, unsigned pos)" <-- Stelle der Hexziffer
    Und dann änderst du die Zeile "return s;" in "return s * (int)pow(16.0, pos);". Das ist schon mal die halbe Miete.

    Viel Spaß. 🙂



  • DirkB schrieb:

    Joe1903 schrieb:

    oder (n=c[s]*16^n?)

    ...
    Der Operator ^ ist in C nicht die Potenz.

    Da bin ich gar nicht drauf gekommen, daß das eine Potenz sein sollte.
    Ich hab mir nur gedacht: "Huch, das ist aber eine gewagte Konstruktion, deren Sinn sich mir nicht wirklich erschließt."



  • Mir fällt noch ein: anstelle von "pow" kann man die Sechzehnerpotenzen auch in einem Array ablegen. 4 Stück sollten wohl erstmal reichen: 1, 16, 256, 4096.


  • Mod

    Andromeda schrieb:

    Mir fällt noch ein: anstelle von "pow" kann man die Sechzehnerpotenzen auch in einem Array ablegen. 4 Stück sollten wohl erstmal reichen: 1, 16, 256, 4096.

    16 hoch x = 1 << 4*x
    Nicht weiter erzählen, ist ein Mathematikergeheimnis.



  • Für sowas benutzt man sscanf.



  • Andromeda schrieb:

    Mir fällt noch ein: anstelle von "pow" kann man die Sechzehnerpotenzen auch in einem Array ablegen. 4 Stück sollten wohl erstmal reichen: 1, 16, 256, 4096.

    Potenzen sind doch gar nicht nötig

    int my_atoi(char s[]) // Wandelt Dezimalstring in int um. Ohne Vorzeichen
    {  
      int ret = 0;
      while (isdigit(*s))
      { i *= 10;          // Basis 10
        i += *s++;
      }
    
      return ret;
    }
    


  • Wutz schrieb:

    Für sowas benutzt man sscanf.

    Lass die Leute doch mal die Grundlagen lernen.



  • Aber nicht anhand von Deppen-Aufgaben, die die Standardbibliothek erledigen kann.



  • Wutz schrieb:

    Aber nicht anhand von Deppen-Aufgaben, die die Standardbibliothek erledigen kann.

    Vielleicht braucht er das eine kleine MCU mit wenig Flash und RAM. Da sind Schwergewichte wie sscanf eher nicht so toll.



  • DirkB schrieb:

    Andromeda schrieb:

    Mir fällt noch ein: anstelle von "pow" kann man die Sechzehnerpotenzen auch in einem Array ablegen. 4 Stück sollten wohl erstmal reichen: 1, 16, 256, 4096.

    Potenzen sind doch gar nicht nötig

    int my_atoi(char s[]) // Wandelt Dezimalstring in int um. Ohne Vorzeichen
    {  
      int ret = 0;
      while (isdigit(*s))
      { i *= 10;          // Basis 10
        i += *s++;
      }
    
      return ret;
    }
    

    Stimmt. Aber sein erster Code ist immer noch der beste (wenn er denn funktioniert). 🙂



  • @Joe1903: Es macht überhaupt keinen Sinn hier ständig Fragen zur Erweiterung/Umstellung von Code zu stellen, den Du irgendwo im Internet gefunden hast, wo er als Lösung zu K&R Aufgaben eingestellt wurde.

    Das verwirrt nur, weil niemand einschätzen kann, auf welchem Stand Du bist.

    Abgesehen davon ist die Lösung bestenfalls Mittelmaß.


Log in to reply