题解:洛谷 P1553 数字反转(升级版)
【题目来源】
【题目描述】
给定一个数,请将该数各个位上数字反转得到一个新数。
这次与 NOIP2011 普及组第一题不同的是:这个数可以是小数,分数,百分数,整数。
- 整数反转是将所有数位对调。
- 小数反转是把整数部分的数反转,再将小数部分的数反转,不交换整数部分与小数部分。
- 分数反转是把分母的数反转,再把分子的数反转,不交换分子与分母。
- 百分数的分子一定是整数,百分数只改变数字部分。
【输入】
一个实数 \(s\)
【输出】
一个实数,即 \(s\) 的反转数
【输入样例】
700/27
【输出样例】
7/72
【算法标签】
《洛谷 P1553 数字反转(升级版)》 #模拟# #字符串# #洛谷原创#
【代码详解】
#include <bits/stdc++.h> // 包含标准库头文件(万能头文件)
using namespace std; // 使用标准命名空间
/**
* 翻转整数部分
* @param s 要翻转的数字字符串
*/
void f0(string s)
{
int len = s.length(); // 获取字符串长度
int mark; // 标记第一个非零字符的位置
// 从后往前找到第一个非零字符
for (mark = len - 1; mark >= 0; mark--)
{
if (s[mark] != '0')
break;
}
// 如果全是零,输出0并返回
if (mark < 0)
{
cout << 0;
return;
}
// 从第一个非零字符开始倒序输出
for (int i = mark; i >= 0; i--)
{
cout << s[i];
}
}
/**
* 翻转小数部分
* @param s 要翻转的小数字符串
*/
void f1(string s)
{
int m = s.find("."); // 找到小数点位置
int len = s.length(); // 获取字符串长度
string s1 = s.substr(0, m); // 提取整数部分
string s2 = s.substr(m + 1, len - m - 1); // 提取小数部分
f0(s1); // 翻转整数部分
cout << '.'; // 输出小数点
// 处理小数部分前导零
int mark = 0;
for (mark = 0; mark < s2.length(); mark++)
{
if (s2[mark] != '0')
break;
}
// 如果小数部分全是零,输出0并返回
if (mark >= s2.length())
{
cout << 0;
return;
}
// 翻转小数部分(去掉末尾的零)
for (int i = s2.length() - 1; i >= mark; i--)
{
cout << s2[i];
}
}
/**
* 翻转分数部分
* @param s 要翻转的分数字符串
*/
void f2(string s)
{
int m = s.find("/"); // 找到分数线位置
int len = s.length(); // 获取字符串长度
string s1 = s.substr(0, m); // 提取分子部分
string s2 = s.substr(m + 1, len - m - 1); // 提取分母部分
f0(s1); // 翻转分子部分
cout << '/'; // 输出分数线
f0(s2); // 翻转分母部分
}
/**
* 翻转百分数部分
* @param s 要翻转的百分数字符串
*/
void f3(string s)
{
int m = s.find("%"); // 找到百分号位置
int len = s.length(); // 获取字符串长度
string s1 = s.substr(0, m); // 提取数字部分
f0(s1); // 翻转数字部分
cout << '%'; // 输出百分号
}
int main()
{
string s; // 定义字符串:存储输入的数字
cin >> s; // 输入数字字符串
// 根据数字类型调用对应的处理函数
if (s.find("/") != -1) // 如果是分数
{
f2(s);
}
else if (s.find("%") != -1) // 如果是百分数
{
f3(s);
}
else if (s.find(".") != -1) // 如果是小数
{
f1(s);
}
else // 如果是整数
{
f0(s);
}
return 0; // 程序正常结束
}
【运行结果】
700/27
7/72
浙公网安备 33010602011771号