Bootstrap

洛谷 P1553 数字反转(升级版) C语言 stl

题目:

https://www.luogu.com.cn/problem/P1553

题目背景

以下为原题面,仅供参考:

给定一个数,请将该数各个位上数字反转得到一个新数。

这次与 NOIp2011 普及组第一题不同的是:这个数可以是小数,分数,百分数,整数。整数反转是将所有数位对调;小数反转是把整数部分的数反转,再将小数部分的数反转,不交换整数部分与小数部分;分数反转是把分母的数反转,再把分子的数反转,不交换分子与分母;百分数的分子一定是整数,百分数只改变数字部分。整数新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零;小数新数的末尾不为 0(除非小数部分除了 0 没有别的数,那么只保留1个 0);分数不约分,分子和分母都不是小数(约分滴童鞋抱歉了,不能过哦。输入数据保证分母不为 0),本次没有负数。

题目描述

给定一个数,请将该数各个位上数字反转得到一个新数。

这次与 NOIp2011 普及组第一题不同的是:这个数可以是小数,分数,百分数,整数。

  • 整数反转是将所有数位对调。

  • 小数反转是把整数部分的数反转,再将小数部分的数反转,不交换整数部分与小数部分。

  • 分数反转是把分母的数反转,再把分子的数反转,不交换分子与分母。

  • 百分数的分子一定是整数,百分数只改变数字部分。

输入格式

一个实数 s

输出格式

一个实数,即 s 的反转数

思路:先判断是否有符号,有符号就分成两个子串分别处理,无符号就单独处理。写好前置0和后置0的函数,左子串都是要清除前置0,注意%和/的右子串 前置0 和 后置0 都要去除。'.'右子串只需要清除后置0。

#include<iostream> 
#include<string>
#include<algorithm>
using namespace std;
string front(string S)//去除前置0 
{
    int pos = 0; //从左往右记录第一个非'0'的下标 
    for (int i = 0; i < S.size(); i++)
    {
        if (S[i] != '0')
        {
            pos = i; 
            break;
        }
    }
    
    if (pos > 0)  //不是只有一个'0' 
    {
        S.erase(0, pos); // 删除前置0 
    }
    //如果只有一个0就不会运行删除erase函数,直接返回'0' 
    return S;
}

string rear(string S)
{
    int pos = S.size() - 1; // 记录从右往左第一个非'0'字符 
    while (pos >= 0 && S[pos] == '0') 
    {
        pos--;
    }

    if (pos != -1) // 不是只有一个'0' 
    {
        S.erase(pos + 1, S.size() - 1 - pos); // 删除 
    }
    //如果只有一个0就不会运行删除erase函数,直接返回'0' 
    return S;
}
int main(void)
{
    bool found = false;
    string s;
    string sl; // 左子串 
    string sr; // 右子串 
    getline(cin, s);

    int p; 
    char ch;  
    for (int i = 0; i < s.size(); i++)//寻找符号下标 
    {
        if (s[i] == '%' || s[i] == '.' || s[i] == '/')
        {
            found = true;
            p = i;//储存下标位置 
            ch = s[i];//储存字符 
            break;
        }
    }

    if(found)//有符号 
    {
        sl = s.substr(0, p); // 左子串 
        sr = s.substr(p + 1, s.size() - (p + 1)); // 右子串 

        reverse(sl.begin(), sl.end()); // 转置左子串 
        reverse(sr.begin(), sr.end()); // 转置右子串 
        
        if(ch == '%' || ch == '/')// % 和 / 的右子串需要去除前置0和后置0 ,左子串都是去除前置0 
        {
            sl = front(sl);
			 
            sr = front(sr);
            sr = rear(sr);
            cout << sl << ch << sr << endl;
        }
        else if(ch == '.')// . 的右子串只要取出后置0 ,左子串都是去除前置0  
        {
            sl = front(sl);
            sr = rear(sr);
            cout << sl << ch << sr << endl;
        }
    }
    else//无符号 
    {
        reverse(s.begin(),s.end());
        s = front(s);//只要去前置0 
        cout << s << endl;
    }



    return 0;
}

两个for的代码:
 

#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
string s,sl,sr;
char sign;
bool found;
int pos;
string front(string s)
{
	int posf = 0;
	for(int i = 0 ; i < s.size() ; i++)
	{
		if(s[i] != '0')
		{
			posf = i;
			break;
		}
	}
	if(posf > 0)
	{
		s.erase(0,posf);
	}
	return s;
}
string rear(string s)
{
	int posr = 0;
	for(int i = s.size() - 1 ; i >= 0 ; i--)
	{
		if(s[i] != '0')
		{
			posr = i;
			break;
		}
	}
	if(posr > 0)
	{
		s.erase(posr+1,s.size() - 1 - posr);
	}
	return s;
}
int main(void)
{
	getline(cin,s);
	for(int i = 0 ; i < s.size() ; i++)
	{
		if(s[i] == '.' || s[i] == '%' || s[i] == '/')
		{
			found = true;
			sign = s[i];
			pos = i;
			break;	
		}
	 } 
	 
	 if(found)
	 {
	 	sl = s.substr(0,pos);
	 	sr = s.substr(pos + 1,s.size() - 1 - pos);
	 	
	 	reverse(sl.begin(),sl.end());
	 	reverse(sr.begin(),sr.end());
	 	
	 	if(sign == '%' || sign == '/')
	 	{
	 		sl = front(sl);
			sr = front(sr);
			sr = rear(sr);	
			cout << sl << sign << sr << endl;
		}
		else if(sign == '.')
		{
		 	sl = front(sl);
		 	sr = rear(sr);
		 	cout << sl << sign << sr << endl;
		}
	 }
	 else
	 {
	 	reverse(s.begin(),s.end());
	 	s = front(s);
	 	cout << s << endl;
	 }
	return 0;
 } 

;