学习笔记
运算符
|运算符| | | | | | |
-|-|-|-|-|-|- |算数运算符|+(加)|-(减)| *(乘)|/(除)|%(取余数)
|关系运算符|>|>=(大于或等于)|<|<=(小于或等于)|!=(不等于)|==(等于) |逻辑运算符|!(非)|&&(并且)|||(或)
|赋值运算符|=|+=|*=|/=|-=| |自增 / 自减|前自增 -- ++i|后自增 -- i++|--i|i--|
-
除法与取余数运算符:
- 除法的算法结果和运算对象的数据类型有关,两个数都是int时,则商为int,若商有小数,则将截取整数部分;被除数和除数中有一个及以上是浮点型数据时,则商为浮点型,且会保留小数部分。
如: 16 / 5 == 3 , 16 / 5.0 == 3.20000 , -13 / 4 == -4
-13 / -3 == 4 , 3 / 5 == 0 , 5 / 3 == 1 - 取余数%的运算对象
必须是整数,结果是整除后的余数,且符号与被除数相同
如: 13 % 3 == 1 , 13 % -3 == 1 , -13 % 3 == -1 , -13 % 23 == -13 , 3 % 5 ==3
- 除法的算法结果和运算对象的数据类型有关,两个数都是int时,则商为int,若商有小数,则将截取整数部分;被除数和除数中有一个及以上是浮点型数据时,则商为浮点型,且会保留小数部分。
-
逻辑运算符:
!真 -- 假 , !假 -- 真
真&&真 -- 真 , 真&&假 -- 假
假&&真 -- 假 , 假&&假 -- 假
真 || 假 -- 真 , 假 || 真 -- 真
真 || 真 -- 真 , 假 || 假 -- 假- c语言对真假的处理:
- 非零是真,零是假
- 真用1表示,假用0表示
- &&左边的表达式为假时,右边的表达式将不会执行
- ||左边的表达式为真时,右边的表达式也将不会执行
- c语言对真假的处理:
-
赋值运算符:
a += 3 -- a = a + 3 ; a /= 3 -- a = a / 3 -
自增 / 自减:
- 前自增与后自增的异同点:
- 相同:最终都使i加1
- 不同:前自增整体表达式的值是i加1之后的值,后自增整体表达式的值是i加1之前的值
- 为什么会出现自增:
- 代码更精炼
- 自增的速度更快
- 学习自增须知:
- 编程时应尽量屏蔽前后自增的差别
- i++ 与 ++i 单独成一个语句,不要把它作为一个完整复合语句的一部分来使用
如:int m = i++ + ++i + i + i++; 这样写不但是不规范的,而且不可移植,所运行可能会出错(设计到顺序点的知识) (自减与自增同理)
- 前自增与后自增的异同点:
-
三目运算符:
格式:A ? B : C
等价于
if(A)
B;
else
C; -
逗号表达式:
- 格式:(A,B,C,D)
- 功能: 从左到右运行;最终表达式是最后一项的值
运算符的优先级别:算术运算符>关系运算符>逻辑运算符>赋值运算符
遇到优先级问题时,为提高代码的可读性,尽量使用括号,不要写出有歧义的代码。一行代码不要出现多个自增自减符号,这会被视作垃圾代码。
流程控制
- 什么是流程控制:
流程控制是指程序代码执行的程序 - 流程控制的分类:
- 顺序执行
- 选择执行
- 定义:某些代码可能执行,也可能不执行,有选择的执行某些代码
- 分类:
if:- if最简单的用法
格式:
if(表达式)
语句;
功能:如果表达式为真,则执行语句,为假则不执行。 - if的范围问题
if默认只能控制一个语句的执行或不执行
如果要控制多个语句,则需用{}将需要控制的语句括起来 - if...else...
- if...else if...else...
在运行if...else...或者if...else if...else语句时,若if与else之间有多个语句,一定要用括号将这些括起来,否则将会出错 - c语言对真假的处理
- 非零是真,0是假
- 真用1表示,假用0表示
- if的常见问题解析
- 空语句的问题:
if (3 > 2); 等价于:
if (3 > 2)
; 这是一个空语句 - if与else后均不需添加分号; else后面添加分号或者if语句以else if结尾,语法不会出错,但是逻辑上是错误的。
- if(表达式)
A;
else if (表达式)
B; else
C;
即便表达式1,2都成立,也只会执行A语句。 switch:
- 空语句的问题:
- 格式:
switch
{
case 常量表达式1: 语句1;
case 常量表达式2: 语句2;
default : 语句3;
} - 所有case后面的常量表达式为便于描述我们姑且称之为标签,这些标签只能是枚举变量,数值变量,字符变量,常变量,宏名中的一种
- switch后面括号里的表达式允许是任何类型(vc++中只允许为int或char)
- switch中不能出现continue,除非其属于for或while的一部分
- if最简单的用法
格式:
- 循环执行
定义:某些代码会被重复执行
分类:
1.for语句
- 格式:
for(1;2;3)
语句A;
for语句中循环条件用分号;隔开,而不用逗号 - 执行的流程:123A32A3循环运行
- 范围与if相近,默认只控制一个语句的执行或不执行,控制多个语句需用{}将所需控制语句括起来
- 多个for循环的嵌套使用:
for(1;2;3) //1
for(4;5;6) //2
A; //3
B; //4
整体是两个语句,1 2 3是第一个语句 , 4是第二个语句
2.while语句
- while和for可以相互转化,但for的逻辑性更强,更不容易出错,推荐多使用for
3.do while语句
- 格式:
do
{
.....
}while(表达式); - do...while不等价于for以及while
- 主要用于人机的交互
*break语句
- break如果用于循环则用来终止循环;如果用于switch则用来终止switch
- break不能直接用于if,除非if属于循环内部的一个子句
- break只能终止距离它最近的一个循环
continue语句
- 用于跳过本次循环余下的语句,转去判断是否需要执行下次循环
for (1;2;3)
{
A;
B;
continue; //如果执行该语句,则执行完该语句后,将会执行语句3,C和D都会被跳过,不会被执行
C;
D;
}
*浮点数的存储所带来的问题 - float和double都不能保证可以精确的存储一个小数
举例:有一个浮点型变量x,如何判断x的值是否为0?
if (x和一个非常小的值差的绝对值小于这个数)
是0;
else
不是0;
*看懂并掌握一个程序:
*强制类型转化
- 格式:(数据类型)(表达式)如:1 / (float)(i)
- 功能:把表达式的值强制转化为前面所执行的数据类型
- 举例: (int)(4.5+2.2),最终值为6
(float)(5.0),最终值为5.000000
代码实操
测试取余数运算符:
#include<stdio.h>
int main()
{
printf("%d %d %d %d %d %d\n", 3%3, 13%-3, -13%3, -13%-3, -13%23, 3%5);
return 0;
}
运行结果:
由输出结果易知:取余%的运算对象必须为整数,结果是整除后的余数,且符号与被除数相同
&&的使用:
#include<stdio.h>
int main()
{
int i = 10;
int k = 20;
int m;
int n;
m = (1>2) && (k=5);
n = (3>2) || (i=8);
printf("m = %d, n = %d, i = %d, k = %d\n", m, n, i, k);
return 0;
}
运行结果:
结论:
0表示假,1表示真
&&左边的表达式为假时,右边的表达式将不会执行
||左边的表达式为真时,右边的表达式也将不会执行
前自增与后自增的比较:
#include<stdio.h>
int main()
{
int i;
int j;
int k;
int m;
i = j = 3;
k = i++;
m = ++j;
printf("i = %d, j = %d, k = %d, m = %d\n", i, j, k, m);
return 0;
}
结论:前自增整体表达式的值是i加1之后的值,后自增整体表达式的值是i加1之前的值
三目运算符:
#include<stdio.h>
int main()
{
int i;
i = (3>2 ? 5 : 1);
printf("%d\n",i);
return 0;
}
//i = (3>2 ? 5 : 1);等价于 if(3>2)
// i = 5;
// else
// i = 1;
运行结果:
逗号表达式:
#include<stdio.h>
int main()
{
int i;
int j = 2;
i = (j++, ++j, j+2, j-3);//j+2不等价j = j+2
printf("%d\n",i);
return 0;
}
运行结果:
结论:逗号表达式从左到右运行;最终表达式是最后一项的值
if最简单的用法:
#include<stdio.h>
int main()
{
if (1)
printf("a\n");
if (0)
printf("b\n");
if (0 == 0)
printf("c\n");
return 0;
}
运行结果:
结论:if语句中,如果表达式为真,则执行语句,为假则不执行。
if举例 -- 求分数的等级:
#include<stdio.h>
int main()
{
float score;
printf("请输入你的成绩:");
scanf ("%f", &score);
if (score > 100)
printf("这是做梦!\n");
else if (score <= 100 && score >= 90)//不能写成90<=score<=100
printf("优秀!\n");
else if (score <= 90 && score >= 80)
printf("良好\n");
else if (score <= 80 && score >= 60)
printf("及格\n");
else
printf("不及格,继续努力\n");
return 0;
}
运行结果:
互换两个数字&比较三个数字的大小:
#include<stdio.h>
int main()
{
int a, b, c;
int t; //定义一个临时变量
printf("请输入三个整数(中间以空格分隔)");
scanf("%d %d %d",&a, &b, &c);
if (a < b)
{
t = a;
a = b;
b = t; //互换a b
}
else if (a < c)
{
t = a;
a = c;
c = t;
}
else if (b < c)
{
t = b;
b = c;
c = t;
}
printf("%d %d %d", a, b, c);
return 0;
}
运行结果:
for语句循环:
#include<stdio.h>
int main()
{
int i;
int sum = 0;
for (i = 1; i <= 10; i++)
sum = sum + i;
printf("sum = %d\n",sum);
return 0;
}
运行结果:
选择循环语句程序设计:
#include<stdio.h>
int main()
{
int i;
int sum1 = 0;
int sum2 = 0; //sum1表示奇数之和,sum2表示偶数之和
float avg1,avg2;
for (i = 1; i <= 100; i++)
{
if (i%2 == 1)
sum1 = sum1 + i;
else if (i%2 == 0)
sum2 = sum2 + i;
}
avg1 = 2*sum1 / (i + 1);
avg2 = 2*sum2 / i; //avg1表示100以内奇数的平均数,avg2表示100以内偶数的平均数
printf("sum1 = %d, sum2 = %d, avg1 = %f, avg2 = %f\n", sum1, sum2, avg1, avg2);
return 0;
}
运行结果:
判断回文数:
#include<stdio.h>
int main()
{
int m;
int sum = 0;
int val;
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;
}
运行结果:
原理:利用while语句(括号中不为0时循环进行,为0时停止输出)依步运行进行取余等运算将所需判断数倒过来,再与原来的数对比是否相等从而判断是否为回文数。
用do...while语句实现多个一元二次方程的运算:
# include<stdio.h>
# include<math.h>
int main(void)
{
double a, b, c;
double delta;
double x1,x2;
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;
if (delta > 0)
{
x1 = (-b + sqrt(delta)) / (2*a);
x2 = (-b - sqrt(delta)) / (2*a);
printf("该一元二次方程有两个解,x1 = %lf,x2 = %lf\n",x1,x2);
}
else if (delta == 0)
{
x1 = (-b + sqrt(delta)) / (2*a);
x2 = x1;
printf("该一元二次方程有唯一解,x1 = x2 = %lf\n",x1);
}
else
{
printf("无解\n");
}
printf("是否继续(Y/N):");
scanf(" %c", &ch); //%c前面必须加一个空格
}while('y' == ch || 'Y' == ch);
return 0;
}
运行结果:
课后习题
5.10
第7题: 输出结果如图
第13题:
a. x -= 1;
b. m = n % k;
c. p = q / (b - a);
d. x = (a + b) / (c * d);
5.11
第3题:
#include<stdio.h>
int main()
{
int a, b, c;
do
{
printf("请输入天数:");
scanf("%d",&a);
b = a%7;
c = a/7;
printf("%d days are %d weeks, %d days\n",a, c, b);
}while (a > 0);
return 0;
}
第8题:
#include<stdio.h>
int main()
{
int a, b, c, d;
printf("请输入第一个整数:");
scanf ("%d",&a);
do
{
printf("请再次输入一个整数:");
scanf ("%d",&b);
c = b%a;
printf("%d\n",c);
}while (b > 0);
return 0;
}
6.16
第5题:实在是不会写,但是有对着答案敲了一遍
第12题:
#include<stdio.h>
int main()
{
double times, i; //times为项数
printf("请输入项数:");
`while ((scanf ("%lf",×) == 1) && (times > 0))` //此句有参考答案
{
int a = 1;
double sum1 = 0, sum2 = 0; //sum1为第一个序列的和,sum2为第二个序列的和
for (i = 1.0; i <= times; i++,a = 0-a)
{
sum1 += 1.0 / i;
sum2 += a*1.0 / i;
}
printf("sum1 = %lf, sum2 = %lf", sum1, sum2);
}
printf("结束");
return 0;
}
结论:第一个序列不收敛,第二个序列收敛于0.7
第18题:
#include<stdio.h>
int main()
{
int friends;
int i = 1;
for (friends = 5; friends < 150; i++)
{
friends = 2 * (friends - i);
printf("第 %d 周有 %d 个朋友\n", i, friends);
}
return 0;
}
7.11
第2题:
a. number >= 90 && number <100;
b. ch!='q' && ch!='k';
c. number >= 1 && number <= 9 && number != 5;
d. number < 1 || number >9
第10题:
***
#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;
}