以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y年,直到x岁才遇到n个数字都不相同的年份”这句话。
输入格式:
输入在一行中给出出生年份y和目标年份中不同数字的个数n,其中y在[1, 3000]之间,n可以是2、或3、或4。注意不足4位的年份要在前面补零,例如公元1年被认为是0001年,有2个不同的数字0和1。
输出格式:
根据输入,输出x和能达到要求的年份。数字间以1个空格分隔,行首尾不得有多余空格。年份要按4位输出。注意:所谓“n个数字都不相同”是指不同的数字正好是n个。如“2013”被视为满足“4位数字都不同”的条件,但不被视为满足2位或3位数字不同的条件。
输入样例1:
1988 4
输出样例1:
25 2013
输入样例2:
1 2
输出样例2:
0 0001
最初时
#include<stdio.h>
#include<stdlib.h>
int main()
{
int y,n;
int count=0;//计数器
int year;
char a[3000][4];//定义字符数组a,存放3000个年份
for(int i=0;i<3000;i++)
{
itoa(i+1,a[i],10);//itoa()学到了,将数值转换为字符(另有许多),在stdlib.h里面
}//此时除了四位数年份以外所有年份都是靠左的,比如a[959]="960\0"
scanf("%d %d",&y,&n);
//从y开始数
for(int j=y;j<3000;j++)
{
//现在开始数y后每个年份有几位数字不同
if(a[j][0]==a[j][1])count++;
else if(a[j][0]==a[j][2])count++;
else if(a[j][0]==a[j][3])count++;
else if(a[j][1]==a[j][2])count++;
else if(a[j][1]==a[j][3])count++;
else if(a[j][2]==a[j][3])count++;//机械劳动,有待改善
if(4-count==n)
{
year=j+1;
count=0;//计数器归零
break;
}
else
{
count=0;
}
}
//现在年龄为year-y
//年份的输出复杂些
if((year>=1)&&(year<=999))
{
printf("%d %04d",year-y,atoi(a[year-1]));
}
else
{
printf("%d %s",year-y,a[year-1]);
}
system("pause");
return 0;
}
完全就是审题失误,从题意的理解再到很多细节,错得一塌糊涂。
重新做之后
#include<stdio.h>
#include<stdlib.h>
int main()
{
int y,n;
int age=0,year;
char tem[5]={"0000"};//数字转为字符便于判断重复情况
int num1;//计数器,记重复数
scanf("%d %d",&y,&n);
for(int i=y;;i++,age++)
{
//数字转字符
itoa(i,tem,10);
//判断重复情况,逆向
num1=0;
if(tem[0]==tem[1])num1++;
if(tem[0]==tem[2])num1++;
if(tem[0]==tem[3])num1++;
if(tem[1]==tem[2])num1++;
if(tem[1]==tem[3])num1++;
if(tem[2]==tem[3])num1++;
if((num1==0&&n==4)||(num1==1&&n==3)||((num1==3||num1==2)&&n==2)||(num1==6&&n==1))//找到了n个数字不同的年份,它就是i
{
year=i;
break;
}
}
printf("%d %04d",age,year);
system("pause");
return 0;
}
这次本应没错了,但仍编译错误,查询PTA平台说明书时知道了:
我刚学到的itoa函数,还想着用它来节省功夫,但竟是明文禁止的不让用。
再改进
#include<stdio.h>
#include<stdlib.h>
int main()
{
char* Int2String(int num,char *str);
int y,n;
int age=0,year;
char tem[5]={"0000"};//数字转为字符便于判断重复情况
int num1;//计数器,记重复数
scanf("%d %d",&y,&n);
for(int i=y;;i++,age++)
{
//数字转字符
Int2String(i,tem);
//判断重复情况,逆向
num1=0;
if(tem[0]==tem[1])num1++;
if(tem[0]==tem[2])num1++;
if(tem[0]==tem[3])num1++;
if(tem[1]==tem[2])num1++;
if(tem[1]==tem[3])num1++;
if(tem[2]==tem[3])num1++;
if((num1==0&&n==4)||(num1==1&&n==3)||((num1==3||num1==2)&&n==2)||(num1==6&&n==1))//找到了n个数字不同的年份,它就是i
{
year=i;
break;
}
}
printf("%d %04d",age,year);
system("pause");
return 0;
}
char* Int2String(int num,char *str)//10进制
{
int i = 0;//指示填充str
if(num<0)//如果num为负数,将num变正
{
num = -num;
str[i++] = '-';
}
//转换
do
{
str[i++] = num%10+48;//取num最低位 字符0~9的ASCII码是48~57;简单来说数字0+48=48,ASCII码对应字符'0'
num /= 10;//去掉最低位
}while(num);//num不为0继续循环
str[i] = '0';
//确定开始调整的位置
int j = 0;
if(str[0]=='-')//如果有负号,负号不用调整
{
j = 1;//从第二位开始调整
++i;//由于有负号,所以交换的对称轴也要后移1位
}
//对称交换
for(;j<i/2;j++)
{
//对称交换两端的值 其实就是省下中间变量交换a+b的值:a=a+b;b=a-b;a=a-b;
str[j] = str[j] + str[i-1-j];
str[i-1-j] = str[j] - str[i-1-j];
str[j] = str[j] - str[i-1-j];
}
return str;//返回转换后的值
}
主要就是把itoa函数换了一下,改成了自己写的,这里隔空感谢一下菜鸟教程,太厉害了。
C 语言整数与字符串的相互转换
- itoa函数安全隐患在于:当字符数组长度不足保存结果时会导致缓冲区溢出 来源 https://www.cnblogs.com/lidabo/archive/2012/07/10/2584706.html
这里再强调一下,字符数组一定要注意,定义的时候要多留一位,存放\0,错了不止一次。 - 在判断一个数字里面有几位不同的时候,一直出错
- 最开始直接C42,判断六次,每有重复的计数器+1,之后拿4减这个,就想得到有几位不同,这是办不到的。
- 实际上稍复杂点,后来改为了:用这个重复数去对应n值(不同位数),相当于一一列出,得到了有普适性的答案:
重复数 | 几位不同 |
---|---|
0 | 4 |
1 | 3 |
3或2 | 2 |
6 | 1 |
- 其他的就错在将tem数组初始化的时候,初始化为\0,这就影响了判断,比如,输入202,他会判断有三位不同,应为数组内部是\0202。