Function to enter the number in any form.

Is there a function similar to "atoi (char *str)", allowing numbers to be entered in any form? (DEC, OCT, HEX, BIN)

Ogogon.

Atoi is a standard C++ function supported by avr-libc and thus, arduino. It works, and so do most other C++ functions. For the full list, see http://www.nongnu.org/avr-libc/user-manual/globals_0x61.html

IIRC atoi() works for decimal only.
the function should be able to recognize the base it was written in. Compilers can if one use the right notation

HEX = base16 => prefix 0x or 0X
BIN = base2 => prefix B or b
OCT = base8 -> prefix 0 (zero)
DEC = base10 => no prefix and it shall not begin with a 0

so in pseudo code it should be something like code below (will not compile)

atoiii(char *str)
{
if (toUpper(str[0]) == 'B') return parseInt(&str[1], 2);
if (str[0] == '0' && toUpper(str[1]) == 'X') return parseInt(&str[2], 16);
if (str[0] == '0') return parseInt(&str[1], 8); break;
return parseInt(str, 10);
}

parseInt(char * str, int base)
{
int rv = 0
char n[16] = { '0', '1', .... 'A', ... 'F' }; //well known digits
for (int i=0; i<strlen(str); i++)
{
rv += indexOf(str*, n);*
_ rv *= base;_

  • }*
    }
    Should get you started.
//
// A few tests using  the standard library function strtol()
// to convert numeric strings to integers in base 2, 8, 10, and 16
//
// davekw7x
//
void setup()
{
    Serial.begin(9600);
}

void loop()
{
    char *s2  = "01011100"; // 88 decimal  [edit]<---Incorrect comment;  The decimal value is 92, as I show below. [/edit]
    char *s8  = "1673";     // 955 decimal
    char *s10 = "9986";     // 9986 decimal
    char *s16 = "ab12";     // 43794 decimal
    
    long x2 = getIntegerWithBase(s2, 2);
    Serial.print("1: x2  = ");Serial.println(x2);Serial.println();

    // Try to get a binary number from "1673"
    x2 = getIntegerWithBase(s8, 2);
    Serial.print("2: x2  = ");Serial.println(x2);Serial.println();

    long x8 = getIntegerWithBase(s8, 8);
    Serial.print("3: x8  = ");Serial.println(x8);Serial.println();

    long x10 = getIntegerWithBase(s10, 10);
    Serial.print("4: x10 = ");Serial.println(x10);Serial.println();

    long x16 = getIntegerWithBase(s16, 16);
    Serial.print("5: x16 = ");Serial.println(x16);Serial.println();
    
    delay(10000);
}

long getIntegerWithBase(char *s, int base)
{
    char *endPtr;
    long retval = strtol(s, &endPtr, base);
    if (*endPtr) {
        Serial.print("   Couldn't convert all of <");
        Serial.print(s);
        Serial.print("> to base ");
        Serial.println(base);
        Serial.print("   First ignored character is 0x");
        Serial.println(*endPtr, HEX);
        Serial.println("   Returned value may not be what you had in mind.");
        Serial.println();
    }
    return retval;
}

Output:


1: x2  = 92

   Couldn't convert all of <1673> to base 2
   First ignored character is 0x36
   Returned value may not be what you had in mind.

2: x2  = 1

3: x8  = 955

4: x10 = 9986

5: x16 = 43794

Regards,

Dave

robtillaart:
...
BIN = base2 => prefix B or b

There is no standard C or C++ representation of a binary constant.

There is a GNU extension that uses prefix 0b and there are Arduino macro definitions for some B... stuff. If someone made me choose, I would choose 0b, but actually I (almost) always resist non-standard language features wherever it is practical.

Since we are making up our own function for string conversion here, anything goes, but I thought I would mention it.

Regards,

Dave

char *s2  = "01011100"; // 88 decimal

Ooops

char *s8  = "1673";     // 955 decimal

Oo-er.
(Octal is normally written with a leading zero in C)

AWOL:
Oo-er.

Hey! I don't just make up this stuff, you know, and I didn't fake the output. You get the same with any standard C or C++ compiler and library, including Arduino's compiler, avr-gcc and library, avr-libc.

That is the way that the standard library function strtol() converts ASCII strings to integer values, and it's been doing that since some time before the publication of the ANSI Standard C language specification in 1989. If anyone doesn't like it, they can make up their own.

AWOL:
Octal is normally written with a leading zero in C)

That is a standard language feature for identifying an octal constants in source code for C and C++ compilers, and has nothing to do with strtol().

Regards,

Dave

Footnote:
About leading '0' indicating octal: If you call strtol() with the special value of base equal to zero, it treats numbers with leading '0' as octal. With base equal to zero, hex numbers must have "0x" or "0X" in front. Otherwise it's treated as decimal.

With bases from 2 up to and including base 36, it just goes as far as it can with characters that can be digits in that base, then it quits.

Note that with base = 16, the string is treated as hexadecimal. Period. For this special case, the leading "0x" or "0X" is optional.

I'm not pointing fingers, but I'm still having problems with

char *s2 = "01011100"; // 88 decimal

in any particular base.

AWOL:
I'm not pointing fingers, but I'm still having problems with

char *s2 = "01011100"; // 88 decimal

in any particular base.

I regret the incorrect comment. For binary "01011100" the answer is, of course 92 decimal, as my output shows.

I really try not to post incorrect stuff, and incorrect comments are sometimes (nearly) as destructive as incorrect code.

I added a note to the comment in my original post. Thanks for caring enough to call it to my attention.

Sorry.

Regards,

Dave

Trying various bases, I get:

base = 2  result= 92
base = 3  result= 846
base = 4  result= 4432
base = 5  result= 16400
base = 6  result= 48204
base = 7  result= 120442
base = 8  result= 266816
base = 9  result= 538812
base = 10  result= 1011100
base = 11  result= 1787654
base = 12  result= 3008592
base = 13  result= 4857736
base = 14  result= 7570892
base = 15  result= 11444850
base = 16  result= 16847104
base = 17  result= 24226292
base = 18  result= 34123356

The code worked, though (as davekw7x notes).

That reminds me of another recent post:

 if (val == 10) {              // If the serial value is 2,