添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接


字符串转换成数字

常见的有三种方法:

1、利用C语言的函数atoi、atof等;

2、利用C++的流,std::stringstream;

3、利用std::stoi、std::stod等函数。

各有优劣,下面逐一分析。

为了方便,将std::stringstream的方法封装成一个模板函数,如下:

template<typename out_type, typename in_value>
out_type convert(const in_value & t){
	std::stringstream stream;
	stream << t;
	out_type result;
	stream >> result;
	return result;
}

测试代码如下:

int _tmain(int argc, _TCHAR* argv[])
	auto funPrint = [](const std::string& str){
		std::cout << "-------------------------------------------" << std::endl;
		std::cout << "原始字符串:" << str << std::endl;
		std::cout << "aotf:" << atof(str.c_str()) << std::endl;
		std::cout << "convert:" << convert<double>(str) << std::endl;
		std::cout << "std::stod:" << std::stod(str) << std::endl;
	std::string strValue("12.4ds52");
	funPrint(strValue);
	system("pause");
	return 0;
}

这里为了后面的测试,将打印功能封装成了一个lambda表达式,执行结果如下:

Android studio 把一个页面的所有字符串变成另一种 android studio字符串转数字_string

三种方法,似乎没有区别,都是遇到第一个非合法字符就停止转换。继续,将主函数修改如下:

int _tmain(int argc, _TCHAR* argv[])
	auto funPrint = [](const std::string& str){
		std::cout << "-------------------------------------------" << std::endl;
		std::cout << "原始字符串:" << str << std::endl;
		std::cout << "aotf:" << atof(str.c_str()) << std::endl;
		std::cout << "convert:" << convert<double>(str) << std::endl;
		std::cout << "std::stod:" << std::stod(str) << std::endl;
	std::string strValue("12.4ds52");
	funPrint(strValue);
	strValue = ("a23.4ds52");
	funPrint(strValue);
	system("pause");
	return 0;
}

与上面相比,多了一次给strValue重新赋值, 新的值第一个字符就是非数字 ,执行结果如下:

Android studio 把一个页面的所有字符串变成另一种 android studio字符串转数字_封装_02

很不幸,程序崩溃!!!

从执行结果可以看出来,崩溃的乃是std::stod(str)这一句;另外,利用std::stringstream转换得到的数字为一个未初始化的双精度浮点数;似乎只有atof执行得比较靠谱。

std::stod系列函数(std::stoi、std::stof等),是可以避免让其崩溃的。当给定的字符串完全不能转换成数字,就会抛出一个 std::invalid_argument 的异常。据此,不但能避免崩溃,一定程度上还能判断字符串的合法性。修改代码如下:

int _tmain(int argc, _TCHAR* argv[])
	auto funPrint = [](const std::string& str){
		std::cout << "-------------------------------------------" << std::endl;
		std::cout << "原始字符串:" << str << std::endl;
		std::cout << "aotf:" << atof(str.c_str()) << std::endl;
		std::cout << "convert:" << convert<double>(str) << std::endl;
			std::cout << "std::stod:" << std::stod(str) << std::endl;
		catch (std::invalid_argument&)
			std::cout << "非法字符串!" << std::endl;
	std::string strValue("12.4ds52");
	funPrint(strValue);
	strValue = ("a23.4ds52");
	funPrint(strValue);
	strValue = ("-.23.124.512");
	funPrint(strValue);
	strValue = ("--1.124");
	funPrint(strValue);
	system("pause");
	return 0;
}

执行结果如下:

Android studio 把一个页面的所有字符串变成另一种 android studio字符串转数字_字符串_03

可以看到,四个字符串严格来说,都是非法的,但是只有第二个和第四个抛出了异常。

所以在实际项目中,需要根据具体情况,进行一些异常处理和判断,再选择合适的方式进行转换。

数字转换成字符串

与字符串转成数字差不多,也有三种方式:

1、sprintf_s函数(需要加上头文件 #include "stdio.h");

2、利用std::stringstream流;

3、std::to_string函数(宽字符可用std::to_wstring);

利用std::stringstream流,就是上面封装的convert函数。

sprintf_s函数为sprintf函数的安全版本,需要指定缓冲区大小。

示例代码如下:

int _tmain(int argc, _TCHAR* argv[])
    auto funPrint_dTos = [](double dValue){
        std::cout << "-------------------------------------------" << std::endl;
        std::cout << "原始数字:" << dValue << std::endl;
        char arr[216];
        sprintf_s(arr, 216, "%f", dValue);
        std::cout << "sprintf_s:" << arr << std::endl;
        std::cout << "convert:" << convert<std::string>(dValue) << std::endl;
        std::cout << "std::to_string:" << std::to_string(dValue) << std::endl;
    funPrint_dTos(12.563);
    system("pause");
    return 0;
}

执行结果如下:

Android studio 把一个页面的所有字符串变成另一种 android studio字符串转数字_数字转换_04

可以看到,sprintf_s和std::to_string都会保留精度,不够的会在小数末尾加上0。当然,sprintf_s可以指定保留的小数位数,将上述代码中的 sprintf_s(arr, 216, "%f", dValue)改为sprintf_s(arr, 216, " %.2f ", dValue),执行结果如下:

Android studio 把一个页面的所有字符串变成另一种 android studio字符串转数字_string_05

至于std::to_string,似乎没有指定保留小数位数的办法,只能根据需求自己封装一个函数。

std::stringstream可以自动精确,去除末尾的0。

同样,也需要根据需求选择转换方式。