strtol和十六進位轉二進位

來源:互聯網
上載者:User

今天,在review 一些代碼的時候,看到了strtol()這個函數,由於以前使用它的時候,還沒有深刻的瞭解,這次,我決定探個究竟。

網上關於這個函數的資料大都來源於同份資料,linux庫函數,講的不夠細緻。於是,我花了幾個小時,認真地嘗試其功能,並整理了這篇文章,希望能對C語言的愛好者一些協助。

希望大家能夠將本文中發現的錯誤及時反饋給我,以便修正。我的信箱是wp.qin@sunmedia.com 。

+----------------+
|      strtol             |
+----------------+

i.e. string to long

long int strtol(const char *nptr, char **endptr, int base)
strtol()會將nptr指向的字串,根據參數base,按權轉化為long int, 然後返回這個值。
參數base的範圍為2~36,和0;它決定了字串以被轉換為整數的權值。
可以被轉換的合法字元依據base而定,舉例來說,當base為2時,合法字元為‘0’,‘1’;base為8時,合法字元為‘0’,‘1’,……‘7’;base為10時,合

法字元為‘0’,‘1’,……‘9’;base 為16時,合法字元為‘0’,‘1’,……‘9’,‘a’,……‘f’;base為24時,合法字元為‘0’,……‘9’,‘a’,……‘n’,base

為36時,合法字元為‘0’,……‘9’,‘a’,……‘z’;等等。其中,不區分大小寫,比如,‘A’和‘a’會都會被轉化為10。
當字元合法時,‘0’,……‘9’依次被轉換為十進位的0~9,‘a’,……‘z’一次北轉換為十進位的10~35。
strtol()函數檢測到第一個非法字元時,立即停止檢測,其後的所有字元都會被當作非法字元處理。合法字串會被轉換為long int, 作為函數的返

回值。非法字串,即從第一個非法字元的地址,被賦給*endptr。**endptr是個雙重指標,即指標的指標。strtol()函數就是通過它改變*endptr的值,即把第一個非法字元的地址傳給endptr。

多數情況下,endptr設定為NULL, 即不返回非法字串。
下面看幾個例子:
------------------------------------------------------
char buffer[20]="10379cend$3";
char *stop;
printf("%d/n",strtol(buffer, &stop, 2));
printf("%s/n", stop);
輸出結果:
2
379cend$3
-------------------------------------------------------
char buffer[20]="10379cend$3";
char *stop;
printf("%d/n",strtol(buffer, &stop, 8));
printf("%s/n", stop);
輸出結果:
543
9cend$3
--------------------------------------------------------
char buffer[20]="10379cend$3";
char *stop;
printf("%d/n",strtol(buffer, &stop, 10));
printf("%s/n", stop);
輸出結果:
10379
cend$3
-------------------------------------------------------
char buffer[20]="10379cend$3";
char *stop;
printf("%d/n",strtol(buffer, &stop, 16));
printf("%s/n", stop);
輸出結果:
17005006
nd$3
另外,如果base為0,且字串不是以0x(或者0X)開頭,則按十進位進行轉化。如果base為0或者16,並且字串以0x(或者0X)開頭,那麼,x(

或者X)被忽略,字串按16進位轉化。如果base不等於0和16,並且字串以0x(或者0X)開頭,那麼x被視為非法字元。
例如:
-------------------------------------------------------
char buffer[20]="0x31da6c";
char *stop;
printf("%d/n",strtol(buffer, &stop, 0));
printf("%s/n", stop);
輸出結果(stop為空白):
3267180

-------------------------------------------------------
char buffer[20]="0x31da6c";
char *stop;
printf("%d/n",strtol(buffer, &stop, 13));
printf("%s/n", stop);
輸出結果:
0
0x31da6c
-------------------------------------------------------

最後,需要說明的是,對於nptr指向的字串,其開頭和結尾處的空格被忽視,字串中間的空格被視為非法字元。
例如:
-------------------------------------------------------
char buffer_1[20]="10379c";
char buffer_2[20]="      10379c        ";
char buffer_3[20]="      10      379c        ";
printf("%d/n",strtol(buffer_1,NULL,0));
printf("%d/n",strtol(buffer_2,NULL,0));
printf("%d/n",strtol(buffer_3,NULL,0));
輸出結果為:
10379
10379
10
-----------------------------------------------------------

----------------------------------------  分割線 ---------------------------------------------------

上面是轉載的內容

下面是自己的一些理解:

 

1.對於strtol的傳回值問題

 

RETURN VALUE
       The  strtol() function returns the result of the conversion, unless the value would
       underflow or overflow.  If an underflow occurs, strtol() returns LONG_MIN.   If  an
       overflow occurs, strtol() returns LONG_MAX.  In both cases, errno is set to ERANGE.
       Precisely the same holds for strtoll() (with LLONG_MIN  and  LLONG_MAX  instead  of
       LONG_MIN and LONG_MAX).

 

