【C語言】類比實現atoi函數

來源:互聯網
上載者:User

標籤:pre   span   狀態   lag   字串轉換   ace   std   turn   類比   

  atoi(表示 ascii to integer)是把字串轉換成整型數的一個函數.

  atoi()函數會掃描參數 nptr字串,跳過前面的空白字元(例如空格,tab縮排等,可以通過isspace( )函數來檢測),直到遇上數字或正負符號才開始做轉換,而再遇到非數字或字串結束時(‘\0‘)才結束轉換,並將結果返回。如果 nptr不能轉換成 int 或者 nptr為空白字串,那麼將返回0

  我們在類比實現atoi函數時,要注意以下幾點:

  1.字串之前的空白問題  

  2.加號或減號

  3.字串為空白時

  4.被轉換的數字過於大(正溢出、負溢出)

  5.其他,無法轉換的情況(全是字母....之類的)

  我們瞭解atoi函數功能和一些注意事項之後,開始類比實現它,代碼如下:

#include<stdio.h>#include<assert.h>#include<stdlib.h>enum{vaild = 0,invaild = 1};int flag = vaild;int my_atoi(const char *str){long long ret = 0;int symbol = 1;//斷言str!=NULLassert(str);//判斷Null 字元if( ‘\0‘ == *str ){flag = invaild;return 0;}//去掉空格、定位字元while(isspace(*str)){str++;}//符號位判斷if(‘-‘==*str){symbol = -1;str++;}else if(‘+‘==*str){str++;}else if(((*str<=‘0‘)&&(*str>=‘9‘))){flag = invaild;return 0;}//其他異常情況處理完畢,開始轉換while((*str!=‘\0‘)&&(*str>=‘0‘)&&(*str<=‘9‘)){ret = (ret*10 + *str-‘0‘);str++;}//帶上符號位ret *= symbol;//檢測溢出//int 0111 1111 1111 1111 1111 1111 1111 1111 正溢出//     7    f    f    f    f    f    f    f//    1000 0000 0000 0000 0000 0000 0000 0000 負溢出//      8     0   0   0     0    0    0    0if(((ret>0x7fffffff)&&(1==symbol)) ||(ret<(signed int)0x80000000)&&(-1==symbol)){flag = invaild;return 0;}//ret合法flag = vaild;return ret;}//列印atoi函數狀態+\nvoid PrintState(){if(flag){printf("異常\n");}else{printf("正常\n");}}//測試函數void FunTest(){printf("value=%d,state=",my_atoi("123456789"));PrintState();//正常printf("value=%d,state=",my_atoi("-123456789"));PrintState();//正常printf("value=%d,state=",my_atoi("-123456789sassa"));PrintState();//正常,遇到字母終止printf("value=%d,state=",my_atoi("  -123456789sassa"));PrintState();//正常,前面帶空格printf("value=%d,state=",my_atoi(""));//////////////異常情況/////////printf("\n\n");PrintState();//異常:Null 字元串printf("value=%d,state=",my_atoi("123456789123456789"),flag);PrintState();//異常:正溢出printf("value=%d,state=",my_atoi("-123456789123456789"),flag);PrintState();//異常:負溢出printf("value=%d,state=",my_atoi("dasdsa"),flag);PrintState();//異常:無法轉換}int main(){FunTest();return 0;}

  彩蛋:在寫測試函數時,有一件事,始終不得其解,一開始我將測試代碼寫成了這樣:

void FunTest(){printf("value=%d,state=%d\n",my_atoi("123456789"),flag);//正常printf("value=%d,state=%d\n",my_atoi("-123456789"),flag);//正常printf("value=%d,state=%d\n",my_atoi("-123456789sassa"),flag);//正常,遇到字母終止printf("value=%d,state=%d\n",my_atoi("  -123456789sassa"),flag);//正常,前面帶空格printf("\n\n\n");printf("value=%d,state=%d\n",my_atoi(""),flag);//異常:Null 字元串printf("value=%d,state=%d\n",my_atoi("123456789123456789"),flag);//異常:正溢出printf("value=%d,state=%d\n",my_atoi("-123456789123456789"),flag);//異常:負溢出printf("value=%d,state=%d\n",my_atoi("dasdsa"),flag);//異常:無法轉換}

  測試時,發現一件詭異的事情!!!!!!!

  結果輸出是這樣:

value=123456789,state=0value=-123456789,state=0value=-123456789,state=0value=-123456789,state=0value=0,state=0    //臥槽!!!為什麼是0?value=0,state=1value=0,state=1value=0,state=1

  我還特意跟進函數體內看,發現全域變數flag確實被改為了1,但為什麼輸出的是0呢???

  正當我百思不得其解時,突然想到printf函數的呼叫慣例是_cdel!!!!

  因此,_cdel呼叫慣例,是將參數由右向左壓棧,因此它先將flag壓棧,然後再執行my_atoi函數,在my_atoi函數體內修改了全域變數flag.....

  所以,最終輸出了0!

  因此,才有了最終代碼!

  

【C語言】類比實現atoi函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.