为了账号安全,请及时绑定邮箱和手机立即绑定

sscanf或atoi将字符串转换为整数有什么区别?

sscanf或atoi将字符串转换为整数有什么区别?

C
九州编程 2019-12-17 14:42:56
gcc 4.4.4 c89将字符串转换为整数值更好。我尝试了2种不同的方法atoi和sscanf。两者都按预期工作。char digits[3] = "34";int device_num = 0;if(sscanf(digits, "%d", &device_num) == EOF) {    fprintf(stderr, "WARNING: Incorrect value for device\n");    return FALSE;}或使用atoidevice_num = atoi(digits);我以为sscanf会更好,因为您可以检查错误。但是,atoi不会进行任何检查。
查看完整描述

3 回答

?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

*scanf()函数系列返回转换后的值的数量。因此,您应该检查以确保sscanf()返回1。 EOF因“输入失败”而ssacnf()返回,这意味着将永不返回EOF。


对于sscanf(),函数必须解析格式字符串,然后解码整数。 atoi()没有那笔开销。两者都遭受以下问题:超出范围的值会导致未定义的行为。


您应该使用strtol()或strtoul()函数,它们可以提供更好的错误检测和检查。他们还会让您知道整个字符串是否已被消耗。


如果需要int,可以随时使用strtol(),然后检查返回的值以查看它是否位于INT_MIN和之间INT_MAX。


查看完整回答
反对 回复 2019-12-17
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

如果不用担心无效的字符串输入或范围问题,请使用最简单的方法: atoi()


否则,具有最佳错误/范围检测的方法既不是也不atoi()是sscanf()。 这很好的答案都准备好了细节上缺乏错误检查atoi()和一些错误检查sscanf()。


strtol()是将字符串转换为的最严格的函数int。但这仅仅是一个开始。下面是详细的示例,以显示正确的用法,并在被接受后给出此答案的原因。


// Over-simplified use

int strtoi(const char *nptr) {

  int i = (int) strtol(nptr, (char **)NULL, 10);

  return i; 

}

就像这样atoi(),忽略了使用的错误检测功能strtol()。


要充分利用strtol(),需要考虑多种功能:


检测到没有转换:示例:"xyz"或""或"--0"?在这些情况下,endptr将匹配nptr。


char *endptr;

int i = (int)strtol(nptr, &endptr, 10);

if (nptr == endptr) return FAIL_NO_CONVERT;

整个字符串应该转换还是仅转换开头部分:"123xyz"可以吗?


char *endptr;

int i = (int)strtol(nptr, &endptr, 10);

if (*endptr != '\0') return FAIL_EXTRA_JUNK;

检测是否值这么大,结果不表示为一个long样"999999999999999999999999999999"。


errno = 0;

long L = strtol(nptr, &endptr, 10);

if (errno == ERANGE) return FAIL_OVERFLOW;

检测该值是否在than的范围之外int,但不是long。如果int和long具有相同的范围,则不需要此测试。


long L = strtol(nptr, &endptr, 10);

if (L < INT_MIN || L > INT_MAX) return FAIL_INT_OVERFLOW;

某些实现超出了C标准,并errno出于其他原因进行了设置,例如在未执行转换的情况下将errno设置为EINVAL或EINVAL Base参数的值无效。。测试这些errno值的最佳时间取决于实现。


全部放在一起:(根据您的需要进行调整)


#include <errno.h>

#include <stdlib.h>


int strtoi(const char *nptr, int *error_code) {

  char *endptr;

  errno = 0;

  long i = strtol(nptr, &endptr, 10);


  #if LONG_MIN < INT_MIN || LONG_MAX > INT_MAX

  if (errno == ERANGE || i > INT_MAX || i < INT_MIN) {

    errno = ERANGE;

    i = i > 0 : INT_MAX : INT_MIN;

    *error_code = FAIL_INT_OVERFLOW;

  }

  #else

  if (errno == ERANGE) {

    *error_code = FAIL_OVERFLOW;

  }

  #endif


  else if (endptr == nptr) {

    *error_code = FAIL_NO_CONVERT;

  } else if (*endptr != '\0') {

    *error_code = FAIL_EXTRA_JUNK;

  } else if (errno) {

    *error_code = FAIL_IMPLEMENTATION_REASON;

  }

  return (int) i;

}

注意:提到的所有功能都允许前导空格,可选的前导符号字符,并受语言环境更改的影响。需要更多代码才能进行更严格的转换。


注意:非OP标题更改偏重于重点。此答案更好地适用于原始标题“将字符串转换为整数sscanf或atoi”


查看完整回答
反对 回复 2019-12-17
  • 3 回答
  • 0 关注
  • 1056 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信