在man手冊中有這樣一段傳回值的介紹,這說明strtol這個函數的出錯只有兩種,第一是上溢,第二是下溢,兩種分別對應於不同的傳回值LONG_MAX和LONG_MIN。所以在用這個函數的時候一定要判斷轉出的數值不能溢出。

 

 

2.關於strtol中endptr的問題

 

錯誤的理解:

static int hex2bin(char *hex_num)<br />{<br /> char *tmp;<br /> char bin_arr[16] = {0};<br /> int bin, i;<br /> char *endptr = NULL;<br /> STF_debug_print("Hex number is %s/n", hex_num);<br /> /* tmp = hex_num + 2 -> cut off '0x'*/<br /> for(tmp = hex_num + 2, i = 0; *tmp != '/0'; tmp++, i+=4){<br /> switch(*tmp)<br /> {<br /> case '0':<br /> strcpy(&bin_arr[i], "0000");<br /> break;<br /> case '1':<br /> strcpy(&bin_arr[i], "0001");<br /> break;<br /> case '2':<br /> strcpy(&bin_arr[i], "0010");<br /> break;<br /> case '3':<br /> strcpy(&bin_arr[i], "0011");<br /> break;<br /> case '4':<br /> strcpy(&bin_arr[i], "0100");<br /> break;<br /> case '5':<br /> strcpy(&bin_arr[i], "0101");<br /> break;<br /> case '6':<br /> strcpy(&bin_arr[i], "0110");<br /> break;<br /> case '7':<br /> strcpy(&bin_arr[i], "0111");<br /> break;<br /> case '8':<br /> strcpy(&bin_arr[i], "1000");<br /> break;<br /> case '9':<br /> strcpy(&bin_arr[i], "1001");<br /> break;<br /> case 'a':<br /> case 'A':<br /> strcpy(&bin_arr[i], "1010");<br /> break;<br /> case 'b':<br /> case 'B':<br /> strcpy(&bin_arr[i], "1011");<br /> break;<br /> case 'c':<br /> case 'C':<br /> strcpy(&bin_arr[i], "1100");<br /> break;<br /> case 'd':<br /> case 'D':<br /> strcpy(&bin_arr[i], "1101");<br /> break;<br /> case 'e':<br /> case 'E':<br /> strcpy(&bin_arr[i], "1110");<br /> break;<br /> case 'f':<br /> case 'F':<br /> strcpy(&bin_arr[i], "1111");<br /> break;<br /> default:<br /> STF_debug_print("Error hex number/n");<br /> break;<br /> }<br /> }<br /> STF_debug_print("bin_arr is %s/n", bin_arr);<br /> bin = strtol(bin_arr, &endptr, 2);<br />#if 0<br /> if(endptr != NULL){<br /> STF_debug_print("strtol error, and endptr = %s/n", endptr == ' '? "space":endptr);<br /> return -1;<br /> }<br />#else<br /> if(*endptr != '/0'){<br /> STF_debug_print("strtol error, and endptr = %s/n", endptr == ' '? "space":endptr);<br /> }else{<br /> STF_debug_print("endptr = %s/n", endptr == NULL ? "null" :<br /> (endptr == '/0') ? "00000" : endptr);<br /> }<br />#endif<br /> return

上面是一段十六進位字串轉二進位字串的代碼,在函數結尾,我本來想用endptr來判斷strtol的轉換是否正確,當時的想法是:如果一個純以'0'或'1'字元構成的字串,那麼正確轉換後endptr應該是NULL。

 

實驗結果:

int main()<br />{<br /> char str1[16] = "adafadfd";<br /> char *endptr;<br /> int num;<br /> num = strtol(str1, &endptr, 16);<br /> if(num == LONG_MAX || num == LONG_MIN){<br /> printf("Num overflow!");<br /> printf(", and endptr is %s/n", *endptr == '/0' ? "0" : endptr);<br /> }else{<br /> printf("str is %s, and strtol is %d",str1, num);<br /> printf(", and endptr is %s/n", *endptr == '/0' ? "0" : endptr);<br /> }<br /> char str2[16] = "1111111";<br /> printf("str is %s, and strtol is %d",str2, strtol(str2, &endptr, 2));<br /> printf(", and endptr is %s/n", *endptr == '/0' ? "0" : endptr);<br /> char str3[16] = "aaaaasss";<br /> printf("str is %s, and strtol is %d",str3, strtol(str3, &endptr, 16));<br /> printf(", and endptr is %s/n", *endptr == '/0' ? "0" : endptr);<br /> return 0;<br />}

 

執行結果:

Num overflow!, and endptr is 0<br />str is 1111111, and strtol is 127, and endptr is 0<br />str is aaaaasss, and strtol is 699050, and endptr is sss  

 

經過上述代碼的一個測試,可以發現:

1. 當字串中的字元完全符合轉換所規定進位的格式要求時,*ptr = '/0',無論是否溢出(情況1和2)

2. 當字串中出現非法字元,那麼*ptr = 第一個非法字元。

3. LONG_MAX和LONG_MIN 常數在<limit.h>標頭檔中。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.