25

如何将程序参数从 转换argvint64_tatoi()仅适用于 32 位整数。

4

7 回答 7

16

有几种方法可以做到:

  strtoll(str, NULL, 10);

这是 POSIX C99 兼容的。

你也可以使用 strtoimax;它具有以下原型:

 strtoimax(const char *str, char **endptr, int base);

这很好,因为它总是与本地 intmax_t 一起工作......这是 C99,你需要包括<inttypes.h>

于 2013-06-08T19:21:19.780 回答
16

符合 C99 的尝试。

[编辑] 雇用@R。更正

// Note: Typical values of SCNd64 include "lld" and "ld".
#include <inttypes.h>
#include <stdio.h>

int64_t S64(const char *s) {
  int64_t i;
  char c ;
  int scanned = sscanf(s, "%" SCNd64 "%c", &i, &c);
  if (scanned == 1) return i;
  if (scanned > 1) {
    // TBD about extra data found
    return i;
    }
  // TBD failed to scan;  
  return 0;  
}

int main(int argc, char *argv[]) {
  if (argc > 1) {
    int64_t i = S64(argv[1]);
    printf("%" SCNd64 "\n", i);
  }
  return 0;
}
于 2013-06-08T20:51:54.567 回答
3

strtoll将其转换long long为通常为 64 位 int 的 a。

于 2013-06-08T19:21:05.300 回答
3

来自网络搜索的用户也应该考虑std::stoll.

它并没有严格有效地回答这个原始问题,但许多用户无论如何const char*都会有一个。std::string如果您不关心效率std::stringstd::string即使您有一个const char*.

它比std::strtoll总是需要 3 个参数更简单。

如果输入不是数字,它应该抛出,但请参阅这些评论

于 2018-12-12T00:48:30.903 回答
2

100% 便携地做这件事有点棘手。long long要求至少为 64 位,但不一定是二进制补码,因此它可能无法表示-0x7fffffffffffffff-1,因此使用strtoll可能会出现破角情况。同样的问题适用于strtoimax. 您可以做的是消耗前导空格(如果您想允许前导空格)并首先检查符号,然后使用strtoullor strtoumax,其中任何一个都需要支持int64_t. 然后,您可以应用该标志:

unsigned long long x = strtoull(s, 0, 0);
if (x > INT64_MAX || ...) goto error;
int64_t y = negative ? -(x-1)-1 : x;

编写此逻辑是为了避免所有溢出情况。

于 2013-06-08T19:45:41.677 回答
1

这适用于我使用不同的 int64 类型,我喜欢干净的 C++ 风格:

std::istringstream iss(argv[i]);
int64_t i64;
iss >> i64;

你可能会得到一个编译错误:operator<<... is not defined。

而且我不知道如果 argv[i] 包含“HALLO”会发生什么。

于 2018-09-14T18:39:16.630 回答
1

如何将字符串转换为 int64_t?

最简单的

#include <stdlib.h>
int64_t value = atoll(some_string);  // lacks error checking.  UB on overflow

更好的

long long v = strtoll(s, NULL, 0);  // No reported errors, well defined on overflow

健壮:创建一个辅助函数来检测所有问题。

#include <stdbool.h>
#include <ctype.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>

// Return error flag
bool my_strtoi64(int64_t *value, const char *s) {
 // Maybe add a s==NULL, value==NULL checks.

  char *endptr;
  errno = 0;
  long long v = strtoll(s, &endptr, 0);

  // Optional code for future growth of `long long`
  #if LLONG_MIN < INT64_MIN || LLONG_MAX > INT64_MAX
  if (v < INT64_MIN) {
    v = INT64_MIN;
    errno = ERANGE;
  } else if (v > INT64_MAX) {
    v = INT64_MAX;
    errno = ERANGE;
  #endif

  *value = (int64_t) v;

  if (s == endptr) { // No conversion, *v is 0
    return true;
  }
  if (errno == ERANGE) { // Out of range
    return true;
  }
  if (errno) { // Additional implementations specific errors
    return true;
  }
  while (isspace(*(unsigned char* )endptr)) { // skip trail white-space
    endptr++;
  }
  if (*endptr) { // Non-numeric trailing text
    return true;
  }
  return false; // no error
}
于 2021-02-04T13:41:48.087 回答