Reputation: 746
I need to convert a large character number to a long to program my Atmega8 chip on AtmelStudio.
I tried using atol()
and strtoul()
and it does not work. I've read on google that there is a bug with strtoul()
which only allows to use smaller values. I tried and it's true. I can convert the char "250" to a long with strtoul()
but not "5555".
I've read that the fix is to make your own strtoul() function but how do I do that? I don't know the implementation of strtoul()
, it's an extern in the library.
This does not work:
char *my_time = "2505";
unsigned long new2 = (unsigned)strtoul(my_time, NULL, 10);
Upvotes: 1
Views: 372
Reputation: 399949
The core of converting an (unsigned) decimal string to an integer is:
unsigned long str2int(const char *s)
{
unsigned long x = 0;
while(isdigit(*s))
{
x *= 10;
x += *s++ - '0';
}
return x;
}
It's really not very complicated, it just walks through the digits, building up the value as it goes. The *s++ - '0'
is perhaps a sign of me failing to rein in my "experienced C programmer's maximum terseness syndrome". Also I was in kind of a hurry. A more clear approach might be:
while(isdigit(*s))
{
x *= 10; /* Each new digit makes the old ones worth more. */
const int digit = *s - '0'; /* Convert digit character to small int. */
x += digit; /* Add the current digit. */
++s;
}
So for instance, consider an input of "432"
. It would be computed as something like ((0 * 10 + 4) * 10 + 3) * 10 + 2.
Since you're working on an 8-bit microcontroller, you can probably gain a lot of code space by limiting yourself to uint16_t
instead of unsigned long
, if your application is limited to integers below 65,536.
Upvotes: 2
Reputation: 180968
It is pretty easy to convert a string of decimal digits representing a number within the range of the machine's unsigned long
type to an unsigned long
value. For example:
unsigned long my_atoul(const char *digits) {
unsigned long result = 0;
const char *c = digits;
while ('0' <= *c && *c <= '9') {
result = result * 10 + (*(c++) - '0');
}
return result;
}
If you want additional features (e.g. choice of radix) or different behavior on non-numeric or overlength input then such things can be implemented on top of that basic approach.
Upvotes: 0
Reputation: 140748
Please run this test program and tell us what it prints. If you don't have printf
, figure out some way of getting us the same information that this program prints. (If you don't have errno
, that part is not as important as the rest of it.)
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main(void)
{
const char *my_time = "2505";
char *endptr;
unsigned long value;
errno = 0;
value = strtoul(my_time, &endptr, 10);
printf("value=%lu endptr=%s delta=%ld errno=%d (%s)\n",
value, endptr, (long)(endptr - my_time),
errno, strerror(errno));
return 0;
}
Upvotes: 0