B1001 3N+1猜想
B1011 A+B和C
- 布尔型的输出
布尔型在C++中可以直接使用,但在C中必须添加头文件stdbool.h,若以%d输出,则true为1,false为0,若要输出true/false,可以以字符串的形式用puts()输出。 - 注意:若要用字符串数组的形式输出,在赋值的时候不可以直接赋值,但在初始化数组的时候是可以用" "的字符串初始化,同时发现若以?:的形式初始化数组是不可以的。
- int -类型的的数据范围是-231 —231 -1,即109次方以内都可以用int;而题目给的是-231 —231 ,所以造成后两个数据没有通过!必须用long long类型来定义变量,long long 数据范围—超过1010 小于1018 次方!scanf输入与printf输出使用%lld。超过1010 或1018 次方
题目若没有说正整数小于109 就必须把变量设为long long。 - PAT中的输出可以不连续输出,也就是说在一个测试点中,可以输入一组数据,然后直接输出数据,然后再读入,再输出。这样是可行的。
B1026 程序运行时间
1.时分秒的输出要保证不足两位时高位用0补充。
2.当题目要求四舍五入保留到整数位时,可以考虑使用math.h中的round()函数,但要注意这种函数的返回值仍为double类型,因此赋值给整型变量时要进行强制类型转换。
B1046划拳
B1008数组元素循环右移问题
–已通过OJ,但是时间复杂度较高,并不是最优算法!
#include <cstdio>
int main() {
int n,m;
scanf("%d%d", &n, &m);
m = m%n;
int a[n];
for(int i=0; i<n; i++) {
scanf("%d", &a[i]);
}
int temp;
for(int i=0; i<m; i++) {
temp=a[n-1];a[n-1]=a[0];a[0]=temp;
for(int i=n-1; i>1; i--) {
temp=a[i];a[i]=a[i-1];a[i-1]=temp;
}
}
for(int i=0; i<n; i++) {
printf("%d", a[i]);
if(i<n-1) {
printf(" ");
}
}
return 0;
}
- == 题目虽然限制了不能使用另外的数组,但是可以直接输出,不用考虑如何移动的问题!==-----书中算法是用这种思想写的
- 注意题目并没有规定M的最大值,也即是说M有可能大于N,因此可以令M = M%N简化算法;这样做是因为N维数组循环向右移动N个位置与原始序列相同。
–书中给出的移动次数最少的算法:
1.求两个数的最大公约数:辗转相除法,主要过程是,先让大数减小数,若余数为零,则最大公约数即为此小数,若余数不为零,则用小数除以余数,看新得到的余数是否为零,如此递归,直到余数为零,此时的除数就是最大公约数。
可以用递归算法写这个部分:
int gcd(int a, int b) {
if(b==0) return a;
else return gcd(b, a % b);
}
#include <cstdio>
int gcd(int a, int b) {
//辗转相除法求a和b的最大公约数
if(b==0) return a;
else return gcd(b, a%b);
}
int main() {
int a[110];
int n, m, temp, pos, next;
scanf("%d%d", &n, &m);
for(int i=0; i<n; i++) {
scanf("%d", &a[i]);
}
m=m%n; //修正m,同时也保证了m一定小于n
if(m!=0){
int d=gcd(n,m);
for(int i=n-m; i<n-m+d; i++) {
temp = a[i];
pos = i;
do {
next = (pos-m+n)%n;
if(next!=i) a[pos]=a[next];
else a[pos]=temp;
pos = next;
}while(pos!=i);
}
}
for(int i=0; i<n; i++) {
printf("%d", a[i]);
if(i<n-1) printf(" ");
}
return 0;
}
B1012 数字分类
1.关于强制类型转换的优先级:
强制类型转换的优先级高于除号。
运算符优先级大全:https://blog.csdn.net/hhs49707555/article/details/77618874
B1018锤子剪刀布
1.考虑将输入的字母用一个函数换成数字,然后再进行处理。
int change(char c) {
if(c=='B') return 0;
if(c=='C')return 1;
if(c=='J')return 2;
}
2.由于在输入时为单个字符,scanf时使用%c可能会吸收空格或换行,因此在适当的地方要用getchar()吸收掉这些空格与换行
3.最后输出的时候,由于要考虑数字重新转化为字母,所以最开始的时候可以建立一个char mp[3]的字符数组,以此来对应各字母
B1010 一元多项式求导
有两个数据点无法通过,推测原因可能是当指数为负数的时候没有运算,因为自己写的循环终止条件是指数为零。
代码如下:
#include <cstdio>
int main() {
int a,exp,count=0; //a为底数,exp为指数
scanf("%d%d", &a, &exp);
while(exp!=0) {
a=a*exp;exp=exp-1;
if(count!=0) printf(" ");
printf("%d %d", a, exp);
count++;
scanf("%d%d", &a, &exp);
}
return 0;
}
注意:1.本题的指数没有负数,不存在负指数的情况
2.结束输入采用while EOF的形式
3.对于零次项求导要特别的写出来
4.求导必须从低次项逐渐向高次求导,否则如果反过来求,高次项求导结果会把还没有求导的低次项系数覆盖,出现错误
5.为什么在求导之后,要把该项的系数赋值为零
#include <cstdio>
int main() {
int a[1010]={0}; //a[i]表示的值是指数为i的系数
int k, e, count=0;
while(scanf("%d%d", &k, &e)!=EOF) {
a[e]=k;
}
a[0]=0;
for(int i=1; i<=1000; i++) {
a[i-1]=a[i]*i;
a[i]=0;
if(a[i-1]!=0) {
count++;
}
}
if(count==0) printf("0 0");
else {
for(int i=1000; i>=0; i--) {
if(a[i]!=0) {
printf("%d %d", a[i], i);
count--;
if(count!=0) printf(" ");
}
}
}
return 0;
}
其他简单解法
#include <cstdio>
int main() {
int coe, exp;
int flag=1;
while(scanf("%d%d", &coe, &exp)!=EOF) {
if(exp>0){
if(flag==1) {
printf("%d %d", coe*exp, exp-1);
flag=0;
}else {
printf(" %d %d", coe*exp, exp-1);
}
}
}
if(flag==1) printf("0 0");
return 0;
}
3.2 查找元素
B1041 考试座位号
#include <cstdio>
typedef struct stu_info{
long long exam_num;
int test_seat;
int exam_seat;
}stu_info;
int main() {
int n;
scanf("%d", &n);
stu_info info[n];
for(int i=0; i<n; i++) {
scanf("%lld%d%d", &info[i].exam_num, &info[i].test_seat, &info[i].exam_seat);
}
int num;
scanf("%d", &num);
for(int i=0; i<num; i++) {
int seat_test;
scanf("%d", &seat_test);
for(int j=0; j<n; j++) {
if(info[j].test_seat==seat_test){
printf("%lld %d", info[j].exam_num, info[j].exam_seat);
}
}
if(i<num-1) printf("\n");
}
return 0;
}
B1004 成绩排名
已通过OJ
#include <cstdio>
struct stu_score{
char name[11];
char num[11];
};
int main() {
stu_score info[101];
int n; //n为学生个数
scanf("%d", &n);
int grade[101]={-1};
for(int i=0; i<n; i++) {
getchar();
scanf("%s %s %d", &info[i].name, &info[i].num, &grade[i]);
}
int min=0, max=0;
for(int i=1; i<n; i++) {
if(grade[i]<grade[min] && grade[i]>=0) min=i;
if(grade[i]>grade[max]) max=i;
}
printf("%s %s\n", info[max].name, info[max].num);
printf("%s %s", info[min].name, info[min].num);
return 0;
}
书中算法很简洁,在写的过程中,主要问题是:
1.一开始想把分数以info[i]的形式保存在i中,但发现在输入时由于分数处在最后一个,所以会导致字符数组赋值时出现两个循环,太麻烦
2.然后又想着把分数单独放在一个数组中,最后寻找最大最小值也需要一次冒泡排序的循环,
以下为书中算法,注意ans_max.score最初赋值为-1,ans_min.score最初赋值为101,千万不要弄反了!
#include <cstdio>
struct Student{
char name[15];
char id[15];
int score;
}temp, ans_max, ans_min;
int main() {
int n;
scanf("%d", &n);
ans_max.score=-1;
ans_min.score=101;
for(int i=0; i<n; i++) {
scanf("%s%s%d", &temp.name, &temp.id, &temp.score);
if(temp.score>ans_max.score) ans_max=temp;
if(temp.score<ans_min.score) ans_min=temp;
}
printf("%s %s\n", ans_max.name, ans_max.id);
printf("%s %s", ans_min.name, ans_min.id);
return 0;
}
B1028人口普查
1.没想出来如何比较日期,一开始想的是直接用yy365+mm30+dd这种粗暴的方法,书中用了if–else if —else分支来比较日期
下面是自己写的,本来一直没办法通过,结果发现自己忘记把temp.num赋值了,浪费了好多时间。好蠢!
另外注意:若所有人的日期都不合法,即count=0, 则在最后输出的时候要单独写出来输出0,否则会多一个空格,报错!
已通过OJ
#include <cstdio>
struct birthday{
char name[6];
int year;
int month;
int day;
int num;
}temp, eldest, yongest;
int main() {
int n; //人数
scanf("%d", &n);
int count=0; //计算生日合理的人数
eldest.num=2014*365+9*30+6+1;
yongest.num=1814*365+9*30+6-1;
for(int i=0; i<n; i++) {
scanf("%s %d/%d/%d", &temp.name, &temp.year, &temp.month, &temp.day);
temp.num=temp.year*365+temp.month*30+temp.day;
if(temp.num<1814*365+9*30+6||temp.num>2014*365+9*30+6){
continue;
}
count++;
if(temp.num<eldest.num) eldest=temp;
if(temp.num>yongest.num) yongest=temp;
}
if(count==0){
printf("0");
} else {
printf("%d %s %s", count, eldest.name, yongest.name);
}
return 0;
}
书中采用的这个函数来比较大小,是正常解法。
bool LessEqu(birthday a, birthday b){ //日期上a比b小则返回true
if(a.year!=b.year) return a.year<=b.year;
else if(a.month<=b.month)return a.month<=b.month;
else return a.day<=b.day;
}
B1032 挖掘机
B1036 跟奥巴马一起编程
出现问题原因:行与行之间并没有空行!这题很简单的。
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
int main() {
int n; //n为列数
char c; //边长的字符
scanf("%d %c", &n, &c);
int raw; //表示行数
raw=(int)round(n*0.5);
//for(int i=col; i>0; i--)
for(int i=raw; i>0; i--) {
if(i==raw || i==1){
for(int j=0; j<n; j++) {
printf("%c", c);
}
if(i==raw) printf("\n");
} else {
for(int j=0; j<n; j++) {
if(j==0 || j==n-1) {
printf("%c", c);
} else {
printf(" ");
}
}
printf("\n");
}
}
return 0;
}
B1027 打印沙漏
对于每行需要打印的字符数及空格数认识不清
数据点有两个没通过,以下为代码
#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
int raw_cal(int n) {
//计算给定n时,第一行输出的字符个数,同时也是沙漏总行数
double d;
d= (-4+sqrt(8.0+8*n))/4;
int raw=(int) d;
if(raw==0) return 1;
return raw*2+1;
}
int main() {
int n; //n表示输入的总的字符数
char c; //表示输入的字符
scanf("%d %c", &n, &c);
int raw; //表示沙漏第一行字符个数,也是沙漏总行数
raw=raw_cal(n);
int sum=0;
for(int k=1; k<=raw; k=k+2) {
sum += k;
}
sum =sum*2-1;
int rest=n-sum;
int count; //表示每行打印出来的字符数
for(int i=0; i<raw; i++) {
if(i<=(raw-1)/2) {
count=raw-i*2;
int temp=i;
while(temp--) { //打印每行前面的空格
printf(" ");
}
for(int j=count; j>0; j--) {
printf("%c",c);
}
if(raw!=1) {
printf("\n");
}
} else {
count=2*i-raw+2;
for(int k=0; k<raw-i-1; k++) {
printf(" ");
}
for(int j=1; j<=count; j++) {
printf("%c", c);
}
if(i<raw-1) printf("\n");
if(i==raw-1 && rest!=0) {
printf("\n");
}
}
}
if(rest!=0) {
printf("%d", rest);
}
return 0;
}
书中把正三角和倒三角分开打印,这样打印思路更加清晰,而且更容易!
#include <cstdio>
#include <cmath>
int main() {
int n;
char c;
scanf("%d %c", &n, &c);
int bottom=(int) sqrt(2.0*(n+1))-1;
if(bottom%2==0) bottom--;
int used=(bottom+1)*(bottom+1)/2-1;
for(int i=bottom; i>=1; i-=2) { //输出倒三角
for(int j=0; j<(bottom-i)/2; j++) {
printf(" ");
}
for(int j=0; j<i; j++) {
printf("%c", c);
}
printf("\n");
}
for(int i=3; i<=bottom; i+=2) { //输出正三角
for(int j=0; j<(bottom-i)/2; j++) {
printf(" ");
}
for(int j=0; j<i; j++) {
printf("%c", c);
}
printf("\n");
}
printf("%d\n", n-used);
return 0;
}
B1022 D进制的A+B
#include <cstdio>
int main() {
int a,b,c,q;
scanf("%d %d %d", &a, &b, &q);
c=a+b;
int z[40], num=0;
do{
z[num++] = c%q;
c=c/q;
}while(c!=0);
for(int i=num-1; i>=0; i--) {
printf("%d", z[i]);
}
return 0;
}
B1037 在霍格沃兹找零钱
#include <cstdio>
int main() {
long long p_g, p_s, p_k, p_knuts; //应付
long long a_g, a_s, a_k, a_knuts; //实付
long long c_g, c_s, c_k, c_knuts; //找零
scanf("%lld.%lld.%lld %lld.%lld.%lld", &p_g, &p_s, &p_k, &a_g, &a_s, &a_k);
p_knuts=(p_g*17+p_s)*29+p_k;
a_knuts=(a_g*17+a_s)*29+a_k;
c_knuts=a_knuts-p_knuts;
if(c_knuts<0) {
printf("-");
c_knuts *= -1;
}
c_k=c_knuts%29;
c_g=c_knuts/29/17;
c_s=c_knuts/29-c_g*17;
printf("%lld.%lld.%lld", c_g, c_s, c_k);
return 0;
}
B1009 说反话
代码中由于使用了gets()来接收字符串,但是PAT已经不再支持gets()(气死我了,还以为自己代码哪里错了,还添加了一溜头文件,结果还是报错 ,没想到是这个原因)
所以考虑使用其他方法:
关于头文件中的cin、cout函数 :
首先需要添加头文件
#include
using namespace std;
1.cin:采用输入运算符>>,不需要取地址符,
如
int n;
cin >> n;
double db;
cin >>db;
char c;
cin >> c;
cin >> n >> db >> c >> str >>; //其中str为char型数组,
如果想读入一整行,则需要使用getline函数,如:
char str[100];
cin.getline(str, 100);
2.cout:与cin同理,使用<<输出运算符,
cout << n << db << c << str;
但要注意输出中间没有加空格,因此可以在每个变量之间加上空格
cout << n <<" "<< db << " " << c << " " << str;
对于cout换行除了使用“\n"之外,还可以使用endl来表示换行:
cout << n << “\n” << db << endl;
如果想要控制double精度,则需要在输出之前加上一些东西,同时还要加上头文件:
#include
cout << setiosflags(ios::fixed) << setprecision(2) << 123.4567 << endl; //这个输出的数为123.46
代码如下:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char str[81];
int blank[81]={0}, i=0, j=0; //保存空格的位置
cin.getline(str, 81);
while(str[i]!='\0') {
if(str[i]==' '){
blank[j++]=i;
}
i++;
}
for(int k=j-1; k>=0; k--) {
int temp=blank[k]+1; //表示空格在字符串中的位序
while(str[temp]!='\0') {
printf("%c", str[temp]);
temp++;
}
printf(" ");
str[blank[k]]='\0';
}
printf("%s", str);
return 0;
}
书中还提供了一种更加简单的方式,由于PAT为单点测试,因此当一行字符串结束同时也是文件结束,因此可以考虑通过
while(scanf("%s", str)!=EOF)这种方式来读入一个个单词,并放置在二维字符数组中,读入完毕后逆序输出单词即可
#include <cstdio>
#include <iostream>
using namespace std;
int main() {
int num = 0;
char ans[90][90];
while(scanf("%s", ans[num]) != EOF) {
num++;
}
for(int i=num-1; i>=0; i--) {
printf("%s", ans[i]);
if(i > 0) printf(" ");
}
return 0;
}
如果是正常读入二维数组的话:
char ans[90][90];
for(int i=0; i<len; i++) {
if(str[i]!=' ') {
ans[r][h++]=str[i];
else {
ans[r][h]='\0';
r++;
}
}
B1006换个格式输出整数
#include <cstdio>
int main() {
int n; //表示输入的整数
scanf("%d", &n);
int digit;
if(n/100!=0) {
digit=n/100;
for(int i=0; i<digit; i++) {
printf("B");
}
digit=n%100;
} else {
digit=n;
}
int n_shi=digit;
if(digit/10!=0) {
digit=digit/10;
for(int i=0; i<digit; i++) {
printf("S");
}
digit=n_shi%10;
}
if(digit!=0) {
for(int i=1; i<=digit; i++) {
printf("%d", i);
}
}
return 0;
}
书中做法,将n的所有位数存放在一个一维数组中,然后逆序地一个个遍历数组中的数,逻辑十分清晰
#include <cstdio>
int main() {
int n;
scanf("%d", &n);
int num=0, ans[5]; //num存放n的位数
while(n!=0) {
ans[num]=n%10;
n=n/10;
num++;
}
for(int i=num-1; i>=0; i--) {
if(i==2) {
for(int j=0; j<ans[i]; j++) {
printf("B");
}
} else if(i==1) {
for(int j=0; j<ans[i] ;j++) {
printf("S");
}
} else {
for(int j=1;j<=ans[i]; j++) {
printf("%d", j);
}
}
}
return 0;
}
B1021 个位数统计
已通过OJ
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main() {
char str[1100];
int digit[10]={0}, num=0;
cin.getline(str, 1100);
for(int i=0; str[i]!='\0'; i++) {
num=str[i]-'0';
digit[num]++;
}
int sum=0; //表示digit[]中不为零的项有多少个,便于最后的格式输出
for(int i=0; i<10; i++) {
if(digit[i]!=0) sum++;
}
for(int i=0; i<10; i++) {
if(digit[i]!=0) {
printf("%d:%d", i, digit[i]);
sum--;
if(sum>0) printf("\n");
}
}
return 0;
}
发现书中的代码并没有把最后一行的"\n"去掉,因此可以认为在PAT中,如果题目没有明确要求,是可以末尾换行的,上面的相关代码简化后如下:这样也是可以通过PAT的测试的。
此外,对于字符型的数字,只要将其减去’\0’即可得到,那么同理,将大写字母换成小写字母如’R’-‘A’+‘a’,小写字母换成大写字母如’b’-‘a’+‘A’
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int main() {
char str[1100];
int digit[10]={0}, num=0;
cin.getline(str, 1100);
for(int i=0; str[i]!='\0'; i++) {
num=str[i]-'0';
digit[num]++;
}
for(int i=0; i<10; i++) {
if(digit[i]!=0) {
printf("%d:%d\n", i, digit[i]);
}
}
return 0;
}
B1031查验身份证
发现使用cin.getline输入字符串会出现问题,暂时不知道为何
已通过OJ
#include <cstdio>
#include <iostream>
using namespace std;
int p_sum[17]={7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; //权重
char m[11]={'1','0','X','9','8','7','6','5','4','3','2'}; //对应的校验码
int main() {
int n;
scanf("%d", &n);
int count=0; //表示输入的身份证编码中正确的个数
char str[n][20];
for(int i=0; i<n; i++) {
scanf("%s", str[i]);
int num[20],sum=0, flag=1; //flag为1表示全是数字,为0表示有字母
for(int j=0; j<17; j++) { //把字符数字转化为数字
if(!str[i][j]>='0' && str[i][j]<='9') {
flag=0;break;
} else {
num[j]=str[i][j]-'0';
}
}
if(flag==0) {
str[i][19]='0';
continue;
}
for(int k=0; k<17; k++) { //计算加权总和
sum += num[k]*p_sum[k];
}
int z=sum%11; //计算得到Z
char key=m[z]; //表示校验码
if(key==str[i][17]) {
str[i][19]='1'; count++;
} else {
str[i][19]='0';
}
}
if(count==n) {
printf("All passed\n");
} else {
for(int i=0; i<n; i++) {
if(str[i][19]=='0') {
printf("%s\n", str[i]);
}
}
}
return 0;
}
B1002 写出这个数
#include <cstdio>
#include <cstring>
char pinyin[10][10]={"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
int main() {
int change[200]; //保存字符数字转化为数字之后的结果
char number[200];
scanf("%s", number);
int length=strlen(number);
for(int i=0; i<length; i++) {
change[i]=number[i]-'0';
}
int sum=0; //保存数字之和
for(int i=0 ;i<length; i++) {
sum += change[i];
}
int digits[200], num=0;
do{
digits[num++]=sum%10;
sum/=10;
} while(sum!=0);
for(int i=num-1; i>=0; i--) {
printf("%s", pinyin[digits[i]]);
if(i>0) printf(" ");
}
return 0;
}
B1014 福尔摩斯的约会
有两个测试点没有通过,
问题总结:
1.在写的时候太马虎了,总是把一些不该写错的地方写错,导致调试很久才知道问题在哪里,到目前为止常犯的错误有:==把–写成++,i写成1,,,,,
2.在写if语句的条件时,如果条件太多的话,可以考虑使用if的嵌套,这样代码看起来更加清晰,且逻辑上不容易错。
3.认真,不要马虎,手一抖就能打错字!
#include <cstdio>
#include <cstring>
char week[8][4]={"0","MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
char hour[24]={'0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N'};
bool isbigletter(char a) {
if(a>='A' && a<='Z') {
return true;
} else {
return false;
}
}
bool isletter(char a) {
if((a>='A' && a<='Z')|| (a>='a' && a<='z')) {
return true;
} else {
return false;
}
}
int main() {
char str[4][70];
for(int i=0; i<4; i++) { //输入字符串
scanf("%s", str[i]);
}
int i=0,count=0;
int first, second; //分别表示0,1号字符串中第一个,第二个相同的字母位序
while(str[0][i]!='\0' && str[1][i]!='\0') {
if(isbigletter(str[0][i]) && isbigletter(str[1][i]) && str[0][i]==str[1][i]) {
if(count==0) {
first=i;
i++;
count++;
}else if (count==1) {
second=i;break;
}
} else {
i++;
}
}
for(int i=0; i<24; i++) {
if(str[0][second]==hour[i]) {
second=i;
}
}
i=0;
int minute;
while(str[2][i]!='\0' && str[3][i]!='\0') {
if(isletter(str[2][i]) && isletter(str[3][i]) && str[2][i]==str[3][i]) {
minute=i;break;
}
i++;
}
printf("%s %02d:%02d\n", week[str[0][first]-'A'+1], second, minute);
return 0;
}
以下为参考书中代码修改的部分,上面代码中的主要问题在于自己把第二个相等的字符看成了相等的字母!
已通过OJ
#include <cstdio>
#include <cstring>
char week[8][4]={"0","MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
bool isletter(char a) {
if((a>='A' && a<='Z')|| (a>='a' && a<='z')) {
return true;
} else {
return false;
}
}
int main() {
char str[4][70];
for(int i=0; i<4; i++) { //输入字符串
scanf("%s", str[i]);
}
int i=0,count=0;
int first, second; //分别表示0,1号字符串中第一个,第二个相同的字母位序
while(str[0][i]!='\0' && str[1][i]!='\0') {
if(str[0][i]==str[1][i] && str[0][i]>='A' && str[0][i]<='G') {
first=i;
break;
}
i++;
}
i++;
while(str[0][i]!='\0' && str[1][i] !='\0') {
if(str[0][i]==str[1][i]) {
if(str[0][i]>='0' && str[0][i]<='9') {
second=str[0][i]-'0';
break;
} else if(str[0][i]>='A' && str[0][i]<='N') {
second=str[0][i]-'A'+10;
break;
}
}
i++;
}
i=0;
int minute;
while(str[2][i]!='\0' && str[3][i]!='\0') {
if(isletter(str[2][i]) && isletter(str[3][i]) && str[2][i]==str[3][i]) {
minute=i;break;
}
i++;
}
printf("%s %02d:%02d\n", week[str[0][first]-'A'+1], second, minute);
return 0;
}
B1024 科学记数法
注意:如果PAT报错显示段错误,一般是数组下标越界,要考虑是否要通过增大数组来避免此错误,本题中,自己在写代码的时候一开始取字符串为number[10000],发现报段错误,当把其增加10的时候错误消失。题目要求是说
该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999。
而一个char字符为一个字节,按道理来说取10000应该不会有影响的,但还是报错,因此最好取比9999大一些。另外书中取得也是10010.
以下为代码:已通过OJ
#include <cstdio>
#include <cstring>
int main() {
char number[10010]; //存储要保存的字符串
scanf("%s", number);
int flag_int=1, flag_exp=1; //flag=1表示为正数,-1为负数
char int_doubl[10010]; //存储字符串的整数位和小数位
int_doubl[0]=number[1]; //整数只占一位
char exp[10]; //存储指数位
int i=0;
if(number[0]=='-') {//将number[]分解成几个部分分开转化
flag_int=-1;
printf("-"); //打印负号
}
i=3; //从小数位开始
int k=1;
while(i>2 && number[i]!='E') {
int_doubl[k++]=number[i++];
}
int_doubl[k]='\0';
i++; //E的下一位,即正负号
if(number[i]=='-') flag_exp=-1;
i++;
int j=0;
while(number[i]!='\0') {
exp[j++]=number[i++];
}
exp[j]='\0';
int exp_num[10], expon=0; //表示指数部分的数字
int exp_length=strlen(exp);
for(int i=0; i<exp_length; i++) {
exp_num[i]=exp[i]-'0';
}
int p=1; //表示乘的数字
for(int i=exp_length-1; i>=0; i--) { //计算得到指数
expon += exp_num[i]*p;
p*=10;
}
if(flag_exp==-1) { //表示指数为负的情况
printf("0.");
for(int i=0; i<expon-1; i++) {
printf("0");
}
printf("%c", int_doubl[0]);
for(int i=1; int_doubl[i]!='\0'; i++) {
printf("%c", int_doubl[i]);
}
}
if(flag_exp==1) { //表示指数为正的情况
int dot=strlen(int_doubl)-1; //减去整数位是小数的
printf("%c", int_doubl[0]); //打印整数部分
if(expon>=dot){ //指数多于小数部分
for(int i=1; int_doubl[i]!='\0'; i++) {
printf("%c", int_doubl[i]);
}
for(int i=0; i<expon-dot; i++) {
printf("0");
}
} else {
for(int i=1; i<=expon; i++) {
printf("%c", int_doubl[i]);
}
printf(".");
for(int i=expon+1; int_doubl[i]!='\0'; i++) {
printf("%c", int_doubl[i]);
}
}
}
return 0;
}
B1048 数字加密
问题:有两个测试点没有通过,不知道是什么边界条件没考虑。
原因:是由于忽视了A字符串比B字符串长的情况,这个时候要把B前的字符看成‘0‘,题目都没有说这种情况该怎么写。总之是要把所有的位都要遍历一遍的,且最终结果字符串的长度是A和B中较长的那个的长度。
以下为代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
using namespace std;
int main() {
char a[105], b[105]; //a表示固定数字,b表示要转化得数字
scanf("%s %s", a, b);
int a_length=strlen(a);
int b_length=strlen(b);
int flag=1; //1表示为奇数位,0表示偶数位
int j=b_length-1; //b数字的最后一位,即个位
for(int i=a_length-1; i>=0 && j>=0; i--) {
if(flag==1) { //奇数位处理
int odd=(a[i]+b[j]-2*'0')%13;
char digit_odd;
switch (odd){
case 10:
digit_odd='J';
break;
case 11:
digit_odd='Q';
break;
case 12:
digit_odd='K';
break;
default:digit_odd=odd+'0';
}
b[j]=digit_odd;
flag=0;
j--;
} else { //偶数位处理
int even=b[j]-a[i];
if(even<0) even += 10;
char digit_even;
digit_even=even+'0';
b[j]=digit_even;
flag=1;j--;
}
}
printf("%s", b);
return 0;
}
以下为书中代码:
书中使用了逆序这个函数,这样可以直接一位一位对应做算术,如果不逆序的话,最后的位数可能会出问题!
另外,注意如果刚开始逆序了,最后打印的时候要逆序回去。
#include <cstdio>
#include <cstring>
const int maxn=110;
char A[maxn], B[maxn], ans[maxn]={0};
void reverse(char s[]) {
int len=strlen(s);
for(int i=0; i<len/2; i++) {
int temp=s[i];
s[i]=s[len-1-i];
s[len-1-i]=temp;
}
}
int main() {
scanf("%s %s", A, B);
reverse(A);reverse(B);
int lenA=strlen(A);
int lenB=strlen(B);
int len = lenA> lenB ? lenA:lenB;
for(int i=0; i<len; i++) {
int numA=i < lenA ? A[i]-'0':0;
int numB=i < lenB ? B[i]-'0':0;
if(i % 2==0) {
int temp=(numB+numA)%13;
if(temp==10) ans[i]='J';
else if(temp==11) ans[i]='Q';
else if(temp==12) ans[i]='K';
else ans[i] = temp+'0';
} else {
int temp=numB-numA;
if(temp<0) temp+=10;
ans[i]=temp+'0';
}
}
reverse(ans);
puts(ans);
return 0;
}