文章目录
1.开头
今天在Codewars上又是碰到一个比较有趣的代码实现问题,是要我们把我们日常所用的阿拉伯数字转化为罗马数字,从中我们可以看出其中的逻辑需求是要求我们输入函数一个int型数据(不知道罗马数字里有没有小数啊哈哈),然后我们把输入的数字经过拆分根据罗马数字的表示规则重新组合,返回出一个string类型的数据。其中因为罗马数字的命名规则的奇特,我们需要对我们的string型数据进行一些基本的string操作。借由此机会来学习string类型操作的用法。
呜呜呜,光写Codewars上的实战经验总结还是没人看嗷,主要是光靠实战可能无法总结出系统的知识点,对各位的帮助没有那么打。所以今后可能还会写Qt的C++GUI编程,多多指教了。
2.具体先看题目内容
1)要求
原文:
Create a function taking a positive integer as its parameter and returning a string containing the Roman Numeral representation of that integer.
Modern Roman numerals are written by expressing each digit separately starting with the left most digit and skipping any digit with a value of zero. In Roman numerals 1990 is rendered: 1000=M, 900=CM, 90=XC; resulting in MCMXC. 2008 is written as 2000=MM, 8=VIII; or MMVIII. 1666 uses each Roman symbol in descending order: MDCLXVI.
翻译君:
创建一个以正整数为参数的函数,并返回一个包含该整数的罗马数字表示形式的字符串。
现代罗马数字的书写方式是,从最左边的数字开始分别表示每个数字,然后跳过任何零值的数字。用罗马数字1990表示:1000 = M,900 = CM,90 = XC;导致MCMXC。2008表示为2000 = MM,8 = VIII; 或MMVIII。1666以降序使用每个罗马符号:MDCLXVI。
2)例子
Assert::That(solution(182) , Equals("CLXXXII"));
Assert::That(solution(1990) , Equals("MCMXC"));
Assert::That(solution(1875) , Equals("MDCCCLXXV"));
3.我的又一次头秃探索
1)认识罗马数字计数方法
基本字符
基本字符 | I | V | X | L | C | D | M |
---|---|---|---|---|---|---|---|
相应的阿拉伯数字表示为 | 1 | 5 | 10 | 50 | 100 | 500 | 1000 |
- 相同的数字连写、所表示的数等于这些数字相加得到的数、如:Ⅲ=3;
- 小的数字在大的数字的右边、所表示的数等于这些数字相加得到的数、 如:Ⅷ=8、Ⅻ=12;
- 小的数字(限于 I、X 和 C)在大的数字的左边、所表示的数等于大数减小数得到的数、如:Ⅳ=4、Ⅸ=9;
- 正常使用时、连写的数字重复不得超过三次;
在一个数的上面画一条横线、表示这个数扩大 1000 倍。(这个不用管,不再我们的实现范围内)- 基本数字 Ⅰ、X 、C 中的任何一个、自身连用构成数目、或者放在大数的右边连用构成数目、都不能超过三个;放在大数的左边只能用一个;
- 不能把基本数字 V 、L 、D 中的任何一个作为小数放在大数的左边采用相减的方法构成数目;放在大数的右边采用相加的方式构成数目、只能使用一个;
2)认识基本string操作
这里,我是从YAMIZA大佬处学习的关于string的各种操作:
其出处:链接: link 点击link直达
不想自己打了,我好懒啊欸嘿嘿。。。
1.字符串的生成
string str:生成空字符串
string s(str):生成字符串为str的复制品
string s(str, strbegin,strlen):将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串初值
string s(cstr, char_len):以C_string类型cstr的前char_len个字符串作为字符串s的初值
string s(num ,c):生成num个c字符的字符串
string s(str, stridx):将字符串str中从下标stridx开始到字符串结束的位置作为字符串初值
————————————————
版权声明:本文为CSDN博主「YAIMZA」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37941471/article/details/82107077
2.字符串的大小和容量
1. size()和length():返回string对象的字符个数,他们执行效果相同。
2. max_size():返回string对象最多包含的字符数,超出会抛出length_error异常
3. capacity():重新分配内存之前,string对象能包含的最大字符数
————————————————
版权声明:本文为CSDN博主「YAIMZA」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37941471/article/details/82107077
3.string的插入:push_back() 和 insert()
1. push_back(): 尾插一个字符
2. insert(pos,char):在制定的位置pos前插入字符char
4.string拼接字符串:append() & + 操作符
// 方法一:append()
string s1("abc");
s1.append("def");
cout<<"s1:"<<s1<<endl; // s1:abcdef
// 方法二:+ 操作符
string s2 = "abc";
/*s2 += "def";*/
string s3 = "def";
s2 += s3.c_str();
cout<<"s2:"<<s2<<endl; // s2:abcdef
————————————————
版权声明:本文为CSDN博主「YAIMZA」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37941471/article/details/82107077
5.string的删除:erase()
1. iterator erase(iterator p);//删除字符串中p所指的字符
2. iterator erase(iterator first, iterator last);//删除字符串中迭代器
区间[first,last)上所有字符
3. string& erase(size_t pos = 0, size_t len = npos);//删除字符串中从索引
位置pos开始的len个字符
4. void clear();//删除字符串中所有字符
————————————————
版权声明:本文为CSDN博主「YAIMZA」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37941471/article/details/82107077
其实还有很多很重要的,比如遍历啊,删除啊,查找啊,替换啊之类的功能
这些还是自信观看YAIMZA大佬文章吧,我就不充当搬运工了。。。(主要还是拿别人的劳动成果心虚。。。)
那好,下面就是自己的劳动成果了:
3)我的实现构想
这里可能会略显复杂,希望有大佬能帮忙简化算法。
#include <iostream>
#include <string>
using namespace std;
string solution(int number);
int main()
{
int numble;
cin >> numble;
cout << solution(numble);
return 0;
}
string solution(int number){
string str;
int i=0;
while (number >= 1000){
str.push_back('M');
number -= 1000;
i++;
}
if (number >= 900) {
str.insert(str.begin() + i - 1, 'C');
number -= 900;
i++;
}else if( number >= 500 ){
str.push_back('D');
number -= 500;
i++;
} else if (number >= 400 ){
str.push_back('C');
str.push_back('D');
number -= 400;
i += 2;
}
while (number >= 100){
str.push_back('C');
number -= 100;
i++;
}
if (number >= 90) {
str.insert(str.begin() + i - 1, 'X');
number -= 90;
i ++;
}else if( number >= 50 ){
str.push_back('L');
number -= 50;
i ++;
} else if (number >= 40 ){
str.push_back('X');
str.push_back('L');
number -= 40;
i += 2;
}
while (number >= 10){
str.push_back('X');
number -= 10;
i++;
}
if (number >= 9) {
str.insert(str.begin() + i - 1, 'X');
number -= 9;
i ++;
}else if( number >= 5 ){
str.push_back('V');
number -= 5;
i ++;
} else if (number >= 4 ){
str.push_back('I');
str.push_back('V');
number -= 4;
i += 2;
}
while (number >= 1){
str.push_back('I');
number -= 1;
i++;
}
return str;
}
然后我们就遇到了BUG,就是如果开始时就在1000~900之间,那么在没有M的前提下,就不能插入C,所以我们要适当改进。
我们发现自己的逻辑出现了问题,其实不需要再M前插入C,在1000~900间,只要打印CM即可了。所以更新代码如下:
#include <string>
string solution(int number){
string str;
int i=0;
while (number >= 1000){
str.push_back('M');
number -= 1000;
i++;
}
if (number >= 900) {
str.push_back('C');
str.push_back('M');
number -= 900;
i+=2;
}else if( number >= 500 ){
str.push_back('D');
number -= 500;
i++;
} else if (number >= 400 ){
str.push_back('C');
str.push_back('D');
number -= 400;
i += 2;
}
while (number >= 100){
str.push_back('C');
number -= 100;
i++;
}
if (number >= 90) {
str.push_back('X');
str.push_back('C');
number -= 90;
i ++;
}else if( number >= 50 ){
str.push_back('L');
number -= 50;
i ++;
} else if (number >= 40 ){
str.push_back('X');
str.push_back('L');
number -= 40;
i += 2;
}
while (number >= 10){
str.push_back('X');
number -= 10;
i++;
}
if (number >= 9) {
str.push_back('I');
str.push_back('X');
number -= 9;
i ++;
}else if( number >= 5 ){
str.push_back('V');
number -= 5;
i ++;
} else if (number >= 4 ){
str.push_back('I');
str.push_back('V');
number -= 4;
i += 2;
}
while (number >= 1){
str.push_back('I');
number -= 1;
i++;
}
return str;
}
又是再一次喜闻乐见的通过,这次因为深夜肝稿导致自己的逻辑思维有点混乱,请不要在意,。萌新嘛,还是各位多多海涵了。