我试图提出一种快速简单的方法:“从stdin获取一个字符串并将其转换为整数。如果不能,则假装我们得到零”。

这是一个Linux嵌入式系统,CPU和内存非常宝贵。性能很重要,准确性不那么重要。这应该能够每秒执行多次摄取。我最终将其转换为守护程序,并将最新的1024个值存储在数组中。

这是我使用atoi的看法:

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[] ) {
  char *c = argv[1];
  unsigned int i = 1; /* on atoi() failure, i = 0 */

  if (i = atoi(c)) {
      puts ("atoi() success");
  }
  else {
      puts ("atoi() FAILED");
  }

  printf("argv[1] = %s\n", argv[1]);
  printf("      i = %d\n", i);
}


一些测试运行/模糊测试:


# ./test_atoi 3
atoi() success
argv[1] = 3
      i = 3

# ./test_atoi 99999999999999999999
atoi() success
argv[1] = 99999999999999999999
      i = 2147483647

# ./test_atoi 3.14159
atoi() success
argv[1] = 3.14159
      i = 3

# ./test_atoi $(echo -ne "\u2605")
atoi() FAILED
argv[1] = ★
      i = 0


这将失败:

# ./test_atoi $(echo -e "\0")
Segmentation fault


我将添加一张NUL支票:

if (argv[1] == '\0') {
    i = 0;
}


这样够了吗?我刚刚(严重)重新实现了strtol吗?
我应该继续使用strtol吗?如果是,我应该检查的内容是否还不是strtol

我真正真正关心的是不会因为输入错误而死亡。我可以很高兴地忍受转换带来的偶然垃圾。

编辑:int i = 1只是因为我想看看atoi()是否使其为0。

贫民窟随时间推移的概况

编辑:我已经删除了打印语句,并在for循环中将从stdin读取的内容包装到atoi / strtol中。

# time seq 0 999888 | ./test_atoi
real    0m5.245s
user    0m5.870s
sys     0m0.030s

# time seq 0 999888 | ./test_atoi
real    0m5.230s
user    0m5.960s
sys     0m0.050s

# time seq 0 999888 | ./test_atoi
real    0m5.395s
user    0m5.920s
sys     0m0.080s

# time seq 0 999888 | ./test_strtol
real    0m5.332s
user    0m5.860s
sys     0m0.030s

# time seq 0 999888 | ./test_strtol
real    0m5.023s
user    0m5.790s
sys     0m0.060s

# time seq 0 999888 | ./test_strtol
real    0m5.286s
user    0m5.970s
sys     0m0.010s


好吧,这太疯狂了。我应该用自己的时间做一些更有成效的工作!

最佳答案

这是一个Linux嵌入式系统,CPU和内存非常宝贵。


是。嗯不如果您运行的是普通的linux,则内核将在几千个地方使用atoi和反函数。除非您打算每秒调用数千次,否则您的单个数字解析器几乎不会产生任何影响。


  我应该继续使用strtol吗?


由于上述原因:是。


  如果是的话,我应该检查的内容还不是吗?


您应该检查strtol的返回值。我真的不支持您的“不需要精确度”方法。这样的事情要么做对了,要么是灾难性的错误。

编辑你说:


  不需要精度=我只关心值0-100


这意味着a)您只需要atoi,而不是atol / strtol;在那里,节省了CPU周期。接下来,您实际上是否需要将看起来像13.288的字符串转换为整数,还是可以假设所有字符串的长度为1到3个字符?在这种情况下,为了获得原始性能,也许

inline unsigned char char2digit(const char *c) {
    unsigned char v = *c - '0';
    return (v<1 || v>9)? 0 : v;
}
inline signed char characters2number(const char *string)
{
    size_t len = strnlen(string,4);
    if(len < 1 || len > 3)
        return -1;
    signed char val = 0;
    signed char power_of_ten = 1;
    for(unsigned char idx = 1; idx <= len; ++idx)
    {
        signed char val += power_of_ten * char2digit(string + len - idx)
        power_of_ten *= 10;
    }
    return val;
}


我的意思是,如果您在烤面包机上。否则atoi会退缩。您可能仍要检查strnlen

10-07 16:25
查看更多