如何将字符串转换为数字

rangf 2013-04-23 07:07:02
如下所示:
1,“123”——>123;
2,“123.555”——>123.555;

如何用一个函数同时实现上面的两种情况?
我知道atoi只能完成第1种情况,atof只能完成第2种情况,
...全文
4663 30 打赏 收藏 转发到动态 举报
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
Athenacle_ 2013-04-27
  • 打赏
  • 举报
回复
等我归来的时候此贴已结。。。 好吧好吧。。随便看看把

class Number :  public WXCC
	{
		virtual void calcHash(void);
	public:
		NS_LEX_CONSTANTS::TYPE		type;		/* T_INT_CON T_FLOAT_CON T_CHAR_CON */
		NS_LEX_CONSTANTS::NUMBER_TYPE	numberType;	/* enum NUMBER_TYPE */
		union
		{
			double d_value;
			int i_value;
		} val;
		Number(const Number& num)
			:type(num.type), numberType(num.numberType)
		{
			val.d_value = num.val.d_value; 
			calcHash();
		}
	};

Number* Lex::tryParseFloatNumber(char* numberBuffer, Number **dest)
{
	/* try to parse a floating number. first check the vaildity, then call the
	* C library call strod()
	*
	*	FLOATING-CONSTANT:
	*		FRACTIONAL-CONSTANT [ EXPONENT-PART ] [ FLOATING-SUFFIX ]
	*
	*	FRACTIONAL-CONSTANT:
	*		[ DIGIT-SEQUENCE ]. DIGIT-SEQUENCE
	*
	*	EXPONENT-PART:
	*		E [ SIGN ] DIGIT-SEQUENCE
	*		e [ SIGN ] DIGIT-SEQUENCE
	*
	*	DIGIT-SEQUENCE:
	*		DIGIT { DIGIT }
	*
	*	FLOATING-SUFFIX:
	*		one of F f L l
	*/
	int reachE = 0, reachP = 0, reachL = 0, reachF = 0;
	double result;
	char* tp = numberBuffer;
	(*dest)->type = T_FLOAT_CON;
	(*dest)->numberType = NT_DB;
	for (;*tp; tp++)
	{
		switch (*tp)
		{
		case '.':

			if (reachE != 0)
			{
				lexerError(LEX_ERROR_ILL_FLO_SUFFIX,tp);
				goto parseFloatError;
			}
			if (reachP != 0)
			{
				lexerError(LEX_ERROR_ILL_FLO_SUFFIX,tp);
				goto parseFloatError;
			}
			reachP++;
			break;
		case 'E':case'e':
			if (reachE != 0)
			{
				lexerError(LEX_ERROR_ILL_FLO_SUFFIX,tp);
				goto parseFloatError;
			}
			reachE++;
			break;
		case 'f':case 'F':
			reachF++;
			*tp = '\0';
			break;
		case 'l':case 'L':
			reachL++;
			*tp = '\0';
			break;
		case '1': case'2':case'3':case'4':case'5':case '6':case '7':case '8':
		case '9':case '0':case '+':case '-':
			break;
		default:
			lexerError(LEX_ERROR_ILL_FLO_SUFFIX, tp);
			(*dest)->numberType = NT_DB;
			goto parseFloatError;
		}
	}
	if (reachP > 1 || reachF > 1 || reachL > 1)
	{
		lexerError(LEX_ERROR_ILL_FLO_SUFFIX, tp);
		(*dest)->numberType = NT_DB;
		goto parseFloatError;
	}
	else
	{
		errno = 0;
		result = strtod((char *)tmpBuffer, NULL);
		if (errno == ERANGE)
		{
			lexerError(LEX_ERROR_FLOATING_OVERFLOW, tmpBuffer);
			goto parseFloatError;
		}
		else
		{
			if (reachF == 1)
				/* this is single precision value, check the range. */
			{
				if ((float)result> FLT_MAX +  FLT_EPSILON ||
					(float)result < (FLT_MAX * -1 ) - FLT_EPSILON)
				{
					lexerError(LEX_ERROR_FLOATING_OVERFLOW, tmpBuffer);
					goto parseFloatError;
				}
				(*dest)->numberType = NT_FL;
			}
			if (reachL == 1)
				(*dest)->numberType = NT_LD;
		}
	}

	(*dest)->val.d_value = result;
	return *dest;
parseFloatError:
	(*dest)->val.d_value = 1.0;
	return *dest;
}

