第三次集训
如何使用scanf编写出高质量代码
- 使用scanf之前先使用printf提示用户以什么样的方式输出
- scanf中尽量不要使用非输出控制符,尤其是不要使用\n
- 应该编写代码对用户的非法输入做适当处理。
`while ((ch=getchar()) !='\n')`
`continue;`
运算符
-
算术运算符
| +(加) -(减) *(乘) /(除) %(取余)
-
关系运算符
| >(大于) >=(大于等于) <(小于) <=(小于等于) !=(不等于) ==(等于)
-
逻辑运算符
| !(非) &&(并且) ||(或)
-
赋值运算符
| = += *= /= -=
优先级别:算数 > 关系 > 逻辑 > 赋值
除法与取模运算符:
-
除法/的运算结果和运算对象的数据类型有关,两个数都是int,则商就是int,若商为小数,则截取小数部分;被除数和除数中只要有一个或两个都是浮点型数据,则商也是浮点型,不截取小数部分。
- 如:16/5 == 3 16/5.0 == 3.20000 -13/4 == -4
- -13/-3 == -4 3/5 == 0 5/3 == 1
- 最典型的例题就是求 s =1+1/2+1/3+1/4+1/5......+1/100的值
-
取余%的运算对象必须是整数,结果是整数后的余数,其余数的符号只与被除数相同。
- 如: 13%3 == 1 13%-3 == 1 -13%3 == -1
- -13%23 == -13 3%5 == 3
逻辑运算符
C语言对真假的处理:非零既为真,零为假;
&&运算符:当左边的表达式为假时,右边的表达式不执行。
||运算符:当左边的表达式为真时,右边的表达式不执行。
一些琐碎的运算符知识:
自增 自减 三目运算符 逗号运算符
1.自增 [ 或者自减 ]
-
分类:
前自增 —— ++i
后自增 —— i++
-
前自增和后自增的异同:
相同:最终都使i的值加1
不同:前自增整体表达式的值是 i 加 1 之后的值、后自增整体表达式的值是 i 加 1 之前的值
-
为什么会出现自增
1.代码更精炼 。2.自增的速度更快。
-
学习自增要明白的一些问题
-
我们编程时应该尽量屏蔽掉前自增和后自增的差别。
-
自增表达式最好作为一个单独语句使用,不要作为一个完整复合语句的一部分来使用。
如: int m = i++ + ++i + i + i++; //这样写不但是不规范的代码,而且是不可移植的代码。此处涉及到顺序点: ' ( ) ' 和 ' , ' 和 ' ; '。此时不知道i++是否立即生效。
2.三目运算符
格式:
A?B:C
等价于
if (A)
B;
else
C;
3.逗号表达式
格式: (A, B ,C , D)
功能: 从左到右执行,最终表达式的值是最后一项的值。
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
流程控制【重点1】:
-
什么是流程控制
程序代码执行的顺序
-
流程控制的分类
-
顺序
-
选择
-
定义
某些代码可能执行,也可能不执行,有选择的执行某些代码。
-
分类
if
-
if最简单的用法
格式:
if(表达式) 语句;功能:
如果表达式为真,执行语句
如果表达式为假,语句不执行
-
if的范围问题
1).
if(表达式) 语句A; 语句B;解释:if默认只能控制语句A的执行或不执行
if无法控制语句B的执行与否,既语句B一定会执行。
2).
if(表达式) { 语句A; 语句B; }此时if可以控制语句A语句B
由此可见: if默认只能控制一个语句的执行或不执行,如果想要控制多个语句的执行 或不执行,就必须把这些语句用{}括起来。
-
if..else...的用法
-
if..else if...else...的用法
格式:
if(表达式1) 语句A; else if (表达式2) 语句B; else if (表达式3) 语句C; else 语句D; -
C语言对真假的处理
非零为真,零为假
真用以表示,假用零表示
-
if举例--求分数的等级
数学中的表达式:(90<=score<=100)不能在C语言中表示,因为首先会对(90<=score)进行运算,结果为0或1,然后再将0或1与100比较。
程序=算法+语言
-
看懂一个程序的三步
1.流程 2.每个语句的功能 3.试数
如何学习一些需要算法的程序(郝老师的学习方法)
- 尝试自己去解决它,大部分人都自己无法解决。
- 如果解决不了,就看答案。 关键是把答案看懂,这个要花很大的精力,也是学习的重点。
- 看懂之后尝试自己去修改程序,并且知道修改之后程序的不同输出结果的意思。
- 照着答案去敲代码。
- 调试错误。
- 不看答案,自己单独把答案敲出来。
- 如果彻底无法彻底理解,就把它背会。
-
if的常见问题解析
-
空语句的问题
if (3 > 2); //等价于 if (3 > 2) ;//这是一个空语句 -
if(表达式1); 语句A; else 语句B;//这是错误的if(表达式1) 语句A; else ; 语句B;//这是正确的 //等价于 else ; 语句B; -
if(表达式1) 语句A; else if (表达式2) 语句B; -
if(表达式1) 语句A; else if (表达式2) 语句B; else (表达式3) 语句C;//错误,正确写法为去掉 (表达式3)或在else (表达式3)之间加if -
if(表达式1) 语句A; else if (表达式2) 语句B; else (表达式3); 语句C;// 语法正确,但逻辑上是错误的。
-
switch
格式:
-
常变量:const int i;//i只能被赋一个值
楼层程序:
-
#include<stdio.h> int main (void) { int val; printf ("输入您想进入的楼层:"); scanf ("%d",&val); switch (val) { case 1: printf ("1层开!\n"); break; case 2: printf ("2层开!\n"); break; case 3: printf ("3层开!\n"); break; default: printf ("没有盖到这层\n"); break; } return 0; }-
循环
-
定义:
某些代码会被重复执行
-
分类:
for
1.格式:
for(1;2;3) A;2.执行的流程【重点】
(1) for,if的嵌套使用
运行结果:
(2)多个for循环的嵌套使用
for(1;2;3) for(4;5;6) A; B;
3.范围问题
4.举例:
1 + 2 + 3……+ 100
1 +1/2+1/3……+ 1/100
<强制类型转换>
格式:(数据类型)(表达式)
功能:将表达式的值强制转化为前面所执行的数据类型
例子:(int)(4.5+2.2) 最终值为6 (float)(5) 最终值为 5.000000
#include <stdio.h> int main(void) { int i; float sum = 0; for ( i = 1; i <=100; i++) { sum = sum + 1/float(i);//强制转换 //更简单的写法为 sum = sum + 1.0/i; } printf("1+1/2+1/3……+1/100=%f\n",sum);//float必须用%f输出 return 0; }<浮点数的存储带来的问题>
循环中更新的变量不能定义为浮点型
float和double都不能保证可以精确的存储一个小数
举例:
有一个浮点型变量x,如何判断x的值是否为0
if(|x-0.000001|<0.000001) 是零; else 不是零;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
while
-
执行顺序 格式:
while(表达式) 语句;
-
与for的比较
while和for之间可以相互转换,但for的逻辑性更强,更不易出错(推荐多使用)。
- 举例
(1)从键盘输入一个数字,如果该数字是回文数,则返回yes,否则返回no。
-
代码如下:
int main(void)
{
int val;//存放需要判断的数字
int m;
int sum = 0;
printf("请输入您需要判断的数字:");
scanf("%d",&val);
m=val;
while (m)
{
sum = sum * 10 + m%10;
m /=10;
}
if(sum == val)
{
printf("Yes!\n");
}
else
{
printf("No!\n");
}
return 0;
}
缺点:该代码无法判断过长的数是否为回文数。
(2)斐波那契数列
结果如下:
代码如下:
#include <stdio.h>
int main(void)
{
int n,i;
int f1, f2, f3;
f1 = 1;
f2 = 1;
printf("请输入您想要求的序列:");
scanf("%d",&n);
if (1 == n)
{
f3 = 1;
}
else if (2 == n)
{
f3 = 1;
}
else
{
for (i = 3; i<=n; i++)
{
f3 = f1 + f2;
f1 = f2;
f2 = f3;
}
}
printf("%d",f3);
return 0;
}
- 什么时候使用while,什么时候使用for(自行体会)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
do……while
格式:
do
{
语句A;
}while(表达式);
并不等价于while,也不等价于for
主要用于人机交互
一元二次方程
运行结果:
代码如下:
#include <stdio.h>
#include <math.h>
int main(void)
{
double a,b,c;
double x1,x2;
double delta;
char ch;
do
{
printf("请依次输入一元二次方程的三个系数:\n");
printf("a = ");
scanf("%lf",&a);
printf("b = ");
scanf("%lf",&b);
printf("c = ");
scanf("%lf",&c);
delta=b*b-4*a*c;
printf("delta=%lf\n",delta);
if(delta > 0)
{
x1 = (-b + sqrt(delta))/( a * 2);
x2 = (-b - sqrt(delta))/( a * 2);
printf("该方程有两个解, x1 = %lf,x2 = %lf\n",x1,x2);
}
else if(delta==0)
{
x1=(-b)/(2*a);
x2=x1;
printf("该方程有唯一解, x1 = x2 =%lf\n",x1);
}
else
{
printf("无解\n");
}
printf("继续请输入Y,退出请输入其他值:");
scanf(" %c", &ch);//%c之前要加空格(暂不讨论)
}while('y'==ch || 'Y'==ch);
return 0;
}
break和continue
break
1.break如果用于循环是用来终止循环
2.break如果用于switch,则是用于终止switch
3.break不能直接用于if,除非if属于循环内部的语句
#include <stdio.h>
int main(void)
{
int i;
switch (2)
{
case 2:
printf("哈哈哈!\n");
break;
}
for (i=0; i<3; ++i)
{
if (3 > 2)
break;//break虽然是if内部语句,但break终止的是外部for的循环
printf("嘿嘿!\n"); //永远不会输出
}
return 0;
}
4.break用于多个for循环
在多层循环中,break只能终止距离最近的循环。
例子:
#include <stdio.h>
int main(void)
{
int i,j;
for (i=0; i<300; ++i)
{
for ( j = 0; j <4; ++j)
{
break;
}
printf("看网课累啊!\n");
}
return 0;
}
5.在多层switch嵌套中,break只能终止距离它最近的switch
输出结果:
continue
作用:跳过本次循环余下的语句,转去判断是否需要判断下次的循环
for ( 1; 2; 3)
{
A;
B;
contine;//如果执行完该语句后,会执行语句3,C,D都会被跳过去。
C;
D;
}
while (表达式)
{
A;
B;
contine;//如果执行完该语句后,会执行表达式,C,D都会被跳过去。
C;
D;
}
课后习题
C Primer Plus
- 5.10 第七题 第十三题
第七题
打印结果:
第十三题:(该程序无实际意义)
- 5.11 第三题 第八题
第三题:
运行结果:
代码如下:
#include <stdio.h>
int main(void)
{
int day,day_left;
int week;
printf("请输入天数:");
scanf("%d",&day);
week = day / 7;
day_left = day % 7;
printf("%d天 是 %d周, %d天",day,week,day_left);
return 0;
}
第八题:
运行结果:
代码如下:
#include<stdio.h>
int main()
{
int a, b, c, d;
int i=0;
do
{
printf("若要结束请输入非正数。\n");
printf("请输入第%d个整数:",i+=1);
scanf ("%d",&a);
if(!(a > 0))
{break;}
printf("请再次输入1个整数:");
scanf ("%d",&b);
if(!(b > 0))
{break;}
c = b%a;
printf("求模运算的结果为:%d\n",c);
}while (1);
return 0;
}
- 6.16 第五题 第十二题 (计算机二级内容) 第十八题
第五题没想出算法
暂时敲不出来。
第十二题:
代码如下:
#include<stdio.h>
int main()
{
double i,sum1=0,sum2=0,xiang;
int a = 1;
do
{
printf("请输入大于1的项数:");
scanf ("%lf",&xiang) == 1;
if(xiang<=1)
{break;}
for (i = 1.0; i <= xiang; i++,a = 0-a)
{
sum1 += 1.0 / i;
sum2 += a*1.0 / i;
}
printf("sum1 = %lf, sum2 = %lf\n", sum1, sum2);
}while(1);
printf("结束");
return 0;
}
第18题 代码:
#include<stdio.h>
int main()
{
int you;
int i = 1;
for (you = 5; 1; i++)
{
you = 2 * (you - i);
if(you > 150)
{break;}
printf("第 %d 周有 %d 个朋友\n", i, you);
}
return 0;
}
运行结果:
- 7.11 第二题 第十题 第二题语句:
a. number >= 90 && number <100;
b. ch!='q' && ch!='k';
c. number >= 1 && number <= 9 && number != 5;
d. number < 1 || number >9;
第十题(我一开始用了do...while和while的嵌套,频繁使用了break,然后感觉有点问题,所以不贴出了。)
但这里还是给出一个答案:
#include<stdio.h>
int main()
{
char ch;
while ((ch = getchar()) != '#')
{
if (ch != '\n')
{
printf("step 1\n");
if (ch == 'b')
break;
else if (ch != 'c')
{
if (ch != 'h')
printf("step 2\n");
printf("step 3\n");
}
}
}
printf("Done\n");
return 0;
}
图片来源视频:www.bilibili.com/video/BV1os… (如有侵权请在文章下留言。)
第十题代码来源:juejin.cn/post/703451… (以获得授权使用)