AtmelStudio 中大值的 C strtoul() 错误

C strtoul() bug for large values in AtmelStudio

我需要将大字符数转换为长字符数,以便在 AtmelStudio 上对我的 Atmega8 芯片进行编程。

我试过使用 atol()strtoul() 但它不起作用。我在 google 上读到 strtoul() 有一个错误,它只允许使用较小的值。我试过了,这是真的。我可以使用 strtoul() 将字符“250”转换为长整数,但不能将“5555”转换为长整数。

我了解到解决方法是创建您自己的 strtoul() 函数,但我该怎么做呢?我不知道strtoul()的实现,它是库中的extern。

这不起作用:

char *my_time = "2505";      
unsigned long new2 = (unsigned)strtoul(my_time, NULL, 10);

请运行这个测试程序并告诉我们它打印了什么。如果您没有 printf,想出 某种方式 来让我们获得与该程序打印的相同信息。 (如果你没有 errno,那部分不如其他部分重要。)

#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;
}

将(无符号)十进制字符串转换为整数的核心是:

unsigned long str2int(const char *s)
{
  unsigned long x = 0;
  while(isdigit(*s))
  {
    x *= 10;
    x += *s++ - '0';
  }
  return x;
}

它真的不是很复杂,它只是遍历数字,边走边建立值。 *s++ - '0' 可能是我无法控制自己的 "experienced C programmer's maximum terseness syndrome" 的标志。我也有点着急。更明确的方法可能是:

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;
}

因此,例如,考虑 "432" 的输入。它会被计算为 ((0 * 10 + 4) * 10 + 3) * 10 + 2.

由于您在 8 位微控制器上工作,如果您的应用程序将自己限制在 uint16_t 而不是 unsigned long,您可能会获得大量代码 space仅限于 65,536 以下的整数。

将表示机器 unsigned long 类型范围内数字的十进制数字字符串转换为 unsigned long 值非常容易。例如:

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;
}

如果您想要额外的功能(例如基数的选择)或非数字或超长输入的不同行为,那么可以在该基本方法之上实现这些东西。