Number* Lex::tryParseDecNumber(char* numberBuffer)
{
	char* tp = numberBuffer;
	int reachU = 0, reachL = 0;
	int result = 0;
	Number * ret;
	int times = 0;
	ret = (Number *)allocateMemory(sizeof(Number));
	ret->numberType = NT_SI;
	ret->type = T_INT_CON;
	while (*(tp))
	{
		switch (*tp)
		{
		case '1': case'2':case'3':case'4':case'5':case '6':case '7':case '8':
		case '9':case '0':
			result = (result * 10) + (*tp - '0');
			break;
		case 'u':case 'U':
			if (reachU == 0)	/* 0x123u */
			{
				ret->numberType |= NT_UNSIGNED_MASK;
				reachU = 1;
			}
			else
			{
				lexerError(LEX_ERROR_ILL_SUFFIX, tp);
			}
			break;
		case 'l':case 'L':
			if (reachL == 0)	/* 0x123l */
			{
				ret->numberType |= NT_LONG_MASK;
				reachU = 1;
			}
			else
			{
				lexerError(LEX_ERROR_ILL_SUFFIX, tp);
			}
			break;
		default:
			lexerError(LEX_ERROR_ILL_SUFFIX, tp);
			break;
		case '.':case 'e':case 'E':
			return tryParseFloatNumber(numberBuffer, &ret);
		}
		tp++;
		times++;
		if (times >= 8)
			/* an integer or long integer is 32bit, 8 hex numbers
			* UINT_MAX = 0xffffffff
			*/
		{
			lexerError(LEX_ERROR_ICON_TOO_BIG, tmpBuffer);
			goto parHexNumFinish;
		}
	}
parHexNumFinish:
	ret->val.i_value = result;
	return ret;
}

Number* Lex::tryParseHexNumber(char* numberBuffer)
{
	char* tp = numberBuffer;
	int reachU = 0, reachL = 0;
	int result = 0;
	Number * ret;
	int times = 0;
	ret = (Number *)allocateMemory(sizeof(Number));
	ret->numberType = NT_SI;
	ret->type = T_INT_CON;
	tp += 2 ;	/* ignore the '0x' or '0X' character */
	while (*(tp))
	{
		switch (*tp)
		{
		case '1': case'2':case'3':case'4':case'5':case '6':case '7':case '8':
		case '9':case '0':
			result = (result << 4) + (*tp - '0');
			break;
		case 'a':case 'A':
			result = (result << 4) + 10;
			break;
		case 'b':case 'B':
			result = (result << 4) + 11;
			break;
		case 'c':case 'C':
			result = (result << 4) + 12;
			break;
		case 'd':case 'D':
			result = (result << 4) + 13;
			break;
		case 'e':case 'E':
			result = (result << 4) + 14;
			break;
		case 'f':case 'F':
			result = (result << 4) + 15;
			break;
		case 'u':case 'U':
			if (reachU == 0)	/* 0x123u */
			{
				ret->numberType |= NT_UNSIGNED_MASK;
				reachU = 1;
			}
			else
			{
				lexerError(LEX_ERROR_ILL_SUFFIX, tp);
			}
			break;
		case 'l':case 'L':
			if (reachL == 0)	/* 0x123l */
			{
				ret->numberType |= NT_LONG_MASK;
				reachL = 1;
			}
			else
			{
				lexerError(LEX_ERROR_ILL_SUFFIX, tp);
			}
			break;
		case '\0':
			break;
		default:
			lexerError(LEX_ERROR_ILL_CHAR_IN_HEX, tp);
			goto parHexNumFinish;
		}
		tp++;
		if (times >= 8)
			/* an integer or long integer is 32bit, 8 hex numbers
			* UINT_MAX = 0xffffffff
			*/
		{
			lexerError(LEX_ERROR_ICON_TOO_BIG, tmpBuffer);
			goto parHexNumFinish;
		}
		times++;
	}
parHexNumFinish:
	ret->val.i_value = result;
	return ret;
}

