数字反转(洛谷P1553):利用STL的优雅实现

利用C++的STL优雅的完成此题。

查看题目

解题思路

这是一道新手入门的题目,但是有很多细节。

做法我们分情况讨论下:

  1. 对于整数,去除前后的0并直接反转

  2. 对于百分数,删去百分号后按照整数的套路即可

  3. 对于分数,找到/并以他为界分割成两个字符串,分别去除前后的0并反转,然后再合并

  4. 对于小数,同上,不过要将分隔符换成.

然后输出即可。

这样看起来,整个题目也并没有那么复杂了。

程序实现

根据上面的归纳,可以看出整个程序无非就几个步骤:

  • 去除前后的0

  • 判断字符串是属于分数,还是小数?又或者是百分数?

  • 将字符串倒置

  • 分割字符串

为了简单与优雅,我们可以直接调用STL的函数解决。

字符串类型的判断

判断字符串的类型,我们可以直接在字符串中查找符号来判断,如果既没有/,也没有.,也没有%,那肯定就是整数了。

在String类中间,内置了一个源String.find(待查找的字符串)的函数,若找到了则返回字符的位置,否则返回string::npos,我们直接拿来用就好。

字符串的倒置

同样的,在STL中内置了一个很好用的反转函数:reverse(起始迭代器,结束迭代器),我们同样可以直接拿来用。

迭代器怎么获取?直接待反转String.begin()和待反转String.end()即可。

分割字符串

在其他的语言中,字符串类型一般都内置了split这样的函数,可C++好像是一个特例。

那就自己实现吧。

在字符串类中,还有一个好用的函数:待分割String.substr(起始位置,取出的长度),可以直接取出给定起点和长度的子字符串。

首先利用find函数找到符号的位置,记录在变量pos中。

然后提取前半部分:起始位置当然是0,长度为pos,这样取到的就是 0~pos-1 的子字符串。

接着提取后半部分:起始位置是pos+1,长度为总长度-pos,这样取到的就是 pos+1~总长度 的子字符串。

去0?

这个就实在没有库函数可以利用了,STL也不可能提供这样“奇怪”的库函数。

当然,自己写一个也很简单。

弄个循环,如果第一位是0,那就删掉第一位,然后重新判断。

同理,从后往前找即可,一直删到最后一位不为0即可。

注意,这里有个小坑,如果“0000”这样的,那么就会返回空字符串。但显然至少需要保留一个0,那我们判断一下就好。

AC代码

#include <bits/stdc++.h>//万能头文件
using namespace std;
string zero(string o)//辅助函数,用于去除字符串前置的0与后置的0
{
while (o[o.length()-1]=='0')//去后0
o=o.substr(0,o.length()-1);
while (o[0]=='0')//去前0
o=o.substr(1,o.length()-1);
return o==""?"0":o;//一个fix,避免全是0就给了个空字符串
}
int main()
{
string o;
cin >> o;
if (o.find(".")!=string::npos)//小数
{
string a=o.substr(0,o.find(".")),b=o.substr(o.find(".")+1,o.length()-o.find("."));
a=zero(a);
b=zero(b);
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
cout << a << "." << b;
}
else if (o.find("\%")!=string::npos)//百分数
{
string a=o.substr(0,o.find("\%"));
a=zero(a);
reverse(a.begin(),a.end());
cout << a << "\%";
}
else if (o.find("/")!=string::npos)//分数
{
string a=o.substr(0,o.find("/")),b=o.substr(o.find("/")+1,o.length()-o.find("/"));
a=zero(a);
b=zero(b);
reverse(a.begin(),a.end());
reverse(b.begin(),b.end());
cout << a << "/" << b;
}
else//啥都找不到,自然是整数
{
o=zero(o);
reverse(o.begin(),o.end());
cout << o;
}
return 0;
}