安全地將字串轉換為數字 strtoX 函式
Version >= C99
從 C99 開始,C 庫有一組安全轉換函式,將字串解釋為數字。它們的名稱形式為 strtoX
,其中 X
是 l
,ul
,d
等之一,用於確定轉換的目標型別
double strtod(char const* p, char** endptr);
long double strtold(char const* p, char** endptr);
它們會檢查轉換是否存在溢位或下溢:
double ret = strtod(argv[1], 0); /* attempt conversion */
/* check the conversion result. */
if ((ret == HUGE_VAL || ret == -HUGE_VAL) && errno == ERANGE)
return; /* numeric overflow in in string */
else if (ret == HUGE_VAL && errno == ERANGE)
return; /* numeric underflow in in string */
/* At this point we know that everything went fine so ret may be used */
如果字串實際上根本不包含任何數字,則 strtod
的這種用法將返回 0.0
。
如果這不令人滿意,可以使用附加引數 endptr
。它是指向指標的指標,指標指向字串中檢測到的數字的末尾。如果設定為 0
,如上所述,或者 NULL
,則會被忽略。
此 endptr
引數提供指示是否已成功轉換,如果成功,則表示數字結束的位置:
char *check = 0;
double ret = strtod(argv[1], &check); /* attempt conversion */
/* check the conversion result. */
if (argv[1] == check)
return; /* No number was detected in string */
else if ((ret == HUGE_VAL || ret == -HUGE_VAL) && errno == ERANGE)
return; /* numeric overflow in in string */
else if (ret == HUGE_VAL && errno == ERANGE)
return; /* numeric underflow in in string */
/* At this point we know that everything went fine so ret may be used */
有類似的函式可以轉換為更寬的整數型別:
long strtol(char const* p, char** endptr, int nbase);
long long strtoll(char const* p, char** endptr, int nbase);
unsigned long strtoul(char const* p, char** endptr, int nbase);
unsigned long long strtoull(char const* p, char** endptr, int nbase);
這些函式有第三個引數 nbase
,它儲存寫入數字的數字基數。
long a = strtol("101", 0, 2 ); /* a = 5L */
long b = strtol("101", 0, 8 ); /* b = 65L */
long c = strtol("101", 0, 10); /* c = 101L */
long d = strtol("101", 0, 16); /* d = 257L */
long e = strtol("101", 0, 0 ); /* e = 101L */
long f = strtol("0101", 0, 0 ); /* f = 65L */
long g = strtol("0x101", 0, 0 ); /* g = 257L */
nbase
的特殊值 0
表示字串的解釋方式與在 C 程式中解釋數字文字的方式相同:0x
的字首對應十六進位制表示,否則前導 0
是八進位制,所有其他數字看作十進位制。
因此,將命令列引數解釋為數字的最實用方法是
int main(int argc, char* argv[] {
if (argc < 1)
return EXIT_FAILURE; /* No number given. */
/* use strtoull because size_t may be wide */
size_t mySize = strtoull(argv[1], 0, 0);
/* then check conversion results. */
...
return EXIT_SUCCESS;
}
這意味著可以使用八進位制,十進位制或十六進位制引數呼叫程式。