问题描述
小M在工作时遇到了一个问题,他需要将用户输入的不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分。小M还发现,有时候输入的数字字符串前面会有无用的
0
,这些也需要精简掉。请你帮助小M编写程序,完成这个任务。
测试样例
样例1:
输入:
s = "1294512.12412"
输出:'1,294,512.12412'
样例2:
输入:
s = "0000123456789.99"
输出:'123,456,789.99'
样例3:
输入:
s = "987654321"
输出:'987,654,321'
解题思路:
问题理解
我们需要将一个不带千分位逗号的数字字符串转换为带千分位逗号的格式,并且保留小数部分。此外,输入的字符串可能包含前导零,这些前导零需要被去除。
数据结构选择
- 我们可以使用字符串来处理输入和输出,因为字符串操作在处理文本格式时非常方便。
算法步骤
- 去除前导零:首先,我们需要去除字符串中的前导零。可以使用
std::stod
将字符串转换为双精度浮点数,然后再转换回字符串,这样可以自动去除前导零。 - 分割整数和小数部分:将字符串分割为整数部分和小数部分。可以使用
std::find
找到小数点的位置,然后分别处理整数和小数部分。 - 格式化整数部分:对整数部分进行格式化,每三位插入一个逗号。可以使用一个循环从后向前遍历整数部分,每三位插入一个逗号。
- 合并结果:将格式化后的整数部分和小数部分合并,形成最终的结果。
第一版代码:
为什么这个叫第一版,自然是因为它过不了
#include <bits/stdc++.h>
#include <string>using namespace std;std::string solution(const std::string& s) {// 去除前导零double num = stod(s);// cout<<num;string cleanedStr = to_string(num);// cout<<cleanedStr<<endl;// 分割整数和小数部分size_t dotPos = cleanedStr.find('.');string integerPart = cleanedStr.substr(0, dotPos);string decimalPart = cleanedStr.substr(dotPos);// 格式化整数部分string formattedIntegerPart;int count = 0;for (int i = integerPart.size() - 1; i >= 0; --i) {formattedIntegerPart = integerPart[i] + formattedIntegerPart;count++;if (count % 3 == 0 && i != 0) {formattedIntegerPart = ',' + formattedIntegerPart;}}// cout<<formattedIntegerPart<<endl<<decimalPart;// 合并结果return formattedIntegerPart + decimalPart;
}int main() {std::cout << (solution("1294512.12412") == "1,294,512.12412") << std::endl;std::cout << (solution("0000123456789.99") == "123,456,789.99") << std::endl;std::cout << (solution("987654321") == "987,654,321") << std::endl;
}
问题分析:
这里的问题在于:当我用stod函数转化成num变量时,这个数字会在小数后面默认补全到6位,再转回到string的时候就会多出零来。
解决方法:
我在中间对小数部分用一个循环去除末尾的0
while (decimalPart.size() > 1 && decimalPart.back() == '0') {decimalPart.pop_back();}
优化处理:考虑到有些数字的小数位数会大于double的精度范围,所以思路有一定改进
最终代码:
#include <bits/stdc++.h>
#include <string>using namespace std;std::string solution(const std::string& s) {// 去除前导零size_t start = 0;while (start < s.size() && s[start] == '0') {start++;}string cleanedStr = s.substr(start);// 分割整数和小数部分size_t dotPos = cleanedStr.find('.');string integerPart = (dotPos == string::npos) ? cleanedStr : cleanedStr.substr(0, dotPos);string decimalPart = (dotPos == string::npos) ? "" : cleanedStr.substr(dotPos);// 去除小数部分多余的零while (decimalPart.size() > 1 && decimalPart.back() == '0') {decimalPart.pop_back();}// 格式化整数部分string formattedIntegerPart;int count = 0;for (int i = integerPart.size() - 1; i >= 0; --i) {formattedIntegerPart = integerPart[i] + formattedIntegerPart;count++;if (count % 3 == 0 && i != 0) {formattedIntegerPart = ',' + formattedIntegerPart;}}// 合并结果return formattedIntegerPart + decimalPart;
}int main() {std::cout << (solution("1294512.12412") == "1,294,512.12412") << std::endl;std::cout << (solution("0000123456789.99") == "123,456,789.99") << std::endl;std::cout << (solution("987654321") == "987,654,321") << std::endl;
}
运行结果: