htoi() - hex- zu dez-Werten wandeln



  • Hi folks,

    ich hab mir ne Funktion htoi geschrieben, die mir ne eingegebene hex-Zahl in ne dezimalzahl wandelt. Klappt alles super, ich möchte nur wissen, ob man folgenden code noch kompakter schreiben kann.

    #include <stdio.h>
    #include <ctype.h>
    #include <string.h>
    
    int htoi(char s[]);
    int pow(int base, int exp);
    
    int main()
    {
    	char hex[11];
    
    	printf("\n-----Hex-->Dez-----\n\n");
    
    	printf("Hex (0x...) : ");
    	scanf("%s", hex);
    
    	printf("Hex: %s ---> Dez: %d\n\n", hex, htoi(hex));
    
    return 0;
    }
    
    int htoi(char s[])
    {
    	unsigned int dez=0, i, j=0;
    
    	for (i=strlen(s)-1; i>1/*note 0x!!!*/; i--) {
    
    		if ( isdigit(s[i]) ) {
    
    			dez += (s[i] - '0') * pow(16,j);  
    		}
    
    		if ( (s[i] >= 0x41 && s[i] <= 0x46) || (s[i] >= 0x61 && s[i] <= 0x66) ) {// a...f OR A...F
    
    			s[i]=tolower(*(s+i));// ;-)
    			dez += (s[i] - 'a' + 10) * pow(16,j);
    		}
    
    		j++;
    	}
    
    	return dez;
    }
    
    int pow(int base, int exp)
    {
    	int pow=1,i;
    
    	for (i=0; i < exp; i++)
    		pow *= base;
    return pow;
    }
    

    Falls Fehler drin sind, sagt bitte bescheid!

    Danke schon mal im Voraus für Eure Mühe!

    Chiao



  • spontan fällt mir nicht viel kürzeres ein vielleicht wenn interpreter mitpsielen sollte 😃

    int htoi(char s[]){int rv;for(rv=0;*s;++s)rv=16*rv+toupper(*s) -'0'-!isdigit(*s)*7;return rv;}
    
    int htoi(char s[]){return *s?pow(16,strlen(s)-1)*(toupper(*s) -'0'-!isdigit(*s)*7) + htoi(s+1):0;}
    


  • @Windalf
    Grausam die Schrottpresse, die du da anwendest ;).

    @/bin/bashor
    Du willst es also kompakter?

    int htoi(const char *s)
    {
       int rueck;
    
       sscanf(s, "%x", &rueck);
    
       return(rueck);
    }
    

    PS: Kleiner Tip. Benutze nicht die Zahlenwerte, wenn es sich um Buchstaben handelt. Ein 'A' ist besser zu lesen als 0x41



  • @AJ
    sscanf gilt nicht...
    ist ja das gleiche wie wenn ich mir nen sinus selber schreiben will und dann sin aus math.h dafür verwende 😉

    Grausam die Schrottpresse, die du da anwendest .

    er wollte es ja kompackt haben 😃



  • @AJ

    Alter Schwede, das is ne Lösung! Danke dafür. Ich arbeite gerade die Aufgaben von Kernighan und Ritchie(Programmieren in C) durch. Die htoi() Funktion wird in Aufgabe 2 - 3 gefordert. Bis zu diesem Punkt hat man die sscanf() Funktion noch nicht gelernt, und deshalb hatte ich von Lösungen in deine Richtung abgesehen. Ich wollt es halt 'zur Fuss' machen.

    Danke nochmal!

    Euer bash0R



  • Eine weitere Möglichkeit.

    int htoi( const char *s )
    {
        return (int)strtol( s, (char **)NULL, 16 );
    }
    


  • Windalf schrieb:

    @AJ
    sscanf gilt nicht...
    ist ja das gleiche wie wenn ich mir nen sinus selber schreiben will und dann sin aus math.h dafür verwende 😉

    Nein ist nicht das gleiche. Es gibt keine htoi() im Standard.
    Und wenn dann darfst du auch kein toupper() und isdigit() verwenden, sondern musst es erst vorher selber proggen. :p 😉



  • @AJ
    ok dann wars zumindest sehr unsportlich sscanf zu nehmen 😃



  • Windalf schrieb:

    @AJ
    ok dann wars zumindest sehr unsportlich sscanf zu nehmen 😃

    Ist Programmieren ein Sport? Wo kann ich mich zu Olympia anmelden? 🤡



  • Ist Programmieren ein Sport? Wo kann ich mich zu Olympia anmelden?

    das wird erst 12 Jahre nachdem Unterwassermurmeln anerkannt ist olympisch... 😉



  • /bin/bash0R schrieb:

    pow(16,j)
    

    Hier bekommst du die Antwort, wie man sowas "kompakter" macht.



  • Programmieren als Olympiadisziplin, das wär's, und die Erzeugnisse gehen an gemeinnützige Vereine wie Microsoft, damit die auch mal in den Genuss von guter Software kommen 😉



  • Hab mir gerade deinen Code noch mal kurz angeschaut und würde statt

    if ( isdigit(s[i]) ) { 
    
                dez += (s[i] - '0') * pow(16,j);   
            } 
    
            if ( (s[i] >= 0x41 && s[i] <= 0x46) || (s[i] >= 0x61 && s[i] <= 0x66) ) {// a...f OR A...F 
    
                s[i]=tolower(*(s+i));// ;-) 
                dez += (s[i] - 'a' + 10) * pow(16,j); 
            }
    

    nicht auch folgendes gehen

    if (isdigit(s[i]))
        dez = dez * 16 + (s[i] - '0');
    else if (s[i] >= 'A' && s[i] <= 'F')
        dez = dez * 16 + (10 + s[i] - 'A');
    else if (s[i] >= 'a' && s[i] <= 'f')
        dez = dez * 16 + (10 + s[i] - 'a');
    else
        // Fehler: kein gueltiges hex Zeichen
        ;
    


  • Hallo zusammen,

    @groovemaster2002
    Danke groovemaster2002, deine Lösung kommt ohne die power() aus.
    Das spart Rechenzeit und Stack-Kapazität.

    Danke

    Chiao



  • Wobei meine Lösung nicht ganz zu deinem Code passt, da du im String von der Stelle mit der geringsten Wertigkeit zu der mit der höchsten Wertigkeit gehst. Mein Vorschlag funktioniert aber nur, wenn das genau andersrum wäre. Willst du diese Reihenfolge beibehalten, sind kleine Anpassungen notwendig. Dann müssen die einzelnen Berechnungen ungefähr so aussehen

    dez += (s[i] - '0') * j;
    

    j ist weiterhin deine Laufvariable, die vor der Schleife mit 1 initialisiert wird und in der Schleife entsprechend berechnet wird

    j *= 16;
    


  • /bin/bash0R schrieb:

    @AJ

    Alter Schwede, das is ne Lösung! Danke dafür. Ich arbeite gerade die Aufgaben von Kernighan und Ritchie(Programmieren in C) durch. Die htoi() Funktion wird in Aufgabe 2 - 3 gefordert. Bis zu diesem Punkt hat man die sscanf() Funktion noch nicht gelernt, und deshalb hatte ich von Lösungen in deine Richtung abgesehen. Ich wollt es halt 'zur Fuss' machen.

    Danke nochmal!

    Euer bash0R

    Ich arbeite auch das Buch durch.... vielleicht kann man sich ja gegenseitig helfen, damit wir das Buch durchpacken !



  • Ich bekomme da falsche Werte angezeigt, wenn ich das Programm benutzte..

    Ox222 = 2 kommt zum Beispiel auch mal vor und ich hab nachgeprüft, dass dies nicht die richtige umgewandelte Dezimalzahl ist !



  • Dann zeig doch mal deinen Code.

    cHillb3rT schrieb:

    Ox222

    ist übrigens kein hex Literal.



  • #define YES 1
    #define NO 0

    /* htoi: hexadezimal TExt in int verwandeln */

    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; /* keine gültige Hex-Ziffer */
    if (inhex == YES)
    n = 16 * n + hexdigit;
    }
    }

    @ Groove: Ne ich habs gelöst, aber ich hab hier noch eine andere Variante zum Lösen gefunden !



  • @chillbert
    Bitte CPP (C/C++) Tags verwenden.


Anmelden zum Antworten