【亂七八糟】atoi、itoa、遞歸

atoi是C標準庫提供的一個接口,函數原型大致爲:

int atoi(const char* pch);
不考慮太多異常情況,可以這樣實現:

int atoi(const char* pch)
	{
		if (NULL == pch)
		{
			return 0;
		}

		int iSymbol = 1;
		if (*pch == '-')
		{
			iSymbol = -1;
			++pch;
		}

		int num = 0;

		//遍歷字符串
		while (*pch != '\0')
		{
			if (*pch>= '0' && *pch<='9')
			{
				num = 10*num + *pch++ - '0';
			}
			else
			{
				break;
			}
			
		}

		return num;
	}

我們知道,數字 + 字符0,可以得到其對應的字符,比如

1 + '0'  == '1'   對應可以得出 '1' - '0' == 0


C標準庫未提供itoa這個接口,但很多編譯器都有提供(比如vs就在stdlib.h中聲明瞭),應用也比較廣泛,一般聲明爲:

char* itoa(int _Val, char * _DstBuf,int _Radix);


不考慮太多異常情況,大致可以這樣實現:

char* itoa(int _Val, char * _DstBuf,int _Radix)
	{
		//只支持2、8、10、16進制
		if(_Radix != 10 && _Radix != 16 && _Radix != 8 && _Radix != 2)
		{
			_DstBuf = '\0';
			return _DstBuf;
		}


		//每個進制每位對應的字符
		char index[]="0123456789ABCDEF";
		
		int i=0;
		int j = 0;
		int k = 0;
		unsigned unum = 0;;			  

		//10進制負數
		if(_Radix==10 && _Val<0) 
		{
			k=1; 
			unum=(unsigned)-_Val;
			_DstBuf[i++]='-';
		}
		else
		{
			unum=(unsigned)_Val;
		}
		
		do	
		{
			_DstBuf[i++] = index[unum%(unsigned)_Radix];
			unum/=_Radix;
		}
		while(unum);


		_DstBuf[i]='\0';
		
		
		//反轉字符串
		char temp;
		for(j=k;j<=(i-k-1)/2;j++)
		{
			temp=_DstBuf[j];
			_DstBuf[j] = _DstBuf[i-1+k-j];
			_DstBuf[i-j-1]=temp;
		}

		return _DstBuf;
	}


這裏主要使用了/、%,還有數字/字符轉換,以及字符串反轉,以下大致解釋下:

比如我調用的時候傳參:

sr::itoa(98521,arr,16);
puts(arr);

意爲將98521轉換爲16進制

在接口中,使用了index[]定義16進制每位的表現字符,使用下標可以一一對應


按照除16 + 模16,可以得到下面這個表

98521 %16   9  
6157   %16  13  
384     %16   0
24       %16   8
1         %16   1


最後一列再對應到index數組中的所有,可以得到9D081,反轉後可得到1809D


--------------------------------------------------------華麗麗的分割線---------------------------------------------

其實按照上面那個表,可以獲知,itoa其實也可以通過遞歸實現,而且由於遞歸使用了棧來存儲中間過程設計的變量,遵循後進先出的規則,所以也不需要反轉字符串

下面也大致實現下,爲了方便起見,使用string來存儲:

void itoa(string &str,int in_iNum,int n)
	{
		//不支持負數
		if (in_iNum < 0)
		{
			in_iNum = -1 *in_iNum;
		}

		int tmp_iVal = in_iNum/n;

		if (tmp_iVal != 0)
		{
			itoa(str,tmp_iVal,n);
		}	

		char index[]="0123456789ABCDEF";

		str.append(1,*(index + in_iNum%n));

	}

遞歸很重要的一點是何時結束調用,這裏當tmp_iVal不爲0時,遞歸調用自己,意思也就是,當tmp_iVal爲0時,結束調用

ps:這裏使用string的一個原因是如果使用char[],還需要關注下標,有個問題是如果再接口中定義變量用作下標變量,實際每次調用,都會是同樣的值

所以這裏不考慮性能問題,直接傳入string,代碼也會稍微整潔易懂些




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章