题目
分析
如果熟悉C++中字符串(string)的各个操作函数,这道题目可以很直观地解决。
我们先看各种输入类型都可能会用到的去前导0和后导0(仅小数部分)的处理。
去前导0
如果一个数字反转后变成000123,我们只要输出123即可。这里的洞见是:找到第一个不是0的位置。string有一个成员函数可以处理这个任务:
string removeLeadingZeros(string s)
{
int pos = s.find_first_not_of("0");
if (pos == string::npos)
{
return "0";
}
return s.substr(pos);
}
我们用find_first_not_of找到第一个不是0的位置,然后取得从这个位置开始余下的所有字符。同时,我们考虑了极端情况:如果一串字符都是0怎么办?这时,按照题意应该是简单地返回"0"。
去后导0
根据题意,去后导0只会在小数部分出现。比如(.)1230,我们只要输出(.)123即可。这里的洞见是:找到最后一个不是0的位置。string有一个成员函数可以处理:
string removeTrailingZeros(string s)
{
int pos = s.find_last_not_of("0");
if (pos == string::npos)
{
return "0";
}
return s.substr(0, pos + 1);
}
我们用find_last_not_of找到最后一个不是0的位置,然后得到这个位置之前的所有字符。同时,也要考虑极端情况。
注意,这里涉及了string.substr(start, end)的用法,需要说明。start/end确定了子字符串的起始位置,但它是个左闭右开(\([start, end)\))的区间。在后续的输入处理中,我们还会用到substr。
根据输入进行处理
根据题意,输入的“数字”(字符串)有四种类型:整数、小数、分数、百分数。针对这四种输入格式,需要不同的处理方式。
小数处理
基本流程是:
字符串反转我们可以用reverse(s.begin(), s.end())完成。代码为:
if (s.find(".") != string::npos)
{
int pos = s.find(".");
string whole = s.substr(0, pos);
string decimal = s.substr(pos + 1, s.size());
reverse(whole.begin(), whole.end());
reverse(decimal.begin(), decimal.end());
whole = removeLeadingZeros(whole);
decimal = removeTrailingZeros(decimal);
cout << whole << "." << decimal << endl;
}
分数和百分数处理
与“小数处理类似”,但只需要去前导0。
整数处理
整数处理只需要反转和去前导0即可。
答案

思考
string类中有很多有用的方法,值得花点时间去研究一下。