Number* Lex::tryParseOctNumber(char* numberBuffer)
{
	char* tp = numberBuffer;
	int reachU = 0, reachL = 0;
	int result = 0;
	Number * ret;
	int times = 0;
	ret = (Number *)allocateMemory(sizeof(Number));
	ret->numberType = NT_SI;
	ret->type = T_INT_CON;
	while (*(tp))
	{
		switch (*tp)
		{
		case '1': case'2':case'3':case'4':case'5':case '6':case '7':case '8':
		case '0':
			result = (result << 3) + (*tp - '0');
			break;
		case 'u':case 'U':
			if (reachU == 0)	/* 0123u */
			{
				ret->numberType |= NT_UNSIGNED_MASK;
				reachU = 1;
			}
			else
			{
				lexerError(LEX_ERROR_ILL_SUFFIX, tp);
			}
			break;
		case 'l':case 'L':
			if (reachL == 0)	/* 0123l */
			{
				ret->numberType |= NT_LONG_MASK;
				reachU = 1;
			}
			else
			{
				lexerError(LEX_ERROR_ILL_SUFFIX, tp);
			}
			break;
		default:
			lexerError(LEX_ERROR_ILL_CHAR_IN_OCT, tp);
			goto parOctNumFinish;
			break;
		}
		tp++;
		times++;
		if (times >= 11)
			/* an integer or long integer is 32bit, 11 oct numbers
			* UINT_MAX = 037777777777
			*/
		{
			lexerError(LEX_ERROR_ICON_TOO_BIG, tmpBuffer);
			goto parOctNumFinish;
		}
	}
parOctNumFinish:
	ret->val.i_value = result;
	return ret;
}

int Lex::newNumber(char *numBuffer, int radix)
{
	Number *ret = NULL;
	switch (radix)
	{
	case 10:
		ret = tryParseDecNumber(numBuffer);
		break;
	case 16:
		ret = tryParseHexNumber(numBuffer);
		break;
	case 8:
		ret = tryParseOctNumber(numBuffer);
		break;
	default:
		assert(0);
	}
	//newTok = new Token(ret);
	currentToken->token_type = ret->type;
	currentToken->token_value.numVal = ret;
	switch (ret->type)
	{
	case T_FLOAT_CON:
		currentToken->token_value.numVal->val.d_value = ret->val.d_value;
		break;
	case T_INT_CON:
		currentToken->token_value.numVal->val.i_value = ret->val.i_value;
		break;
	default: assert(0);
	}

	return currentToken->token_type;
}

int Lex::number(char peek)
{
	getNextChar(BACK);
	getBufferUntilSp();//把下一个数字放入tmpBuffer数组
	switch (peek)
	{
	case '0':
		if (isdigit(tmpBuffer[1])) /* oct numbers */
		{
			return newNumber(tmpBuffer, 8);
		}
		else if (tmpBuffer[1] == 'x' || tmpBuffer[1] == 'X') /*hex numbers*/
			return newNumber(tmpBuffer, 16);
		else if (tmpBuffer[1] == '\0')		/* there is a 0 */
			return newNumber(tmpBuffer, 10);
	default:		/* dec numbers */
		return newNumber(tmpBuffer, 10);
	}
}

UnknowName 2013-04-26
  • 打赏
  • 举报
