一、PTA实验作业
题目1: 400~499 中4出现的次数
1. 本题PTA提交列表
2. 设计思路
一、main函数
- 1.函数声明int fun(int x)
- 2.定义变量i,k,i表示输入的值,k存放4出现次数
- 3.重复以下步骤直到i>499
- 4.调用函数int fun(int x)计算i中k值
- 5.累加k值
- 6.输出k值
二、函数int fun(int x)
- 1.k赋初值0
- 2.当x!=0时,重复下面步骤
- 3.计算个位数字x%10,如果x%10==4,k++
- 4.去除末位数字, x=x/10
- 5.返回k值
3.本题调试过程碰到问题及PTA提交列表情况说明。
k值输出不对
调试
可以很清楚的看到m的值是i的个位数字,也就是说每次取个位数字后去除个位数字的语句没有实现,导致k实际输出的是个位数字为4的数字个数
改正:换do while语句为while语句,调试下看看有没有实现去除个位数字
可以看到这次k记录的数值就对了
小插曲:忽略main函数中的k+=fun(i)语句,看到k数值是1,2觉得没实现累加,利用了静态局部变量来实现对k进行累加,导致输出一个几千的数值。后改正
题目2:使用函数输出水仙花数
1. 本题PTA提交列表
2. 设计思路
一、main函数
- 1.定义整型变量m,n
- 2.输入m,n
- 3.调用函数int narcissistic( number )判断是否为水仙花数
- 4..如果 narcissistic( m )==1,printf("%d is a narcissistic number\n", m)
- 5.如果 narcissistic( n )==1,printf("%d is a narcissistic number\n",n)
- 6.调用函数void PrintN( int m, int n )选出(m,n)中的水仙花数,输出这些水仙花数
二、函数int narcissistic(int number )
- 1.定义整型变量N,i,j,,number1,number2
- 2.给N赋初值0
- 3.定义整型变量sum,存放各个位数的数字的N次方和 ,并赋初值
-
- number1=number,number2=number
- 5.如果number1不为0重复下面步骤
- 6.去个位数: number1=number1/10
- 7.N++,用来表示位数
- 8.i=1,当i小于N的值时,重复下面步骤
- 9.j=number2%10,sum=sum+pow(j,N)
- 10.如果sum==number,返回1,否则,返回0
三、函数void PrintN( int m, int n )
- 1.m++
- 2.当m<n时,重复下面步骤
- 3.如果narcissistic(m)==1,输出这个数
- 4.m++;
3.本题调试过程碰到问题及PTA提交列表情况说明。
错误代码:
#include <stdio.h>
int narcissistic( int number );
void PrintN( int m, int n );
int main()
{
int m, n;
scanf("%d %d", &m, &n);
if ( narcissistic(m) ) printf("%d is a narcissistic number\n", m);
PrintN(m, n);
if ( narcissistic(n) ) printf("%d is a narcissistic number\n", n);
return 0;
}
#include<math.h>
int narcissistic( int number )//调用函数
{
int N,i,j;
int sum=0;
while(number!=0){//如果number不为0执行循环体
j=number%10;//取个位数
N++;//累加N来计算水仙花数位数
number=number/10;//除去个位数得到新的number
}
for(i=1;i<=N;i++){
j=number%10;
number=number/10;
sum=sum+pow(j,N);//计算各个位数的数字的N次方和
}
if(sum==number){//如果各个位数数字N次方和等于这个数
return 1;}//返回1
return 0;//否则返回0
}
void PrintN( int m, int n ){
int number;
for(number==m;number<=n;number++){//当number在(m,n】范围内执行循环体
if( narcissistic(number)==1){//如果为水仙花数
printf("%d\n",number);//输出这个数
}
}
}
运行:
第二个函数没有输出,会不会是没有进入这个函数?
135不是水仙花数,但是也输出了,所以第一个函数调用是不是也有问题。。。。
变成输出m到n所有数了,没有实现判断水仙花数
错误代码:
#include <stdio.h>
int narcissistic( int number );
void PrintN( int m, int n );
int main()
{
int m, n;
scanf("%d %d", &m, &n);
if ( narcissistic(m)) printf("%d is a narcissistic number\n", m);
PrintN(m, n);
if ( narcissistic(n))printf("%d is a narcissistic number\n", n);
return 0;
}
#include<math.h>
int narcissistic( int number )//调用函数
{
int N,j,sum,i;
N=0;
sum=0;
do{//如果number不为0执行循环体
number=number/10;//除去个位数得到新的number
N++;//位数加一
} while(number!=0);
for(i=1;i<=N;i++){
j=number%10;//取个位数
number=number/10;//去除个位数
sum=sum+pow(j,N);//计算各个位数的数字的N次方和
}
if(sum==number)//如果各个位数数字N次方和等于这个数
return 1;//返回1
return 0;//否则返回0
}
void PrintN( int m, int n ){
while(m<n){
if( narcissistic(m)==1){//如果为水仙花数
printf("%d\n",m);}//输出这个数
m++;
}
}
调试:
发现m,n不能输入,还有sum一直为0
错误:忽略了number定义的类型是全局变量,所以在取个位的循环结束后number=0,并且影响到后面出现的number,根据全局变量特点,它们的值都为0了,导致错误
改正:用number1,number2来存放number的值,number1,number2分别用于俩个循环,这样就不改变number的值了
提交:
新错误:运行超时,没有输出
调试:
调试发现掉入循环出不去,仔细观察发现循环条件是number1!=0,而我写成number!=0,导致循环不能结束。
改正后:
不是很明白这个错误,但是知道错误是因为输入范围问题
再次阅读题目,循环起点应该m+1而不是m,在循环开始前执行m++,提交正确
题目3:求组合数
1. 本题PTA提交列表
2. 设计思路
一、main函数
- 1.定义俩个整型变量,m,n
- 2.定义俩个浮点型变量result,表示组合数结果
- 3.调用函数double fact(int n),计算result=fact(n)/(fact(m)*fact(n-m))
- 4.输出result,控制输出位数为0
二、函数double fact(int n)
- 1.定义整型变量i,存放循环次数
- 2.给fact赋初值 double fact=1.0
- 3.当i小于等于n时,重复下面步骤
- 4.fact=fact*i
- 5.i++
- 6.返回fact的值
3.本题调试过程碰到问题及PTA提交列表情况说明。
错误:没有给 fact 赋初值
改正过程:尝试使用double i,double(fact*i)但是运行还是一样的错误,double型乘以int就是double型,错误点不在这。给fact赋值fact=1,运行还是显示这个错误,改为1.0还是不行。错误上面解释是希望输出double型。所以尝试改成double fact==1.0就对了
二、同学代码结对互评
1.同学互评照片。(我、沈梦婷)
2.我的代码、互评同学代码截图
题目6-9 验证哥德巴赫猜想
我的代码:
#include <stdio.h>
#include <math.h>
int prime( int p );
void Goldbach( int n );
int main()
{
int m, n, i, cnt;
scanf("%d %d", &m, &n);
if ( prime(m) != 0 ) printf("%d is a prime number\n", m);
if ( m < 6 ) m = 6;
if ( m%2 ) m++;
cnt = 0;
for( i=m; i<=n; i+=2 ) {
Goldbach(i);
cnt++;
if ( cnt%5 ) printf(", ");
else printf("\n");
}
return 0;
}
int prime( int p ){
int k;
for(k=1;k<=p/2;k++){//如果循环中满足p%k==0,说明这个数不是素数,结束循环
if(p%k==0)
break;
}
if(k>p/2&&p!=1)//如果循环正常结束,满足该条件,就是素数
return 1;
else return 0;
}
void Goldbach( int n ){
int x1,x2;
for(x1=2;x1<n;x1++)
for(x2=2;x2<n;x2++)
if(prime(x1)==1&&prime(x2)==1&&x1<=x2){//调用素数函数判断是否为素数
if(x1+x2==n)//判断是否满足哥德巴赫猜想
printf("%d=%d+%d",n,x1,x2);
break;
}
}
沈梦婷的代码:
#include <stdio.h>
#include <math.h>
int prime( int p );
void Goldbach( int n );
int main()
{
int m, n, i, cnt;
scanf("%d %d", &m, &n);
if ( prime(m) != 0 ) printf("%d is a prime number\n", m);
if ( m < 6 ) m = 6;
if ( m%2 ) m++;
cnt = 0;
for( i=m; i<=n; i+=2 ) {
Goldbach(i);
cnt++;
if ( cnt%5 ) printf(", ");
else printf("\n");
}
return 0;
}
int prime( int p )
{
int i,n;
if(p==1)//判断p为1时不是素数
return 0;
n=sqrt(p);
for(i=2;i<=n;i++){
if(p%i==0){//判断p是否为素数
return 0;
}
}
return 1;
}
void Goldbach( int n )
{
int p,q;
for(p=2;p<=n;p++){
if(prime(p)!=0){//p是素数
q=n-p;//p与q的关系
if(prime(q)!=0){//q是素数
printf("%d=%d+%d",n,p,q);
break;
}
}
}
}
3.我和同学代码不同在哪里?有哪些各自优势?你更喜欢哪种代码风格?如果同学代码有错的也请帮忙指出来哪里出问题。
我预计是通过两个循环,找到满足哥德巴赫猜想的输出,为了找到题目要求的一组就结束,还加了break,但是还是输出所有情况,改了几次也不行,觉得这种方法更适用于穷举。而沈梦婷是通过找到最小的素数后,利用俩个数相加等于n的条件,将另一个数值表示出来,再判断这个数是不是素数,如果是,则验证了哥德巴赫猜想.沈梦婷的代码思路清晰,也简化了很多。相比较我的代码中嵌套循环判断要循环的次数比沈梦婷代码循环次数多很多。所有我更喜欢她的代码。
三、截图本周题目集的PTA最后排名。
四、本周学习总结
1.你学会了什么?
1.1 C语言哪些数据类型?
整型、字符型、实型
1.2 字符型数据需要注意地方?
(1)不仅可以写成字符常量的形式,也可以用相应的ASSCII码表示,即可用整数表示。整数变量和字符型变量是可以互换的
(2)字符具有数值特征,可以像整数一样参加运算
(3)转义字符只代表一个字符
(4)ASCII字符集中所有字符都能用转义字符表示
1.3 自增自减运算符?
(1)使变量的值增1或减1
设n是一个整型变量并已赋值
++n和n++都相当于n=n+1
--n和n--都相当于n=n-1
(2)取变量的值作为表达式的值
++n的运算顺序是:先执行n=n+1,再将n的值作为表达式++n的值
n++的运算顺序是:先将n的值作为表达式n++的值,再执行n=n++
1.4 运算符优先级?
(1)如果操作数两侧的运算符优先级相同,则按结合方向决定计算顺序
(2)运算符优先级从高到低排列:逻辑运算符、算术运算符、关系运算符、逻辑运算符、条件表达式、赋值运算符、逗号运算符
(3)优先级不同则按优先级从高到低计算
1.5 C语言哪些表达式?
算术表达式、赋值表达式、关系表达式、逻辑表达式、条件表达式和逗号表达式
课堂派哪里做错,做错的请在这里分析原因?
(1)int x=1,y=012;
printf("%d",y*x++);
正确答案:10
我的答案:20
分析:++的优先级高于*,x++的值就是x,y是八进制,y=10,所以结果为10
(2)若a为int类型,且其值为3,则执行表达式a+=a-=a*a后,a的值
正确答案:-12
我的答案:-3
分析:a*a优先,所以a-=9.也就是a=a-9.a的值变为-6.所以a+=-6,即a=a-6,所以a=-12
1.6 其他内容?
(1)指定整型数据的输出宽度:%md,若实际位数小于m,则左端补空格,若大于m,则按实际位数输出
(2)double类型指定输出宽度:%m.nf,保留n位小数,输出宽度为m
(3)ch-'a'+'A'把小写字符转换成数字
ch-'0'把数字字符转为数字
val+'0'把数字转换为数字字符
(4)类型转换
1.自动类型转换
2.强制类型转换
2.本周的内容,你还不会什么?
二进制的转换和运算符的优先级顺序记忆不清。以及在PTA中忘记全局变量用于整个程序这一显著特点,导致程序运行中更改了全局变量的值。主要是刚学的知识点不大熟,单拎出来会,放在题目中就忘了,需要一个加深印象的过程吧。
3.循环结构考试总结
1.哪题做错了,怎么改?
第四题没做,第五题错了。
第四题中的二进制,课本上没有,导致拿到题目自我暗示我没学过,肯定不会写。第五题的话还没理出算法,不知道如何写代码。
第四题的话可以先去了解下二进制,然后再做一遍。第五题要认真再想想。。。
2.考试结果满意么,怎么改进?
不满意。多多加强课本上一些比如素数判断这类函数,题目中也挺常见的,太过依赖课本会觉得都懂这些简单函数,但是自己写的时候各种小细节问题就暴露出来了,浪费时间去找错误
3.其他总结。
1.时间不要浪费在简单题上,导致占用过多时间,所以一些常见的函数啊,语句啊,要记熟
2.书本上有提到但是没有详细介绍的知识点要尽快通过查找资料补齐这部分知识,不能拖延,那就真没时间看了。二进制对我来说就是血淋淋的例子
3.查错能力很重要