Codewars一些积累No.3 从罗马数字编码器来初探string的实用用法

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)认识罗马数字计数方法

基本字符

基本字符IVXLCDM
相应的阿拉伯数字表示为1510501005001000
  1. 相同的数字连写、所表示的数等于这些数字相加得到的数、如:Ⅲ=3;
  2. 小的数字在大的数字的右边、所表示的数等于这些数字相加得到的数、 如:Ⅷ=8、Ⅻ=12;
  3. 小的数字(限于 I、X 和 C)在大的数字的左边、所表示的数等于大数减小数得到的数、如:Ⅳ=4、Ⅸ=9;
  4. 正常使用时、连写的数字重复不得超过三次;
  5. 在一个数的上面画一条横线、表示这个数扩大 1000 倍。(这个不用管,不再我们的实现范围内)
  6. 基本数字 Ⅰ、X 、C 中的任何一个、自身连用构成数目、或者放在大数的右边连用构成数目、都不能超过三个;放在大数的左边只能用一个;
  7. 不能把基本数字 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;
}

又是再一次喜闻乐见的通过,这次因为深夜肝稿导致自己的逻辑思维有点混乱,请不要在意,。萌新嘛,还是各位多多海涵了。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值