Lazy loaded image
技术分享
4️⃣C语言学习笔记
00 min
2024-9-18
2025-1-22
summary
type
status
date
slug
tags
category
文件和媒体
文本
icon
password

变量定义

变量是一个保存数据的地方,当需要在程序中保存数据时,比如上面例子中要记录用户输入的价格,就需要一个变量来保存它,用一个变量保存了数据,它才能参加到后面的计算中,比如计算找零
变量定义的一般形式就是<类型名称><变量名字>;
一行可以定义多个变量,用逗号隔开,分号代表结束
变量需要名字,是一种标识符,意思它是用来区分不同的名字,标识符基本原则是只用用字母、数字、下划线组成,数字不能出现在第一个位置,C语言的关键字也不能用来做标识符

变量赋值和初始化

price=0是一个式子,这里的=是一个赋值运算符,表示将=右边的值赋给左边的变量
<类型名称><变量名称>=<初始值>
所以的变量在使用之前必须定义或声明,所有的变量必须具有确定的数据类型,数据类型表示在变量中可以存放什么样的数据,变量中只能存放指定类型的数据,程序运行过程中也不能改变变量的类型

常量和变量

不变的量是常量,是直接写在程序里的
定义一个常量:const int AMOUNT=100;
const是修饰符,加在int前面,用来给这个变量加上一个(不变的)的属性。这个const表示这个变量的值一旦初始化,就不能再修改,一般const后面的常量需要是大写

浮点数

整数运算的结果只有整数部分,不然就要用浮点数
带小数点的数值叫浮点数
当浮点数和整数放在一起运算时,C就会将整数转换为浮点数,然后进行浮点数的运算,%d要改成%f
如果把int换成double,就可以把变量改成double类型的浮点数变量了;double本来是双精度浮点数的第一个单词,表示浮点数类型,除了double,还有float(浮点)表示单精度浮点数
用double时,输入时要把%d改成%lf
数据类型:
整数
带小数点的数
int
double
printf(”%d”,…)
printf(”%f”,…)
scanf(”%d”,&…)
scanf(”%lf”,&…)

表达式

运算符是指进行运算的动作,比如加法运算符”+“,减法运算符”-“
算子是指参与运算的值,这个值可能是常数,也可能是变量,还可能是一个方法的返回值
取余计算%
hour1*60+minute1 ——>转换为分钟为单位
t/60 ——>小时部分;t%60 ——>分钟
程序就是数据计算

运算符的优先级

优先级
运算符
运算
结合关系
举例
1
+
单目不变
自左向右
a*+b
1
-
单目取负
自右向左
a*-b
2
*
自左向右
a*b
2
/
自左向右
a/b
%
取余
自左向右
a%b
3
+
自左向右
a+b
3
-
自左向右
a-b
4
=
赋值
自右向左
a=b
有一个算子的运算符就是单目运算,两个算子就是双目运算
赋值也是运算符
a=b=6 ——>a=(b=6)

交换变量

程序表达的是顺序执行的动作,而不是关系
a=6 b=5
t=a
a=b
b=t
提供一个地方存放东西:t

复合赋值和递增递减

5个算术运算符可以和赋值运算符=结合起来,形成复合赋值运算符
+
+=
-
-=
*
*=
/
/=
%
%=
total+=5
total=total+5
注意两个运算符中间不要有空格
total+=(sum+100)/2
total=total+(sum+100)/2
 
total*sum+12
total=total*(sum+12)
 
“++”和1”--”是单目运算符,这个算子还必须是变量。他们分别叫递增和递减运算符,作用是给这个变量+1或-1
count++
count+=1
count=count+1
前缀后缀
++和--放在变量的前面,叫做前缀形式,放在变量后面叫做后缀形式
a++的值是a加1以前的值,++a的值是加了1以后的值,无论哪个,a自己的值都加了1
表达式
运算
表达式的值
count++
给count加1
count原来的值
++count
给count加1
count+1以后的值
count--
给count减1
count原来的值
--count
给count减1
count-1以后的值
可以单独使用,但是不要组合进表达式

做判断:if语句根据条件决定做还是不做

if(条件成立){
……
}
如果条件成立,就做这件事情,如果不成立,就不做这件事情

判断的条件

