大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
问题:
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M,其对应关系如下表:
字符 | 数值 |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。
通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
你的任务是设计一个算法,将一个整数转换为罗马数字。不巧的是,此时打印机恰好发生了一些故障。它不能够打印某些字符,否则将会发生故障彻底损坏。因此,你需要将这部分字符从生成的罗马数字中剔除掉。
Input
输入有两行
第一行为一个整数num,代表要转换的数,其中1 <= num <= 3999;
第二行为一个字符串,字符串中的字符不能在结果中出现,保证字符串的长度不会超过3。
Output
输出为一个字符串,代表转换成的罗马数字。如果罗马数字全部不能打印,则输出空行。
Sample Input
9
I
Sample Output
X
//这题对我来说有些难度,这里我总结了一点心得,分享一下
解题思路
任务一:将正整数转化成罗马字符
任务二:筛选掉我们不需要的字符
接下来我分任务给出不同解法
主函数部分(略了)
#include<stdio.h>
#include<string.h>
void change(int num,char *sh);
void del(char* sh,char* ch);
int main(){
int num;
char ch[3]={};
char sh[100]={};
scanf(“%d %s”,&num,&ch);
change(num,sh);
del(sh,ch);
printf(“%s”,sh);
}
任务一:将正整数转罗马字符串
方法一:
//找离该数最大的罗马字符
int stomax(int num){
int reflect[13]={1,4,5,9,10,40,50,90,100,400,500,900,1000};
int cuns=0;
for(int i=0;i<13;i++){
if(reflect[i]>num){
break;
}
cuns=i;
}
return cuns;
}
void change(int num,char* sh){
char roman[14][3]={“I”,”IV”,”V”,”IX”,”X”,”XL”,”L”,”XC”,”C”,”XD”,”D”,”XM”,”M”};
int reflect[13]={1,4,5,9,10,40,50,90,100,400,500,900,1000};
//用num去除数,寻找需要的罗马字符个数
int cuns=stomax(num);
int cn=0;
while(num>0){
int t=num/reflect[cuns];
num=num%reflect[cuns];
for(int j=0;j<t;j++){
//以下这句很想用上指针或者strcpy或者strcat,奈何我不会用 ,求大家带带我
for(int k=0;k<strlen(roman[cuns]);k++){
sh[cn++]=roman[cuns][k];
}
}
cuns=stomax(num);
}
}
方法二:
void change(int num,char* sh){
char roman[14][3]={“I”,”IV”,”V”,”IX”,”X”,”XL”,”L”,”XC”,”C”,”XD”,”D”,”XM”,”M”};
int reflect[13]={1,4,5,9,10,40,50,90,100,400,500,900,1000};
for(int i=12,j=0;i>=0;i–){
while(reflect[i]<=num){
num-=reflect[i];//这里就是精髓啊
for(int k=0;k<strlen(roman[i]);k++){
sh[j++]=roman[i][k];
}
}
}
}
任务二:除去对应的字符
方法一:
void del(char* sh,char* ch){
//利用双指针,一个判断,一个存储
int i,j;
for(i=0,j=0;i<strlen(sh);i++){
for(int k=0;k<strlen(ch);k++){
if(sh[i]==ch[k]) continue;
else {
*(sh+j)=*(sh+i);
j++;
}
}
}
*(sh+j)=’\0′;//这里一定要注意,有了它数组不需要的部分才会消失
}
方法二:
#include<stdlib.h>//不要忘了,用malloc必备
char *del(char* sh,char* ch){
printf(“%p “,sh);
char *shf=(char*)malloc(sizeof(char)*strlen(sh));
int i=0,j=0;
for(i=0,j=0;i<strlen(sh);i++){
for(int k=0;k<strlen(ch);k++){
if(sh[i]!=ch[k]){
*(shf+j)=sh[i];
j++;
}
}
}
*(shf+j)=’\0′;
return shf;//为啥这里是返回而不是直接让sh=shf?
//因为sh实际是局部形式指针参数,是一个地址与原sh一样的指针,把sh的地址赋值为shf的地址并不能改变原sh 的值,从而没有意义。上面是因为在sh的原地址做出了改变,所以有意义。除了直接return,还能将形参修改成全局变量,我还不会,会了再补充。
}
方法三:链表法
虽然没输出,也放这了,有空再改。(主要是思想?,将不需要元素的地址跳过)
void del(char* sh,char* ch){
char *shf=(char*)malloc(sizeof(char)*strlen(sh));
while(sh!=NULL || sh+1!=NULL){
for(int i=0;i<strlen(ch);i++){
if(*sh==ch[i]){
shf=sh+1;
sh++;
sh=shf+1;
}else{
sh++;
}
}
sh++;
}
}
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/187507.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...