Как преобразовать строку в int64_t?
Как преобразовать параметр программы из argv
в int64_t
? atoi()
подходит только для 32-битных целых чисел.
7 ответов
Соответствующая попытка 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;
}
Есть несколько способов сделать это:
strtoll(str, NULL, 10);
Это POSIX C99-совместимый.
Вы также можете использовать strtoimax; который имеет следующий прототип:
strtoimax(const char *str, char **endptr, int base);
Это хорошо, потому что он всегда будет работать с локальным intmax_t ... Это C99, и вам нужно включить <inttypes.h>
Пользователи, пришедшие с веб-поиска, должны также учитывать std::stoll
,
Он не дает точного ответа на этот оригинальный вопрос const char*
но многие пользователи будут иметь std::string
в любом случае. Если вы не заботитесь об эффективности, вы должны получить неявное преобразование (основанное на пользовательском преобразовании с использованием одного аргумента). std::string
конструктор) в std::string
даже если у вас есть const char*
,
Это проще чем std::strtoll
который всегда будет требовать 3 аргумента.
Должен выдать, если на входе не число, но посмотрите эти комментарии.
strtoll
преобразует его в long long
который обычно является 64-битным Int.
Делать это на 100% переносимо немного сложно. long long
должен быть не менее 64 бит, но не обязательно должен быть дополнением до двух, так что он не сможет представлять -0x7fffffffffffffff-1
и, таким образом, используя strtoll
может иметь сломанный угловой чехол. Та же проблема относится к strtoimax
, Вместо этого вы можете использовать начальный пробел (если вы хотите разрешить начальный пробел) и сначала проверить наличие знака, а затем использовать strtoull
или же 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;
Эта логика написана, чтобы избежать всех случаев переполнения.
Это сработало для меня с другим типом int64, и мне нравится чистый стиль C++:
std::istringstream iss(argv[i]);
int64_t i64;
iss >> i64;
Вы можете получить ошибку компиляции: operartor<<... не определен.
И я не знаю, что произойдет, если argv[i] содержит "HALLO".
Как преобразовать строку в 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
}