#include <stdlib.h> int atoi(const char *nptr); double atof(const char *nptr); 返回值:轉換結果
atoi把一個字元串開頭可以識別成十進制整數的部分轉換成int型,相當於下面要講的strtol(nptr, (char **) NULL, 10);。例如atoi("123abc")的返回值是123,字元串開頭可以有若干空格,例如atoi(" -90.6-")的返回值是-90。如果字元串開頭沒有可識別的整數,例如atoi("asdf"),則返回0,而atoi("0***")也返回0,根據返回值並不能區分這兩種情況,所以使用atoi函數不能檢查出錯的情況。下面要講的strtol函數可以設置errno,因此可以檢查出錯的情況,在嚴格的場合下應該用strtol,而atoi用起來更簡便,所以也很常用。
atof把一個字元串開頭可以識別成浮點數的部分轉換成double型,相當於下面要講的strtod(nptr, (char **) NULL);。字元串開頭可以識別的浮點數格式和C語言的浮點數常量相同,例如atof("31.4 ")的返回值是31.4,atof("3.14e+1AB")的返回值也是31.4。atof也不能檢查出錯的情況,而strtod可以。
#include <stdlib.h> long int strtol(const char *nptr, char **endptr, int base); double strtod(const char *nptr, char **endptr); 返回值:轉換結果,出錯時設置errno
strtol是atoi的增強版,主要體現在這幾方面:
不僅可以識別十進制整數,還可以識別其它進制的整數,取決於base參數,比如strtol("0XDEADbeE~~", NULL, 16)返回0xdeadbee的值,strtol("0777~~", NULL, 8)返回0777的值。
endptr是一個傳出參數,函數返回時指向後面未被識別的第一個字元。例如char *pos; strtol("123abc", &pos, 10);,strtol返回123,pos指向字元串中的字母a。如果字元串開頭沒有可識別的整數,例如char *pos; strtol("ABCabc", &pos, 10);,則strtol返回0,pos指向字元串開頭,可以據此判斷這種出錯的情況,而這是atoi處理不了的。
如果字元串中的整數值超出long int的表示範圍(上溢或下溢),則strtol返回它所能表示的最大(或最小)整數,並設置errno為ERANGE,例如strtol("0XDEADbeef~~", NULL, 16)返回0x7fffffff並設置errno為ERANGE。
回想一下使用fopen的套路if ( (fp = fopen(...)) == NULL) { 讀取errno },fopen在出錯時會返回NULL,因此我們知道需要讀errno,但strtol在成功調用時也可能返回0x7fffffff,我們如何知道需要讀errno呢?最嚴謹的做法是首先把errno置0,再調用strtol,再查看errno是否變成了錯誤碼。Man Page上有一個很好的例子:
例 25.10. strtol的出錯處理
#include <stdlib.h>
#include <limits.h>
#include <stdio.h>
#include <errno.h>
int main(int argc, char *argv[])
{
int base;
char *endptr, *str;
long val;
if (argc < 2) {
fprintf(stderr, "Usage: %s str [base]\n", argv[0]);
exit(EXIT_FAILURE);
}
str = argv[1];
base = (argc > 2) ? atoi(argv[2]) : 10;
errno = 0; /* To distinguish success/failure after call */
val = strtol(str, &endptr, base);
/* Check for various possible errors */
if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
|| (errno != 0 && val == 0)) {
perror("strtol");
exit(EXIT_FAILURE);
}
if (endptr == str) {
fprintf(stderr, "No digits were found\n");
exit(EXIT_FAILURE);
}
/* If we got here, strtol() successfully parsed a number */
printf("strtol() returned %ld\n", val);
if (*endptr != '\0') /* Not necessarily an error... */
printf("Further characters after number: %s\n", endptr);
exit(EXIT_SUCCESS);
}strtod是atof的增強版,增強的功能和strtol類似。