条件
计算两个值之间的关系,所以叫做关系运算
运算符
意义
==
相等
!=
不相等
>
大于
>=
大于或等于
<
小于
<=
小于或等于
关系运算的结果
当两个值的关系符合关系运算符的预期时,关系运算的结果为整数1,否则为整数0
表达式
结果
printf(”%d”,5==3
0
printf(”%d”,5>3)
1
printf(”%d”,5<=3)
0
优先级
所有的关系运算符的优先级比算术运算的低,但是比赋值运算的高
判断是否相等的==和!=的优先级比其他的低,而连续的关系运算是从左到右进行的

实例:找零计算器、年龄计算

notion image

notion image

 

if如果条件不成立,否则

如果if后面还有语句,它们在if结束后会执行,无论条件如何
我们可以在if后面跟上一个else
else=否则的话
notion image

 

if语句2

一个基本的if语句由一个关键字if开头,跟上在括号里的一个表示条件的逻辑表达式,然后是一对大括号”{}“之间的若干条语句。如果表示条件的逻辑表达式的结果不是个零,那么就执行后面跟着的这对大括号中的语句,否则就跳过这些语句不执行,而继续下面的其他语句
if语句还有另外一种形式,就是可以没有后面的大括号
if语句这一行结束的时候并没有表示语句结束的“;”,而后面的赋值语句写在if的下一行,并且缩进了,在这一行结束的时候有一个表示语句结束的”;”。这表明这条赋值语句是if语句的一部分,if语句拥有和控制这条赋值语句,决定它是否要被执行。
else同理

 

循环

写程序写的不是关系,不是说明,而是步骤!
/*如果我们把while翻译成“当 ”,那么一个while循环的意思就是:当条件满足时,不断地循环重复循环体内的语句。 循环执行之前判断是否继续循环,所以有可能循环一次也没有被执行

while循环

notion image
数位数的算法:
1.用户输入x;
2.初始化n为0;
3.x=x/10,去掉个位;
4.n++;
6.如果x>0,回到3;
6.否则n就是结果。
if和while的区别仅仅在于一次性还是反复多次的做,后者包括反复多次的判断条件
循环体内要有改变条件的机会,否则会出不来
如果把while循环翻译为“当”,那么一个while循环的意思就是:当条件满足时,不断地重复循环体内的语句
循环执行之前判断是否继续循环,所以有可能循环一次也没有被执行
条件成立是循环继续的条件

do-while

先做循环内的句子
在进入循环的时候不做检查,而是在执行完一轮循环体的代码之后,再来检查循环的条件是否满足,如果满足则继续下一轮循环,不满足则结束循环
notion image
结束语句要么是大括号要么是分号
do-while循环和while循环很像,区别是在循环体执行结束的时候才来判断条件。也就是说,无论如何循环都会至少一遍,然后再来判断条件。与while循环相同的是,条件满足时执行循环,条件不满足时结束循环

for循环

阶乘
n!=1x2x3x4x……xn
4!=1x2x3x4=24
notion image
for循环 像一个计数循环:设定一个计数器,初始化它,然后计数器到达某值之前,重复执行循环体,而每执行一轮循环,计数器值以一定步骤进行调整,比如加1或者减1 for=对于 for(count=10;count>0;count--) 就读成:“对于一开始的count=10,当count>0时,重复做循环体,每一轮循环在做完循环体内语句后,使得count--。” 小套路 :做求和的程序时,记录结果的变量应该初始化0,而做求积的变量时,记录结果的变量应该初始化为1 C99循环控制变量i只在循环里被使用,在循环外没有如何用处,所以可以把变量i的定义写到for语句里面 for(int i=1)

循环的选择

for(i=0;i<n;i++) 则循环的次数时n,而循环结束以后,i的值是n。循环的控制变量i,是选择从0开始还是从1开始, 是判断i<n还是判断i<=n,对循环的次数和循环结束后变量的值都有影响
for(初始动作;条件;每轮的动作){ } for中的每一个表达式都是可以省略的for(;条件;)==while(条件)
Tips 如果有固定次数,用for 如果必须执行一次,用do while 其他情况用while

逻辑类型

bool:
#include<stdbool.h>
之后就可以使用bool和true、false

 

逻辑运算

 
运算符
描述
示例
结果
逻辑非
!a
如果a是true结果就是false,如果a是false结果就是true
&&
逻辑与
a&&b
如果a和b都是ture,结果就是true;否则就是false
||
逻辑或
a||b
如果a和b有一个是true,结果为true;两个都是false,结果为false
如果要表达4<x<6,应该x>4&&x<6,因为4<x的结果是一个逻辑值(0或1)
理解:
age>20&&age<30
index<0||index>99
!age<20会先算!age,然后就两个结合在一起,比如age如果是0,那么!age就会变成1,如果是1就变零,永远小于20,如果想不小于20,就要加括号
逻辑运算符普遍低于比较运算符,!是单目运算符,单目运算符高于双目运算符
优先级:
!>&&>||
!done&&(count>MAX):!done会先算,如果count>MAX并且done是0,那么整个结果才会是1
优先级
运算符
结合性
1
()
从左到右
2
! + - ++ --
从右到左(单目的+和-)
3
* / %
从左到右
4
+ -
从左到右
5
< <= > >=
从左到右
6
== !=
从左到右
7
&&
从左到右
8
||
从左到右
9
= += -= *= /= %=
从右到左
赋值永远是最低的
 
短数:
逻辑运算是自左向右进行的,如果左边的结果已经能够决定结果了,就不会做右边的计算
a==6&&b==1
a==6&&b+=1
对于&&,左边是false时就不做右边了
对于||,左边时true时就不做右边了
不要把赋值,复合赋值组合进表达式里

条件运算

notion image
条件运算符的优先级高于赋值运算符,但是低于其他所有运算符

逗号运算符

逗号用来连接两个表达式,并以它右边的表达式的值作为它的结果,逗号的优先级是所有运算符中最低的,所以它两边的的表达式会先计算;逗号的组合关系是自左向右,所以左边的表达式会先算,而右边的表达式的值就会留下来作为逗号运算的结果
逗号主要在for中使用,如:
for(i,j=10;i<j;i++,j--)………

嵌套的if-else

当if的条件满足或不满足的时候要执行的语句也可以是一条if或if-else语句,这就是嵌套的i语句
else一般会和最近的if匹配,如果加了大括号,则根据大括号匹配,缩进格式不能暗示else的匹配
tips
在if或else后面总用{}大括号
即使只有一条语句的时候

级联的if-else


多路分支

switch-case

如果输入的3给到了type,那么就会直接跳到case 3,不用像else-if一个一个做判断。然后break把运行带到了return。
switch表达式必须是int类型:只能是整数型的结果
常量可以是常数,也可以是常数计算的表达式
switch语句可以看作是一种基于计算的跳转,计算控制表达式的值后,程序会跳转到相应的case(分支标号)的地方,分支标号只是说明switch内部位置的路标,在执行完分支中的最后一条语句后就,如果后面没有break,就会按顺序执行下面的case,直到遇到一个break或者switch结束为止。
/取整 %取余

计算循环

tips:
如果要模拟运行一个很大次数的循环,可以模拟较小的循环次数,然后推断
如果某个变量要做累加,那么一般初始值为0
如果某个变量要做除法,那么可以根据终点给判断值

 

循环算平均数

让用户输入一系列的正整数,最后输入-1表示输入结束,然后程序计算出这些数字的平均数,输入输出的数字的个数和平均数
首先需要有三个变量:
一个记录读到的整数的变量,这里用number
一个计算平均数的变量,每读到一个数,就把它加到一个累加的变量里去,这里用sum
一个用来储存平均数个数的变量,这里用count
一个变量计数累加的结果,一个记录读到的数的个数,到全部数据读完,再拿sum去除count读到的数的个数
算法:
notion image
算法:
1.初始化变量sum和count为0;
2.读入number
3.如果number不是-1,就将number加入到sum,并将count加1,回到步骤2
4.如果numbr是-1,那就计算和打印出sum/count(注意要换成浮点数计算

猜数字

1.计算机随机想一个数,记在变量number里
2.一个负责记录次数的变量count初始化为0
  1. 用用户输入一个数字a
4.count递增(加1)
5.判断a和number的大小关系,如果a大,就输出“大”;如果a小就输出“小”
6.如果a和number是不相等的(无论大还是小),程序转回到第3步
7.否则,程序输出“猜中”和次数,然后结束
随机数:
每次召唤rand()就得到一个随机的整数
因为要进入循环,让用户输入一个数,然后在循环结束的时候再判断是否继续循环,所以do while更合适

整数求逆

整数的分解:
整数是由1至多位数字组成
对一个数字做%10的操作,就得到它的个位数
对于一个整数做/10的操作,就去掉了它的个位数
然后再对2的结果做%10,就得到原来数的十位数了
以此类推
数的逆序:
输入一个正整数,输出逆序的数

if常见错误

错误1:忘记加大括号
养成好习惯,永远在if、else……后面加大括号,哪怕只有一个语句
 
错误2:if后面的分号
分号即代表结束,哪怕里面没有内容,空白也代表内容,c语言会认为if里面也有一条语句了,分号下面大括号的内容就变成普通语句,跟if就没有关系了。所以if、else后面不要加分号
 
错误3:错误使用==和=
if只要求()里的值是零或非零
只敲了一个等号就是赋值,赋值是表达式,只会把b给a,而不会判断a和b是否相等
尊重warning:根据warning解决问题
0对于if来说条件不成立
 
错误3:代码风格
在if和else之后必须加上大括号形成语句块
大括号内的语句缩进一个tab的位置

循环控制

素数:只能被1和自己整除的数,不包括1
2,3,5,7,9,11,13,15,17,19
break:跳出循环
continue:跳出循环这一轮剩下的语句进入下一轮
notion image

嵌套的循环

循环里面还是循环,可以是for和for的嵌套也可以是for和while的嵌套,没有任何关系,不用特别去理解,当你需要嵌套的时候就放个嵌套进去,需要注意的是:两重循环里面的控制变量不能是一样的,如果是一样的就会混淆,比如第一个循环初始值是x=2,里面的循环的变量就要是i=2
找出100以内的素数
找出前50个的素数

从嵌套的循环中跳出

break只能跳出其所在的循环
break和continue只能对它所在的那层循环做
exit:接力break:
goto:
goto的后面要跟一个标号,比如out。第二个标号要有冒号结尾,上面代码的意思是满足条件就跳到out的位置去

前n项求和

notion image
注意因为有分数,所以用浮点数,可用double也可用float
加减n项求和:
notion image
加sign使分子不断从正负转换达到加减n项求和的目的

整数分解

正序分解整数
此处以x为123为例
开始int定义了一个x,用于存放用户输入的数,然后定义变量mask初始值为1,再下一行将x的值赋给变量t,当t(也就是用户给的值)大于9时,t/10等于12,mask*10变成10,继续while循环,t现在是12仍大于9,t/10等于1,mask10*10等于10,进入下一步输出x=123(注意123不是t,x一直没动过)输出mask等于00,进入下一步do while定义d等于123/100等于1,输出1,if判断mask100大于9,输出空格,然后123取余100等于23,mask100/10等于10,进入while循环判断条件,mask10大于0,继续循环do,d等于23/10等于2,输出2,if判断mask10大于9,输出空格。x23%10等于3,mask10/10等于1,满足while循环条件,继续do,d等于3/1等于3,输出3。if判断条件不满足,不再输出空格。后面的取余和除已经不重要了,while循环条件也不满足,至此结束
x=123
123/100 →1
123%100 →23
100/10 →10
23/10 →2
23%10 →3
10/10 →1
3/1 →3
3%1 →3
1/10 →0

求最大公约数

枚举
1.设t为2
2如果u和v都能被t整除,则记下这个t
3.t加1后重复第2步,直到t等于u或v
  1. 曾经记下的最大的可以同时整除u和v的t就是gcd(最大公约数)
此处以a4,b2为例
开始定义了a和b,用于保存用户输入的参数。定义了min,用于存放最小参数那个常量a或b,if判断如果a小于b,那么最小数min就是a,else否则b就是最小的,这里a是4,b是2,所以最小的是b。定义ret初始值为0,ret用来保存最大公约数。定义i。进入for循环,i初始值为1;如果i小于等于最小的min(a和b其中一个),则进行for循环内的动作,每次进入循环时i加1,现在i是1,min是b(b的值是2),所以满足i<=min的条件,进入if判断条件,4%1=0,满足条件进入下一个if判断条件2取余1同样能整除,下一步把i的值也就是1赋给ret。继续for循环,直到不满足条件为止。满足条件,进入for循环,i+1=2,如果满足a取余2能整除的条件(已满足),进入下一个循环满足2取余2能整除的条件,把i(2)赋予ret。继续for循环,满足2小于等于2,i加1=3,如果4取余3能整除则满足条件,这里不满足,结束循环,进入printf输出
 
辗转相除法
1.如果b等于0,计算计算,a就是最大公约数
  1. 否则,计算a除以b的余数,让a等于b,而b等于哪个余数
  1. 回到第一步
此处以a4,b2为例
只讲解while部分,进入while循环,当b不等于0时,开始循环,现在b是2,满足条件,下一步将4取余2等于2的值赋值给t,将2赋值给a,将t(2)赋值给b,重复循环直到b等于0,循环结束
上一篇
EMPTY-ARTICLE
下一篇
海风C学习笔记