不使用庫函數將字符串轉爲double類型(考慮科學計數法表示的字符串)

本題來源於騰訊2014年暑期實習生招聘附加題1,實現的代碼如下。

//字符串轉double,考慮科學計數法表示
bool ParseNumber(const char* s,double* d)
{
	bool bNegtiveBase,bNegtiveExp;//分別表示基數和指數是否爲負
	int nPreZero = 0;//基數前綴0的個數
	const char* p;
	int sum_i = 0;
	double sum_f = 0.0;
	int sum_exp = 0;
	double sum = 0.0;
	bNegtiveBase = bNegtiveExp = false;
	if(!s)
		return false;
	if('-' == *s)
	{
		bNegtiveBase = true;
		s++;
	}
	for(;'0' == *s;nPreZero++,s++);//統計基數前綴0的個數
	for(;*s != '.' && *s != 'e' && *s != 'E' && *s != '\0';s++)
	{
		if(*s < '0' || *s > '9')
		{
			return false;
		}
		sum_i = sum_i*10 + *s - '0';
	}
	if(0 == sum_i && 0 == nPreZero)//基數爲0且前綴0個數爲0,說明是.25、e7、E7、“”之類的數據格式
		return false;
	if('.' == *s)//還需要計算小數部分數值
	{
		for(p = s;*p != 'e' && *p != 'E' && *p != '\0';p++);//找到尾數部分的末尾
		if(s==p-1)
			return false;
		s = p;
		p--;
		for(;*p != '.';p--)
		{
			if(*p < '0' || *p > '9')
				return false;
			sum_f = sum_f*0.1 + 0.1*(*p - '0');
		}
	}
	if('e' == *s || 'E' == *s)//還需要計算階碼
	{
		s++;
		if('-' == *s)
		{
			bNegtiveExp = true;
			s++;
		}
		else if('+' == *s)
		{
			bNegtiveExp = false;
			s++;
		}
		nPreZero = 0;
		for(;*s != '\0';s++)
		{
			if(*s < '0' || *s > '9')
			{
				return false;
			}
			sum_exp = sum_exp*10 + *s - '0';
			nPreZero++;
		}
		if(0 == sum_exp && 0 == nPreZero)
			return false;
	}
	sum = sum_i + sum_f;
	if(bNegtiveExp)//階碼爲負
	{
		while(sum_exp > 0)
		{
			sum /= 10;
			sum_exp--;
		}
	}
	else
	{
		while(sum_exp > 0)
		{
			sum *= 10;
			sum_exp--;
		}
	}
	if(bNegtiveBase)//基數爲負
		sum = -sum;
	*d = sum;
	return true;
}

//測試函數
#include <iostream>
using namespace std;
int main()
{
	double d = 0.0;
	char* s[] = {"123562.578e56",
		"-1254.0256e+23",
		"-1254.0256e-23",
		"1458921",
		"14875.236",
		"1423e-089",
		"01546.3e-9",
		"0000.000",
		"000.000e000",
		"00.01e+0",
		".32",
		"0.",
		"0.e-7",
		"0.2e",
		"0.2e-6g",
		"2a5.3e-6",
		"2a5.3f6",
		NULL};
	for(int i=0;i<18;i++)
	{
		if(!ParseNumber(s[i],&d))
		{
			if(!s[i])
				cout<<"指針爲NULL"<<endl;
			else
				cout<<s[i]<<"非法"<<endl;
		}
		else
		{
			cout<<"\""<<s[i]<<"\""<<"="<<d<<endl;
		}
	}
	return 0;
}

測試結果:


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