简体   繁体   English

如何将字符串转换为 int64_t?

[英]How to convert string to int64_t?

How to convert program parameter from argv to int64_t ?如何将程序参数从argv转换为int64_t atoi() is suitable only for 32 bit integers. atoi()仅适用于 32 位整数。

A C99 conforming attempt.符合 C99 的尝试。

[edit] employed @R. [编辑] 使用@R。 correction更正

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

There are a few ways to do it:有几种方法可以做到:

  strtoll(str, NULL, 10);

This is POSIX C99 compliant.这是符合 POSIX C99 的。

you can also use strtoimax;你也可以使用 strtoimax; which has the following prototype:它具有以下原型:

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

This is nice because it will always work with the local intmax_t ... This is C99 and you need to include <inttypes.h>这很好,因为它始终与本地 intmax_t 一起使用...这是 C99,您需要包含<inttypes.h>

strtoll将其转换为long long ,通常是 64 位 int。

Doing this 100% portably is a little bit tricky. 100% 可移植地执行此操作有点棘手。 long long is required to be at least 64 bits, but need not necessarily be twos complement, so it might not be able to represent -0x7fffffffffffffff-1 , and thus using strtoll could have a broken corner case. long long要求至少为 64 位,但不一定是二进制补码,因此它可能无法表示-0x7fffffffffffffff-1 ,因此使用strtoll可能会出现坏的情况。 The same issue applies to strtoimax .同样的问题适用于strtoimax What you could do instead is consume leading space (if you want to allow leading space) and check for the sign first, then use strtoull or strtoumax , either of which is required to support values up to the full positive range of int64_t .您可以做的是消耗前导空间(如果您想允许前导空间)并首先检查符号,然后使用strtoullstrtoumax ,这两者都需要支持高达int64_t的完整正范围的值。 You can then apply the sign:然后,您可以应用该标志:

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

This logic is written to avoid all overflow cases.编写此逻辑是为了避免所有溢出情况。

Users coming from a web search should also consider std::stoll .来自网络搜索的用户也应该考虑std::stoll

It doesn't strictly answer this original question efficiently for a const char* but many users will have a std::string anyways.对于const char*它并没有严格有效地回答这个原始问题,但许多用户无论如何都会有一个std::string If you don't care about efficiency you should get an implicit conversion (based on the user-defined conversion using the single-argument std::string constructor) to std::string even if you have a const char* .如果您不关心效率,即使您有const char*也应该获得隐式转换(基于使用单参数std::string构造函数的用户定义转换)到std::string

It's simpler than std::strtoll which will always require 3 arguments.它比std::strtoll更简单,后者总是需要 3 个参数。

It should throw if the input is not a number, but see these comments .如果输入不是数字,它应该抛出,但请参阅这些评论

This worked for me with a different int64 type, and I like the clean C++ style:这对我使用了不同的 int64 类型,我喜欢干净的 C++ 风格:

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

You may get an compile error: operartor<<... is not defined.您可能会收到编译错误:operartor<<... 未定义。

And I don't know what happens, if argv[i] contains "HALLO".如果 argv[i] 包含“HALLO”,我不知道会发生什么。

How to convert string to int64_t?如何将字符串转换为 int64_t?

The simplest最简单的

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

Better更好的

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

Robust: Create a helper function to detect all problems.健壮:创建一个辅助函数来检测所有问题。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM