PAT A1060字符串处理

时间:2023-01-07 11:31:48

处理字符串的实用函数

字符串处理是PAT基础题中较难的一种,一般不涉及数据结构的知识,基础但并不容易AC,有很多边界情况要考虑。 使用字符数组的方法处理字符串非常麻烦和琐碎,使用string的函数以及STL一些与字符串有关的函数可以使问题更清晰简单
string相关函数

string str = "hello world~";

//#1 str.substr返回子串的拷贝
string s1 = str.substr(6,6);
//world~

//#2 str.append在strwei尾追加字符串,返回str的拷贝
auto s = str.append(" hello");
//hello world~ hello

//#3 str.replace用一个字符串替换str中的部分,返回str的拷贝
auto s = str.replace(6,6,"Cpp");
//hello cpp hello

//#4 string搜索
//#均有逆向搜索的版本
str.find("hello");      //返回"hello"第一次出现的地方
str.find('o');          //返回'o'第一次出现的地方
str.find_first_of("abcd");//返回"abcd"中任一字符第一次出现的地方
str.find_first_not_of("hello ");//返回任一不属于"hello "中的字符首次出现的地方
//如果没有找到,均返回string::npos

//#5 数值转换
string s = to_string(val);
//数值类型转换为string,val是数值类型

//string转换为数值类型,格式一定要正确,否则可能触发异常
stoi
stof
stod

1060. Are They Equal (25)

If a machine can save only 3 significant digits, the float numbers 12300 and 12358.9 are considered equal since they are both saved as 0.123*105 with simple chopping. Now given the number of significant digits on a machine and two float numbers, you are supposed to tell if they are treated equal in that machine.

Input Specification:

Each input file contains one test case which gives three numbers N, A and B, where N (<100) is the number of significant digits, and A and B are the two float numbers to be compared. Each float number is non-negative, no greater than 10100, and that its total digit number is less than 100.

Output Specification:

For each test case, print in a line “YES” if the two numbers are treated equal, and then the number in the standard form “0.d1…dN*10^k” (d1>0 unless the number is 0); or “NO” if they are not treated equal, and then the two numbers in their standard form. All the terms must be separated by a space, with no extra space at the end of a line.

Note: Simple chopping is assumed without rounding.

Sample Input 1:
3 12300 12358.9

Sample Output 1:
YES 0.123*10^5

Sample Input 2:
3 120 128

Sample Output 2:
NO 0.120*10^3 0.128*10^3


题意

给出一个正整数N,两个浮点数,将浮点数转化为标准的科学计数式: 0.d1…dN*10^k,保留N位有效数字,然后比较这两个数转化后的格式是否相等

  1. 浮点数用字符串保存
    给出的浮点数很大,最多100位,超过所有数值型能表示的范围

思路

  1. 0.d1…dN *10^k
    目的是获取k和有效数字d1…dN

  2. 第一位有效数字和小数点的位置至关重要

    • 小数点的位置 - 第一位有效数字的位置 = k
    • 第一位有效数字向后N位就是有效数字d1…dN
    • 如果没有第一位有效数字,则这个数是0

完整代码

#include <iostream>
#include <string>
#include <algorithm>

using namespace std;

//*10^k 计算k
int getk(const string& s)
{
    //也可以用s.find('.'),寻找'.'的位置,如果没有,令它为s.size()

    int pos_dot = s.find_first_of(".") == string::npos ? s.size() : s.find_first_of(".");
    //找到第一位有效数字(第一位非 0或. 的字符)
    int pos_first_sig = s.find_first_not_of("0.");
    //如果没有第一位有效数字,这个数是0
    if (pos_first_sig == string::npos)
    {
        return 0;
    }
    else
    {
        int res = pos_dot - pos_first_sig;

        //[1]为什么负数就要+1?

        return res > 0 ? res : res + 1;
    }
}

//0.d1...dN 获取格式化d1...dN
string getstd(const string& s, int N)
{

    int pos_first_sig = s.find_first_not_of("0.");
    string temp;
    int i = pos_first_sig;
    while (N && i < s.size())
    {
        //获取N位有效数字时,跳过 .
        if (s[i] != '.')
        {
            temp.push_back(s[i]);
            --N;
        }
        ++i;
    }
    //原字符串有效数字长度不足N位,用0补位
    while (N)
    {
        temp.push_back('0');
        --N;
    }
    return temp;
}

string getres(const string& s, int N)
{
    return "0." + getstd(s, N) + "*10^" + to_string(getk(s));
}
int main()
{

    int N;
    string s1, s2;
    cin >> N >> s1 >> s2;
    if (N == 0)
        while (1);
    if (getres(s1, N) == getres(s2, N))
    {
        cout << "YES " << getres(s1, N);
    }
    else
    {
        cout << "NO " << getres(s1, N) << " " << getres(s2, N);
    }

    system("pause");
    return 0;
}

[1]为什么负数要+1

如 123.348 是 0.123*10^3k=3
pos_dot - pos_first_sig = 3 -0 =3 符合

如 0.01234 是 0.123*10^-1k=-1
pos_dot - pos_first_sig = 1-3 = -2 不符合

原因就在于k为负数时,小数点在首位有效数字前面,小数点会被计算进去