Page 1 of 1

Converting String to Integer

Posted: Sat Jun 16, 2007 2:36 am
by Cmaranec
Hello,
how can i convert integer to (for example) char dd[128] ? I tried to create function like IntToStr (from Pascal), but it didn't work...

Posted: Sat Jun 16, 2007 2:56 am
by Bughunter
1. Divide the value by the base of the numbering system (for decimal, the base is 10)
2. Convert the remainder value of the division to ASCII (for decimal, this is usually done by adding 0x30)
3. Check if the quotient of the division is 0, if it is _not_ then go back to step 1.
4. When the loop ends, reverse the string buffer (for example '54321' becomes '12345')

thx

Posted: Sat Jun 16, 2007 2:57 am
by Cmaranec
Ok, i will try it, thanks

works

Posted: Sat Jun 16, 2007 3:08 am
by Cmaranec
Yes, it works fine, thanks.

Question 2: How can i convert string to integer? (with error code) i have char firstc[64]; and char secndc[64]; and int first; and int secnd; and i want to "copy" all from 'firstc' to 'first' and from 'secndc' to 'secnd'.

Re: works

Posted: Sat Jun 16, 2007 3:45 am
by Brendan
Cmaranec wrote:Yes, it works fine, thanks.

Question 2: How can i convert string to integer? (with error code) i have char firstc[64]; and char secndc[64]; and int first; and int secnd; and i want to "copy" all from 'firstc' to 'first' and from 'secndc' to 'secnd'.
Something like this perhaps?

Code: Select all

char *convertStringToInt(int *number, char *string) {
    if(strncasecmp(string, "0x", 2) == 0) {
        // Hexadecimal
        return convertStringToIntWithBase(number, &string[2], 16);
    }
    if(*string == '0') {
        // Octal???
        return convertStringToIntWithBase(number, &string[1], 8);
    }
    // Decimal
    return convertStringToIntWithBase(number, string, 10);
}


char *convertStringToIntWithBase(int *number, char *string, int base) {
    int digit;

    *number = 0;

    for(;;) {
        if( (*string >= '0') && (*string <= '9') )  {
            digit = *string - '0';
        } else if( (*string >= 'A') && (*string <= 'Z') )  {
            digit = *string - 'A' + 10;
        } else if( (*string >= 'a') && (*string <= 'z') )  {
            digit = *string - 'a' + 10;
        } else {
            break;
        }
        if(digit >= base) {
            break;
        }
        if(*number >= INT_MAX / base) {
            return NULL; // Will overflow...
        }
        *number = *number * base;
        if(*number >= INT_MAX - digit) {
            return NULL; // Will overflow...
        }
        *number = *number + digit;
        string++;
    }
    return string;
}
Of course you can do more. For e.g. supporting binary, handling leading '-' and '+' characters, supporting arbitrary number bases (e.g. "0r6r54321" could be a number in base 6), handling exponents (e.g. "-1E2" could be -100 in decimal), etc. You could also combine all of that, so that "-0r4r32100E-0r16r1" is a base 4 number with a negative base 16 exponent (in this case, -57 in decimal). ;)


Cheers,

Brendan

thx

Posted: Sat Jun 16, 2007 4:05 am
by Cmaranec
Thank you, i am doing simple calculator :D

Re: works

Posted: Sat Jun 16, 2007 5:13 am
by Bughunter
Cmaranec wrote:Yes, it works fine, thanks.
Great job, congrats! 8)

...

Posted: Sat Jun 16, 2007 6:23 am
by Cmaranec
Sorry, have you got other code for convert string to integer?

Posted: Sat Jun 16, 2007 6:48 am
by Bughunter
Basically, you make a loop and pick a character each loop, convert the character back to a raw value, then multiply that by 10 each loop iteration. Oh yes, start at the end of the string and decrease your counter every iteration.

I'll see if I have an example laying around.

Posted: Sat Jun 16, 2007 7:03 am
by Bughunter
Here is an example:

Code: Select all

int atodw(const char *str) {
    int value = 0;

    for(int counter = strlen(str)-1, multiplier = 1; !(counter < 0); --counter, multiplier *= 10) {
        value += (str[counter] - 0x30) * multiplier;
    }
   
    return value;
}

Posted: Sat Jun 16, 2007 7:21 am
by XCHG
Here is a function that I have coded for my kernel that converts an unsigned string to a 32-bit Unsigned DWORD value. This one is optimized and it wouldn't use the MUL instruction at all for multiplication:

Code: Select all

; --------------------------------------------------
  __StrToDWORD:
    ; DWORD __StrToDWORD (const char* InStr)
    PUSH    EBX
    PUSH    EDX
    PUSH    EBP
    MOV     EBP , ESP
    MOV     EBX , DWORD PTR [EBP + 0x10]
    XOR     EAX , EAX
    .Loop:
      MOV     EDX , DWORD PTR [EBX]
      AND     EDX , 0x000000FF
      JE      .EP
      AND     EDX , 0x0000000F
      ADD     EAX , EAX
      LEA     EAX , [EAX + 0x04*EAX]
      ADD     EAX , EDX
      INC     EBX
      JMP     .Loop
    .EP:
      POP     EBP
      POP     EDX
      POP     EBX
    RET     0x04
; --------------------------------------------------

Posted: Sat Jun 16, 2007 7:41 am
by Bughunter
I have written a similar function ASM some time ago. Cmaranec wanted a C function so why post the ASM one? Since Cmaranec also asked how to convert a string back to an integer, I don't think he understands much of ASM since he's just exploring calculators :)

Imho, you shouldn't overthrow someone with 'complicated' stuff that they will probably not (yet) understand.

thx

Posted: Sat Jun 16, 2007 8:32 am
by Cmaranec
OK, thanks to all, i will try bughunter's example

wow

Posted: Sat Jun 16, 2007 9:17 am
by Cmaranec
Wow, thanks ! All the functions works well 8)

Re: wow

Posted: Sat Jun 16, 2007 9:21 am
by Bughunter
Cmaranec wrote:Wow, thanks ! All the functions works well 8)
That's good to hear :D