sträng till int, i C?
sträng till int, i C?
Någon som vet en listig minnessnål metod att omvandla en sträng innehållande ett tvåsiffrigt hexadecimalt nummer till en int?
Tex "5B" till en int.
Det finns en färdig c-funktion för detta men den tar en hel del minne och det börjar bli lite trångt i Atmega88'an.
Har själv en del varianter löst skissade i huvudet, men någon kanske har en bättre ide.
Tex "5B" till en int.
Det finns en färdig c-funktion för detta men den tar en hel del minne och det börjar bli lite trångt i Atmega88'an.
Har själv en del varianter löst skissade i huvudet, men någon kanske har en bättre ide.
Jovars.....
alternativt
Kod: Markera allt
word HexToInt(char * Data,byte Numbers)
{
word Result = 0;
while(Numbers)
{
Result <<= 4;
switch(*Data)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
Result += *Data - '0';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
Result += *Data - 'A' + 10;
break;
}
Numbers--;
Data++;
}
return(Result);
}
Kod: Markera allt
word HexToInt(char * Data,byte Numbers)
{
word Result = 0;
while(Numbers)
{
Result <<= 4;
if((*Data >= '0') && (*Data <= '9')) Result += *Data - '0';
else if((*Data >= 'A') && (*Data <= 'F')) Result += *Data - 'A' + 10;
// else ILLEGAL CHARACTER.....
Numbers--;
Data++;
}
return(Result);
}
Eller så:
unsigned int hex2int(char *s)
{
unsigned char val;
val = *s>='a'?*s-('a'-10):*s-'0';
s++;
val <<= 4;
val += *s>='a'?*s-('a'-10):*s-'0';
return val;
}
int main(int argc, char *argv[])
{
char hexval[] = {"fe"};
printf("HexStr: %s Int: %.02x\n", hexval, hex2int(hexval));
}
Har iofs ingen koll på om det är illegala hextecken in....
unsigned int hex2int(char *s)
{
unsigned char val;
val = *s>='a'?*s-('a'-10):*s-'0';
s++;
val <<= 4;
val += *s>='a'?*s-('a'-10):*s-'0';
return val;
}
int main(int argc, char *argv[])
{
char hexval[] = {"fe"};
printf("HexStr: %s Int: %.02x\n", hexval, hex2int(hexval));
}
Har iofs ingen koll på om det är illegala hextecken in....
dennis: lite ineffktivt kanske.... samma funktion 2 gg. Kan också bara konvertera 2 tecken till en byte.
Men visst är den kompakt och att ändra den är ju snabbt.
Gimbal: i Dennis' rutin ska du tänka på att ändra alla 'a' till 'A' om du avser att köra versala och i min ska du ändra 'A' osv till deras gemener motsvarigheter om du vill köra gemener.
Ett alternativ som klarar allt legalt:
Men visst är den kompakt och att ändra den är ju snabbt.
Gimbal: i Dennis' rutin ska du tänka på att ändra alla 'a' till 'A' om du avser att köra versala och i min ska du ändra 'A' osv till deras gemener motsvarigheter om du vill köra gemener.
Ett alternativ som klarar allt legalt:
Kod: Markera allt
unsigned int Hex2Int(char * Data, char Numbers)
{
unsigned int Result;
Result = 0;
while(Numbers)
{
Result <<= 4;
if((*Data >= '0') && (*Data <= '9') Result += *Data - '0';
else if((*Data >= 'A') && (*Data <= 'F') Result += *Data - ('A' + 10);
else if((*Data >= 'a') && (*Data <= 'f') Result += *Data - ('a' + 10);
// else ILLEGAL CHARACTER
Numbers--;
}
return(Result);
}
OK, då kanske en egen C rutin blir mindre än just *den* rutinen,
men en egen asm rutin som gör precis det du vill skulle säkert vinna i alla fall...
Jag menar, 16 "case", som det var i ett exempel, hur ser det ut
efter kompilering ? Jag tror knappast att kompilatorn är så smart att
den "ser" att värderna till case ligger i nummerordning, utan det blir
sannolikt 16 st tester i asm...
men en egen asm rutin som gör precis det du vill skulle säkert vinna i alla fall...
Jag menar, 16 "case", som det var i ett exempel, hur ser det ut
efter kompilering ? Jag tror knappast att kompilatorn är så smart att
den "ser" att värderna till case ligger i nummerordning, utan det blir
sannolikt 16 st tester i asm...
And here are the results from the Swedish jury.
De tre varianterna Icecap1, Icecap2 samt dennis1 var i slutändan väldigt lika. Men, vilket var huvudsaken, extremt mycket bättre än den mer generella standard C-funktionen.
Icecap1 tog acceptabla 1.7%
Icecap2 ännu bättre med 1.6%
och dennis1 rullar in på måttliga 1.8%
Den enda standardfunktionen jag hittade arbetade tyvärr med floats (strtol) och knaprade därför i sig ohyggliga 7.9% av minnet. Och nej, strtoi fanns inte.
Så vinsten i det här fallet (såvida ingen annan funktion finns) blir ganska fin.

De tre varianterna Icecap1, Icecap2 samt dennis1 var i slutändan väldigt lika. Men, vilket var huvudsaken, extremt mycket bättre än den mer generella standard C-funktionen.
Icecap1 tog acceptabla 1.7%
Icecap2 ännu bättre med 1.6%
och dennis1 rullar in på måttliga 1.8%
Den enda standardfunktionen jag hittade arbetade tyvärr med floats (strtol) och knaprade därför i sig ohyggliga 7.9% av minnet. Och nej, strtoi fanns inte.
Så vinsten i det här fallet (såvida ingen annan funktion finns) blir ganska fin.
I det här fallet så används funktionen för att kolla checksumman på ett speciellt NMEA0183 meddelande som ramlar in max 1 gång per sekund. vilket i datorsammanhang är ungefär lika med aldrig.
Har tyvärr ingen aning om hur många instruktioner 1.6% motsvarar, men med 8KB minne så det blir det ca. 131 bytes.
Har tyvärr ingen aning om hur många instruktioner 1.6% motsvarar, men med 8KB minne så det blir det ca. 131 bytes.
Blev lite nyfiken så jag provade att kompilerade lite med gcc och mega48 som target.
icecap1 adderade 88 bytes.
icecap2 adderade 82 bytes.
dennis1 adderade 58 bytes.
strtol från avr libc adderade 802 bytes.
Man skall nog tänka på att när jag tog med strtol så följde nog en hel del annat från libc med också, så om den enda rutinen man behöver från libc är strtol så lönar det sig att göra en egen.
icecap1 adderade 88 bytes.
icecap2 adderade 82 bytes.
dennis1 adderade 58 bytes.
strtol från avr libc adderade 802 bytes.
Man skall nog tänka på att när jag tog med strtol så följde nog en hel del annat från libc med också, så om den enda rutinen man behöver från libc är strtol så lönar det sig att göra en egen.