回复
引用 23 楼 rangf 的回复:
[quote=引用 22 楼 Athenacle_ 的回复:] 此贴开始人生攻击了。。 “123”的atof的结果应该是123的浮点数形式。 请问LZ, 你需要一个函数,统一处理字符串数字?那用什么类型的返回值呢? 用 struct { int flag, union { int i, double f, } }; 么? 否则你的问……
你问对了,大概就是要这么一个东东。 比如: 遇到一个“123”——>就会自动转换为int型的123 遇到一个“123.444”——>就会自动转换为float型的123.444 遇到一个“0xFFFFFFFF”——>就会自动转换为long int型的0xFFFFFFFF 但是不需要对应“abc”这种情况。[/quote] 不需要对应abc是什么意思? 难道是只有遇到”0xFFFFFFFF"才转化? 如果是0xffabcabc就不转换了对吗?
UnknowName 2013-04-26
  • 打赏
  • 举报
回复
引用 21 楼 vasilyben 的回复:
楼上你就把我排除在外了??? 不知道是我心态有问题,还是咋的。。。 楼主不懂也就罢了,虚心学习嘛倒也是,但我老觉得挑三拣四不结贴很让人烦。 还有那些不懂装懂的,比如楼上这位,混淆视听,自己啥也不懂扯张嘴乱糊弄,哎。。 可惜了CSDN这么好的平台,强烈要求增加版面巡视人员。
你的实现和2楼的思想是一样的。 所以没有在回复中提到。 我的思想是 : 授人以鱼不如授人以渔。 再者你的代码也不够规范,变量名都是没有看不出来含义的字母, 可读性比较差,也也是没有推荐的原因。 我也是一个在努力成长中的菜鸟,水平有限,有说错的地方还请包含。
赵4老师 2013-04-26
  • 打赏
  • 举报
回复
电脑内存只是一个一维二进制字节数组及其对应的二进制地址; 人脑才将电脑内存中的这个一维二进制字节数组及其对应的二进制地址的某些部分看成是整数、有符号数/无符号数、浮点数、复数、英文字母、阿拉伯数字、中文/韩文/法文……字符/字符串、函数、函数参数、堆、栈、数组、指针、数组指针、指针数组、数组的数组、指针的指针、二维数组、字符点阵、字符笔画的坐标、黑白二值图片、灰度图片、彩色图片、录音、视频、指纹信息、身份证信息……
rangf 2013-04-26
  • 打赏
  • 举报
回复
引用 21 楼 vasilyben 的回复:
楼上你就把我排除在外了??? 不知道是我心态有问题,还是咋的。。。 楼主不懂也就罢了,虚心学习嘛倒也是,但我老觉得挑三拣四不结贴很让人烦。 还有那些不懂装懂的,比如楼上这位,混淆视听,自己啥也不懂扯张嘴乱糊弄,哎。。 可惜了CSDN这么好的平台,强烈要求增加版面巡视人员。
我的需求没有说清楚,sorry。 我不需要这个函数。
rangf 2013-04-26
  • 打赏
  • 举报
回复
引用 20 楼 tomur 的回复:
其实字符串转换成数字,不过是ASCII码 --> 数字的转换。 如果楼主有兴趣,可以自己实现一个,也很简单。 2楼和17楼的方法也是推荐使用的。
我的需求没有说清楚,sorry。
rangf 2013-04-26
  • 打赏
  • 举报
回复
引用 22 楼 Athenacle_ 的回复:
此贴开始人生攻击了。。 “123”的atof的结果应该是123的浮点数形式。 请问LZ, 你需要一个函数,统一处理字符串数字?那用什么类型的返回值呢? 用 struct { int flag, union { int i, double f, } }; 么? 否则你的问……
你问对了,大概就是要这么一个东东。 比如: 遇到一个“123”——>就会自动转换为int型的123 遇到一个“123.444”——>就会自动转换为float型的123.444 遇到一个“0xFFFFFFFF”——>就会自动转换为long int型的0xFFFFFFFF 但是不需要对应“abc”这种情况。
Athenacle_ 2013-04-26
  • 打赏
  • 举报
