2018年3月底的PTA(二)
C高级第二次PTA作业(1)
题目6-7 删除字符串中数字字符
1.设计思路
为了偷懒,本题算法和流程图是精简代码后的,具体请看本题实验代码的第二段代码。
(1)算法(子函数)
第一步:定义子函数类型void、名delnum,形参字符指针型s。
第二步:整数i(用作循环变量),整数j(用来做新的字符数组的下标),将0赋给i,将0赋给j。
第三步:若地址s+i中的字符为结束符则跳到第四步,否则下一步。
第四步:若地址s+i中的字符在0到9之间则i+1赋给i,跳到上一步,否则地址s+i中的字符赋给地址s+j中的字符,j+1赋给j,跳到上一步。
第五步:结束符赋给地址s+j中的字符。
(2)流程图
2.实验代码
#include "stdio.h"
void delnum(char *s);
int main ()
{
char item[80];
gets(item);
delnum(item);
printf("%s\n",item);
return 0;
}
void delnum(char *s)
{
char strings[80];
short int j=0;
for(short int i=0;*(s+i)!='\0';i++)
if(*(s+i)<='9'&&*(s+i)>='0')
continue;
else
{
*(strings+j)=*(s+i);
j++;
}
strings[j]='\0';
for(short int i=0;i<j;i++)
*(s+i)=*(strings+i);
*(s+j)='\0';
}
本题做完后突然发现可以再精简,代码如下:
void delnum(char *s)
{
short int j=0;
for(short int i=0;*(s+i)!='\0';i++)
if(*(s+i)<='9'&&*(s+i)>='0')
continue;
else
{
*(s+j)=*(s+i);
j++;
}
*(s+j)='\0';
}
3.本题调试过程碰到问题及解决办法
错误信息1:
错误原因:在第一个for循环中判断数字字符时漏掉了一个0,用非法的语句直接将字符数组名赋给字符数组名,当然直接把字符数组赋给间接访问数组首元素地址和把间接访问字符数组赋给间接访问字符数组也不行(试过了)。
改正方法:把漏掉的0补上,用循环将不是数字的字符一个一个赋给原字符数组s。
错误信息2:
错误原因:因为原字符数组的长度超过去除数字字符的字符串,多余的原字符串对应多余下标的字符还在。
改正方法:在去除数字字符的字符串最后加上结束符。
题目6-8 统计子串在母串出现的次数
1.设计思路
(1)算法(子函数)
第一步:定义子函数类型整型,名fun,形参字符指针型str、substr。
第二步:整数i、j、count,0分别赋给i、j、count。
第三步:若地址str+i中的字符为结束符则返回count,否则下一步。
第四步:若地址substr+j中的字符为结束符则跳到下一步,否则跳到第七步。
第五步:若地址substr+j中字符为结束符则count+1赋给count,否则不执行,然后0赋给j。
第六步:i+1赋给i,跳到第三步。
第七步:若地址str+i中的字符等于地址substr+j中的字符则i+1赋给i。
第八步:j+1赋给j,跳到第四步。
(2)流程图
2.实验代码
#include<stdio.h>
int fun(char *str,char *substr);
int main()
{
char str[81]="asdasasdfgasdaszx67asdmklo",substr[4]="asd";
int n;
n=fun(str,substr);
printf("n=%d\n",n);
return 0;
}
int fun(char *str,char *substr)
{
short int j=0,count=0;
for(short int i=0;*(str+i)!='\0';i++)
{
for(j=0;*(substr+j)!='\0';j++)
if(*(str+i)==*(substr+j))
i++;
else
break;
if(*(substr+j)=='\0')
count++;
}
return count;
}
3.本题调试过程碰到问题及解决办法
错误信息1:
错误原因:第一个for循环中判断的字符数组的地址错误。
改正方法:地址改成最后一个结束符的地址substr+j。
错误信息2:
错误原因:j定义在第二个for循环中,只在第二个for循环中能用,是局部变量,在第一个for循环中并没有定义j。
改正方法:在for循环外定义一个变量j。
本题在完成后发现有一个非智力因素的错误,在j作循环变量的循环中,循环条件出错了,但实际并没有影响到程序的运行,所以程序并没有报错,具体错误可在错误信息截图中查看,实验代码中已改。
题目6-9 字符串中除首尾字符外的其余字符外按降序排列
1.设计思路
(1)算法(子函数)
第一步:定义子函数类型整型,名fun,形参字符指针型s,整型num。
第二步:整数i、j、k,1赋给i。
第三步:若i小于num-2则返回主函数,否则i赋给k,i+1赋给j。
第四步:若j小于num-2则交换(s+k)和(s+i),i+1赋给i,跳到上一步,否则下一步。
第五步:若(s+k)小于(s+j)则j赋给k,否则不执行,然后j+1赋给j,跳到第三步。
(2)流程图
略
2.实验代码
#include <stdio.h>
int fun(char *s,int num);
int main()
{
char s[10];
gets(s);
fun(s,7);
printf("%s",s);
return 0;
}
int fun(char *s,int num)
{
for(short int i=1;i<num-2;i++)
{
short int k=i,swap;
for(short int j=i+1;j<num-1;j++)
if(*(s+k)<*(s+j))
k=j;
swap=*(s+k);
*(s+k)=*(s+i);
*(s+i)=swap;
}
}
3.本题调试过程碰到问题及解决办法
错误信息:
错误原因:没看懂题目中传递的参数num是什么意思,num的意思是降序排列字符数组中的前num个元素除首尾,第一个for循环中的最后一个交换语句出现非智力错误,直接把地址s+k的字符赋给了地址s+i中的字符。
改正方法:第一个for循环条件不等号右边改成num-2,除掉第num-1个元素,第二个for循环条件右边改成num-1.去掉第num个元素。
题目7-1 输出学生成绩
1.设计思路
(1)算法
第一步:定义整数N,输入N。
第二步:申请动态内存,名grade,强制转换动态内存为整型指针型,大小为N个整型变量长度。
第三步:若grade等于空则不执行,否则下一步。
第四步:定义单精度型-1赋给max、101赋给min、0赋给sum,整数0赋给i。
第五步:若i大于等于N则输出average = sum除以N的值换行max = max的值换行min = min的值(保留两位小数),释放grade动态内存,否则下一步。
第六步:输入地址grade+I中的值,若max小于地址grade+i中的值则地址grade+i中的值赋给max,否则不执行,若min大于地址grade+i中的值则地址grade+i中的值赋给min,否则不执行。
第七步:sum+地址grade+I中的值的和赋给sum,i+1赋给i,跳到第五步。
(2)流程图
略
2.实验代码
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
void main()
{
short int N;
scanf("%d\n",&N);
short int *grade=(int *)malloc(N*sizeof(short int));
if(grade!=NULL)
{
float max=-1,min=101,sum=0;
for(short int i=0;i<N;i++)
{
scanf("%d",grade+i);
if(max<*(grade+i))
max=*(grade+i);
if(min>*(grade+i))
min=*(grade+i);
sum+=*(grade+i);
}
printf("average = %.2f\nmax = %.2f\nmin = %.2f\n",sum/N,max,min);
free(grade);
}
system("pause");
}
3.本题调试过程碰到问题及解决办法
错误信息1:
错误原因:空字符小写不能用,释放动态内存时指针变量标错。
改正方法:空字符改大写NULL,释放动态内存free的指针变量改成自己代码定义的grade。
错误信息2:
错误原因:最小值min初始值设置了-1已经是最小了,导致for循环中怎么比较都是-1最小,所以答案错误。
改正方法:最小值min初始值设置为101。
C高级第二次PTA作业(2)
题目7-1 计算职工工资
1.设计思路
(1)算法
第一步:定义结构名Staffinformation,结构中的变量字符数组name,单精度baespay、fluctuatingwages、expenses、actualwages。
第二步:定义整数N,结构变量s,输入N,0赋给整数i。
第三步:若i小于N则下一步,否则结束。
第四步:输入name、basepay、fluctuatingwages、expenses。
第五步:actualwages等于basepay加fluctuatingwages减expenses。
第六步:输出name、actualwages,i+1赋给i,跳到第三步。
(2)流程图
2.实验代码
#include <stdio.h>
#include <stdlib.h>
struct Staffinformation
{
char name[10];float basepay;
float fluctuatingwages;float expenses;
float actualwages;
};
void main()
{
signed short int N;
scanf("%d",&N);
struct Staffinformation s;
for(signed short int i=0;i<N;i++)
{
scanf("%s %f %f %f\n",s.name,&s.basepay,&s.fluctuatingwages,&s.expenses);
s.actualwages=s.basepay+s.fluctuatingwages-s.expenses;
printf("%s %.2f\n",s.name,s.actualwages);
}
system("pause");
}
3.本题调试过程碰到问题及解决办法
错误信息1:
错误原因:变量只能有下划线字符数字组成,在定义结构时变量名有空格。
改正方法:把空格去掉。
错误信息2:
错误原因:用数组做的,但是PTA不通过。
改正方法:直接把数组去掉换成一个变量s。
提交列表:
题目7-2 计算平均成绩
1.设计思路
(1)算法
第一步:定义全局结构,名student,结构内的变量长度为6的字符串number,长度为10的字符串name,整型grade。
第二步:定义整数N,0赋给整数sum,0赋给整数i,输入整数N。
第三步:定义student结构长度为N数组变量名infor。
第四步:若i小于N则下一步,否则输出转换浮点数sum处以N的值(保留两位小数),0赋给i,跳到第六步。
第五步:分别输入到第i+1个结构变量内的变量number、name、grade,sum加第i+1个结构变量内的变量grade赋给sum,i+1赋给i,跳到第四步。
第六步:若i小于N则下一步,否则结束。
第七步:若转换浮点数sum处以N的值大于结构中第i+1个grade则输出结构数据中第i+1个name、number,否则不执行。
第八步:i+1赋给i,跳到第六步。
(2)流程图
略
2.实验代码
#include <stdio.h>
#include <stdlib.h>
struct student
{
char number[6];char name[10];
int grade;
};
void main()
{
int N,sum=0;
scanf("%d",&N);
struct student infor[N];
for(signed short int i=0;i<N;i++)
{
scanf("%s %s %d\n",infor[i].number,infor[i].name,&infor[i].grade);
sum+=infor[i].grade;
}
printf("%.2f\n",sum/N*1.0f);
for(signed short int i=0;i<N;i++)
if(sum/N*1.0f>infor[i].grade)
printf("%s %s\n",infor[i].name,infor[i].number);
system("pause");
}
3.本题调试过程碰到问题及解决办法
本题编译错误:略
错误信息1:
错误原因:在定义结构内的变量时为了节省空间,将grade和sum定义成了短整型,导致这道题目输入的时候值太大超出短整型范围。
改正方法:将短整型改成整型。
错误信息2:
错误原因:定义结构内的学号变量number时,没考虑到结束符也占一个字符。
改正方法:学号变量的范围加一。
本题学生名字的长度要求是小于10,10对了只是凑巧,并不是在做题目的时候想到的。
提交列表:
C高级第二次PTA作业(3)
题目6-1 按等级统计学生成绩
1.设计思路
(1)算法(子函数)
第一步:定义整型子函数名set_grade,形参结构名student指针p,整型n。
第二步:定义整数0赋给count,0赋给整数i。
第三步:若i小于n则下一步,否则返回count。
第四步:若地址p+i指向的结构内的变量score在85-100之间则A赋给地址p+i指向的结构内的变量grade,i+1赋给i,跳到第三步,否则下一步。
第五步:若地址p+i指向的结构内的变量score在70-84之间则B赋给地址p+i指向的结构内的变量grade,i+1赋给i,跳到第三步,否则下一步。
第六步:若地址p+i指向的结构内的变量score在60-69之间则C赋给地址p+i指向的结构内的变量grade,i+1赋给i,跳到第三步,否则下一步。
第七步:若地址p+i指向的结构内的变量score在0-59之间则D赋给地址p+i指向的结构内的变量grade,count+1赋给count,i+1赋给i,跳到第三步。
(2)流程图
2.实验代码
#include <stdio.h>
#define MAXN 10
struct student
{
int num;char name[20];
int score;char grade;
};
int set_grade( struct student *p, int n );
int main()
{
struct student stu[MAXN], *ptr;
int n, i, count;
ptr = stu;
scanf("%d\n", &n);
for(i = 0; i < n; i++)
scanf("%d%s%d", &stu[i].num, stu[i].name, &stu[i].score);
count = set_grade(ptr, n);
printf("The count for failed (<60): %d\n", count);
printf("The grades:\n");
for(i = 0; i < n; i++)
printf("%d %s %c\n", stu[i].num, stu[i].name, stu[i].grade);
return 0;
}
int set_grade(struct student *p,int n)
{
short int count=0;
for(signed short int i=0;i<n;i++)
if((p+i)->score>=85&&(p+i)->score<=100)
(p+i)->grade='A';
else if((p+i)->score>=70&&(p+i)->score<=84)
(p+i)->grade='B';
else if((p+i)->score>=60&&(p+i)->score<=69)
(p+i)->grade='C';
else
{
(p+i)->grade='D';
count++;
}
return count;
}
3.本题调试过程碰到问题及解决办法
错误信息:
错误原因:访问结构指针对应的结构内的变量时,结构指针的用法错误,还在以前的习惯上。
改正方法:直接使用地址,不需要间接访问,将间接访问符号和括号去掉,并使用指向箭头->,指向结构内的变量score、grade。
提交列表:
题目6-2 结构体数组按总分排序
1.设计思路
(1)算法(子函数)
第一步:定义子函数类型void、名calc,形参结构student指针型p、整型n。
第二步:定义整数循环变量0赋给i。
第三步:若i小于n则0赋给地址p+i中的结构内的变量sum,0赋给整型循环变量j,跳到下一步,否则返回主函数。
第四步:若j<3则地址p+i中的结构内的变量sum加地址p+i中的结构内的变量score赋给地址p+i中的结构内的sum,j+1赋给j,跳到第四步,否则i+1赋给i,跳到上一步。
第一步:定义子函数类型void、名calc,形参结构student指针型p、整型n。
第二步:0赋给整型循环变量i。
第三步:若i小于n-1则下一步,否则返回主函数。
第四步:i赋给整数k,i+1赋给整型循环变量j。
第五步:若j小于n则下一步,否则交换结构数组中第i+1个元素和第k+1元素,i+1赋给i,跳到第三步。
第六步:若地址p+k中的结构内变量sum小于地址p+i中的结构内变量sum则j赋给k,否则不执行。
第七步:j+1赋给j,跳到第五步。
(2)流程图
略
2.实验代码
#include <stdio.h>
struct student
{
int num;
char name[15];
float score[3];
float sum;
};
void calc(struct student *p,int n);
void sort(struct student *p,int n);
int main()
{
struct student stu[5];
int i,j;
float f;
for(i=0;i<5;i++)
{
scanf("%d%s",&stu[i].num,stu[i].name);
for(j=0;j<3;j++)
{
scanf("%f",&f);
stu[i].score[j]=f;
}
}
calc(stu,5);
sort(stu,5);
for(i=0;i<5;i++)
{
printf("%5d%15s",stu[i].num,stu[i].name);
printf(" %.1f %.1f %.1f %.1f\n",stu[i].score[0],stu[i].score[1],stu[i].score[2], stu[i].sum);
}
return 0;
}
void calc(struct student *p,int n)
{
for(signed short int i=0;i<n;i++)
{
(p+i)->sum=0;
for(signed int j=0;j<3;j++)
(p+i)->sum+=(p+i)->score[j];
}
}
void sort(struct student *p,int n)
{
for(signed short int i=0;i<n-1;i++)
{
short int k=i;
for(signed short int j=i+1;j<n;j++)
if((p+k)->sum<(p+j)->sum)
k=j;
struct student swap=p[k];
p[k]=p[i];
p[i]=swap;
}
}
3.本题调试过程碰到问题及解决办法
错误信息1:
错误原因:选择法排序交换时只交换了结构student中的sum的值,题目要求是交换学生的所有信息,并且sum是单精度型,想当然的设置成了整型。
改正方法:交换变量定义成结构中的student型,实现整个结构变量的交换。
错误信息2:
错误原因:交换赋值时将值赋给一个式子,这在C语言中是不合法的。
改正方法:更换成合法的数组名加下标的形式。
本题直接将循环变量定义成结构变量的地址也可以实现,代码懒得呈现了。
提交列表:
学习总结和进度
总结知识点和错误:
本次学习了结构的定义和使用、结构变量的定义和使用、结构数组的定义和使用、动态内存的定义和使用,在写代码的过程中发现信息交换时都是整体交换不是单方面的交换,而且经常出一些上学期的低级错误,比如等式左边是不能赋值给式子,局部变量的使用范围经常使用不在范围内的局部变量,字符数组要多定义一个结束符的长度,动态内存的定义和使用还是不熟练。
GitHub地址:
评论博客地址:
学习进度表格和折线图
日期 | 代码时间 | 代码行数 | 博客时间 | 博客字数 |
---|---|---|---|---|
3月26日 | 0 | 0 | 16 | 160 |
3月27日 | 51 | 24 | 72 | 543 |
3月28日 | 19 | 9 | 67 | 342 |
3月29日 | 44 | 34 | 67 | 199 |
3月30日 | 0 | 0 | 0 | 0 |
3月31日 | 0 | 0 | 0 | 0 |
4月1日 | 24 | 17 | 0 | 0 |
4月2日 | 12 | 13 | 50 | 549 |
4月3日 | 30 | 14 | 47 | 45 |
4月4日 | 0 | 0 | 0 | 0 |
4月5日 | 0 | 0 | 0 | 0 |
4月6日 | 0 | 0 | 0 | 0 |
4月7日 | 0 | 0 | 77 | 203 |
4月8日 | 0 | 0 | 0 | 0 |
4月9日 | 0 | 0 | 0 | 0 |