2013-06-08 6 views
15

argvからint64_tにプログラムパラメータを変換する方法はありますか? atoi()は32ビット整数にのみ適しています。文字列をint64_tに変換するには?

+0

'int64_t'が' long'と同じプラットフォームでは、すばやくハッキリなやり方は['atol()'](http://en.cppreference.com/w)です。/c/string/byte/atoi)。 –

+1

int64_tに一致する指定子でsscanfを使用すると、プラットフォームに依存しない方法が提供されます。 – chux

+2

ちょっとしたポイント:あなたが求めているのは、 'char *'を 'int64_t'に変換する方法ではありません(単純なキャストは答えになります)。代わりに' char * 'は、十進数の文字列のような人間指向のテキスト形式の数値を' int64_t'に変換します。 –

答えて

10

A 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; 
} 
+2

+1は 'sscanf'を使うという賢明な考え方ですが、あなたが必要とするのは' PRId64'ではなく 'SCNd64'です。私はまた、 'sscanf'がオーバーフローでうまく動作しなければならないかどうか不明です。 –

+0

@R .. 'scanf()'ファミリは 'strtol()'のような機能を持つように指定されていると思います。後者の場合、範囲エラーによって 'eranno'に' ERANGE'が格納されます。 (C11ドラフト7.8.2.3.3)。したがって、 'errno'テストを組み込むことができます。 – chux

+1

@chux本当ですか? [this](http://pubs.opengroup.org/onlinepubs/009604599/basedefs/inttypes.h.html)によると 'SCNd64'は' scanf'、 'PRId64'は' printf'です。 – pmichna

1

strtollは、通常は64ビットのintであるlong longに変換されます。

8

それを行うには、いくつかの方法があります。

strtoll(str, NULL, 10); 

これは、POSIX C99の準拠しています。

strtoimaxも使用できます。次のプロトタイプ持っている:それは常にローカルintmax_t型で動作しますので、

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

これはいいです...これはC99ですが、あなたはこの100%をやっ<inttypes.h>

+1

そのキャストの必要はありません... –

+0

@OliCharlesworthあなたは正しいですが、キャストは、OPがそれを解析したい場合、ヒントとして、文字列へのポインタで置き換えることができますすべて。 –

+1

@AhmedMasudそれがドキュメントの目的です。あるいはコメントかもしれない。余計なキャストを入れてはいけません。重複していて、隠れエラーを隠すかもしれません。**最も重要なのは、読みやすさが低下することです。** –

1

を含める必要がポータブルに少しはありますトリッキー。 long longは少なくとも64ビットである必要がありますが、必ずしも2の補数である必要はないので、-0x7fffffffffffffff-1を表すことができない可能性があります。したがって、strtollを使用すると、コーナーケースが壊れてしまう可能性があります。同じ問題がstrtoimaxにも当てはまります。その代わりに先導スペースを消費し、最初にサインを確認してから、strtoullまたはstrtoumaxint64_tの正の最大範囲までの値をサポートする必要があります)を使用します。

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

このロジックは、すべてのオーバーフローケースを避けるために書かれています。

+1

しかし、 'int64_t'は2の補数とは異なる符号付き表現を持つシステムで定義されているとは限りません。また、これは、整数型の整数型がオプションである主な理由の1つと考えられます。 – ouah

+0

私はPOSIXが必要と思っていましたが、実際にはPOSIXは8,16,32ビットの正確なサイズの型しか必要としません。 'int64_t'と' uint64_t'はPOSIXではオプションです。ですから、 'long'や' long long'が適切でないシステムでは、 'int64_t'が存在しそうにないと私は同意します。 –

+0

「すべてのオーバーフローのケースを避けるためにロジックがどのように書かれているか」は不明です。 ' - (x-1)-1'や' -x'は 'x'と同じ働きをします。 – chux

関連する問題