回复
此贴开始人生攻击了。。 “123”的atof的结果应该是123的浮点数形式。 请问LZ, 你需要一个函数,统一处理字符串数字?那用什么类型的返回值呢? 用 struct { int flag, union { int i, double f, } }; 么? 否则你的问题就是无意义的
赵4老师 2013-04-26
  • 打赏
  • 举报
回复
都自动了,程序员就失业了!
vasilyben 2013-04-26
  • 打赏
  • 举报
回复
楼上你就把我排除在外了??? 不知道是我心态有问题,还是咋的。。。 楼主不懂也就罢了,虚心学习嘛倒也是,但我老觉得挑三拣四不结贴很让人烦。 还有那些不懂装懂的,比如楼上这位,混淆视听,自己啥也不懂扯张嘴乱糊弄,哎。。 可惜了CSDN这么好的平台,强烈要求增加版面巡视人员。
自信男孩 2013-04-24
  • 打赏
  • 举报
回复
引用 4 楼 lcmzgy 的回复:
用sprintf()和sscanf()不是更好吗
++这个方法也不错, 不过需要首先判断该字符串表示的是整数还是浮点数。
老王爱上猫 2013-04-24
  • 打赏
  • 举报
回复
int i = type_convert<int>("123"); double j = type_convert<double>("123.555");

template<class Out_Type, class In_Type>
Out_Type type_convert(const In_Type& T)
{
	stringstream ss;
	ss<<T;
	Out_Type result;
	ss>>result;
	return result;
}
  • 打赏
  • 举报
回复
果断sscanf
vasilyben 2013-04-24
  • 打赏
  • 举报
回复
main() { char *a="12345.111111"; double ad=0.0; int ai=0; int i; int j=0; for(i=0;i<strlen(a);i++) { if(a[i]=='.') { printf("%f\n",atof(a)); j++; break; } } if(j==0) { printf("%d\n",atoi(a)); } } char *a="你自己写个数" ,然后装进去,编译,运行,就可以看到结果。
UnknowName 2013-04-24
  • 打赏
  • 举报
回复
其实字符串转换成数字,不过是ASCII码 --> 数字的转换。 如果楼主有兴趣,可以自己实现一个,也很简单。 2楼和17楼的方法也是推荐使用的。
vasilyben 2013-04-24
  • 打赏
  • 举报
回复
楼主。。。。 你把这段代码复制运行了再说吧。。。。 main() { char *a="12345.111111"; double ad=0.0; int ai=0; int i; int j=0; for(i=0;i<strlen(a);i++) { if(a[i]=='.') { printf("%f\n",atof(a)); j++; break; } } if(j==0) { printf("%d\n",atoi(a)); } }
rangf 2013-04-24
  • 打赏
  • 举报
回复
引用 3 楼 HuiyuYang_fish 的回复:
1,“123”——>123;用atof后是什么?
不会是123的。
引用 15 楼 zhcosin 的回复:
人家要求的是从字符串转成数字,一看回帖一大半都说的是从数字转成字符串,哈哈,你们这帮人啊,眼睛让驴给踢啦。 两种情况都用 atof 难道会有什么问题吗?
有问题。如上面所示。
赵4老师 2013-04-24
  • 打赏
  • 举报
回复
char s1[]="123";
char s2[]="123.555";
double d1,d2;
sscanf(s1,"%lf",&d1);
sscanf(s2,"%lf",&d2);
printf("%lg\n%lg\n",d1,d2);
vasilyben 2013-04-24
  • 打赏
  • 举报
回复
楼上 搞清楚 atoi 和 atof 吧 或者你先搞清楚什么是自然数什么是实数再说吧 再或者搞清楚什么是整型什么是浮点型再来嘲笑我们吧。
C_linux记事 2013-04-24
  • 打赏
  • 举报
回复
先用if判断再用函数
加载更多回复(9)

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