简体   繁体   中英

How to convert string to int64_t?

How to convert program parameter from argv to int64_t ? atoi() is suitable only for 32 bit integers.

A C99 conforming attempt.

[edit] employed @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.

you can also use 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>

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

Doing this 100% portably is a little bit tricky. 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. The same issue applies to 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 . 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 .

It doesn't strictly answer this original question efficiently for a const char* but many users will have a std::string anyways. 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* .

It's simpler than std::strtoll which will always require 3 arguments.

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:

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

You may get an compile error: operartor<<... is not defined.

And I don't know what happens, if argv[i] contains "HALLO".

How to convert string to 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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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