C语言学习笔记
一些在学习C语言过程中做的笔记
课程链接:程序设计入门——C语言
出现在
scanf()
中的东西是程序希望你输入的东西 而不是程序将要输出的东西const
是一个修饰符,加在int
的前面,用来给这个变量增加一个 不变 ( const )的属性。这个 const 的属性一旦被初始化就不能再修改了。示例:
const int AMOUNT = 100; int change = AMOUNT - price;
任意一个整数做加减乘除,结果依然是整数。这是一段示例代码:
#include<stdio.h> int main(){ printf("%d",10/3); return 0; }
这段代码的输出将是
3
而不是3.333333....
如果想要得到
3.33333333...
的输出,那么代码应该修改为:#include<stdio.h> int main(){ printf("%f",10.0/3); return 0; }
在C中,
10
与10.0
是完全不同的两个数10
是整数 ,10.0
是浮点数。浮点数就是带小数点的数值。浮点这个词的本意就是指小数点是浮动的,是计算机内部表达非整数(包含分数和无理数)的一种方式。另一种方式叫做定点数,不过在C语言中你不会遇到定点数。人们借用浮点数这个词来表达所有的带小数点的数。
当浮点数和整数放到一起运算时,C会将整数转换成浮点数,然后进行浮点数的运算。
整数
int
printf("%d",...);
scanf("%d",...);
浮点数
double
printf("&f",...);
scanf("&lf",...);
表达式 是一系列运算符和算子的组合,用来计算一个值。
运算符(operator)是指进行运算的动作,比如加法运算符“+”,减法运算符“-”。
算子(operand)是指参与运算的值,这个值可能是常数,也可能是变量,还可能是一个方法的返回值
例如一个表达式:
a = b + 5
在这个式子中,“ = ” 和 “ + ” 是运算符,a、b、5 是算子
四则运算 C符号 意义 + + 加 - - 减 × * 乘 ÷ / 除 % 取余 () () 括号 如下是一段计算时间差的代码,用到了第8点的四则运算。
#include<stdio.h> int main(){ int hour1,minute1; int hour2,minute2; printf("请输入较早的时间(小时 分钟):"); scanf("%d %d",&hour1,&minute1); printf("请输入较晚的时间(小时 分钟):"); scanf("%d %d",&hour2,&minute2); int t1 = hour1 * 60 + minute1; // 转换为分钟单位 int t2 = hour2 * 60 + minute2; //如上 int t = t2 - t1; printf("时间差是%d小时%d分钟。",t/60,t%60); // t/60是小时部分,t%60是分钟部分 return 0; }
运算符优先级
优先级 运算符 运算 结合关系 举例 1 + 单目不变 自右向左 a*(+b) 1 - 单目取负 自右向左 a*(-b) 2 * 乘 自左向右 a*b 2 / 除 自左向右 a/b 2 % 取余 自左向右 a%b 3 + 加 自左向右 a+b 3 - 减 自左向右 a-b 4 = 赋值 自右向左 a=b 在
a+b
中,运算符 = 的两边有两个算子,说明这是双目运算像
-a
这样运算符两边只有一个算子的叫做单目运算对于C语言来说,赋值(=)也是一个运算符
- 赋值也是运算,也有结果
a=6
的结果是a被赋予的值,也就是6a=b=6
–>a=(b=6)
不推荐使用 嵌套式赋值。示例:
int a =6; int b; int c = 1+(b=a);
result = (result = result * 2) * 6 * (result = 3 + result);
- 不利于阅读
- 容易出错
这种表达式太复杂,不利于阅读和理解,容易造成读程序时的误解。所以要避免写出这样的复杂表达式。这个表达式应该被拆成若干个表达式,然后以明显的正确的顺序来进行计算。
程序表达的是顺序执行的动作,而不是关系。
复合赋值
- 5个算数运算符(+ - * / %)可以和赋值运算符(=)结合起来,形成复合赋值运算符。
+=
-=
*=
/=
%=
total += 5
等价于total = total + 5
- 两个运算符中间不要有空格
递增/递减运算符
- “++”和“–”是两个很特殊的运算符,它们是单目运算符。这个算子必须是变量。
- 这两个运算符分别叫做递增和递减运算符,他们的作用就是给这个变量+1或者 -1。
- 下面三个表达式都是等价的:
count++
;count += 1;
count = count + 1;
++和–可以放在变量的前面,叫做前缀形式;也可以放在变量的后面,叫做后缀形式。
++i
,--i
(在使用 i 之前,先使 i 加(减)1);i++
,i--
(在使用 i 之后,使 i 的值加(减)1)。乍一看,
++i
和i++
的作用相当于i=i+1
。但是++i
和i++
的不同之处在于++i
是先执行i=i+1
后,再使用 i 的值;而i++
是先使用 i 的值之后,再执行i=i+1
。可以这么理解记忆:自增自减都是从左往右运算的,那么
i++
就应该是先用i
的值,再去给它自身+1;以此类推,++i
就应该是先给它自身+1,再去使用i
的值。表达式 运算 表达式的值 count++ 给count加1 count原来的值 ++count 给count加1 count加1后的值 count– 给count减1 count原来的值 –count 给count减1 count减1后的值 根据比较的结果,决定做、还是不做某些动作,就要用到if语句。
一个基本的if语句由一个关键字if开头,跟上在括号里的一个表示条件的逻辑表达式,然后是一对大括号“{}”之间的若干条语句。如果表示条件的逻辑表达式的结果为true,那么就执行后面跟着的这对大括号中的语句,否则就跳过这些语句不执行,而继续下面的其他语句。
关系运算符
运算符 意义 == 相等 != 不相等 > 大于 >= 大于等于 < 小于 <= 小于等于 关系运算的结果
- 当两个值的关系复合关系运算符的预期时,关系运算的结果为整数1,否则为整数0。
printf("%d\n",5==3);
会打印0
printf("%d\n",5>3);
会打印1
printf("%d\n",5<=3);
会打印0
关系运算符的优先级:
所有的关系运算符的优先级比算术运算符的低,但是比赋值运算的高。
例如
7 >= 3 + 4
,+
比>=
的优先级高,所以在这个表达式中先计算3+4
再比较7 >= 3 + 4
通过这段代码可以验证是否先算 算数运算符,后算 关系运算符。
#include<stdio.h> int main(){ printf("%d",7>=3+4); return 0; }
- 编译运行后,结果为 `1`。说明 **关系运算符的优先级比算术运算符的低**。 判断是否相等的 **==** 和 **!=** 的优先级比其他的关系运算符的低,而连续的关系运算是从左到右进行的。 - `5 > 3 == 6 > 4` 输出为 `1` - `6 > 5 > 4 ` 输出为 `0` 因为是先算`6 > 5` ,结果是 `1`,然后算 `1 > 4` 结果为 `0` - (两条示例分别印证了上面 <span class="heimu" title="悲">上面。。上面的什么呢 想不出来(悲</span> 23. **注释** 注释(comment)插入在程序代码中,用来向读者提供解释信息。它们对于程序的功能没有任何影响,但是往往能使得程序更容易被人类读者理解。 可用: - `//` \***C99独有** - `/* */` - 延续数行的注释,要用多行注释的格式来写。 - 多行注释由一对字符序列 `/*` 开始,而以 `*/` 结束。也可以用于一行内的注释。 - `int ak=47 /*36*/ ,y=9;` - 单行注释 **C99独有** 24. 在C语言中,每个语句通常以分号(;)结束。但是,如果你使用了**大括号** `{}` 来创建一个代码块,那么块内的最后一个语句后面的分号**是可选的**。这是因为大括号**定义了一个语句块,它本身就是一条语句**,所以不需要在块的末尾加分号。 25. 一个基本的if语句由一个关键字 `if` 开头,跟上在括号里的一个表示条件的逻辑表达式,然后是一对大括号“{}”之间的若干条语句。 如果表示条件的逻辑表达式的结果不是零,那么就执行后面跟着的这对大括号中的语句,否则就跳过这些语句不执行,而继续下面的其他语句。 示例: ```c #include<stdio.h> int main(){ if (xxxx){ xxxxxxx; // 这一句是if语句的一部分 } else { xxxxxxx; // 这一句是else语句的一部分 } return 0; }
if语句这一行结束的时候并没有表示语句结束的
;
,而后面的赋值语句写在if的下一行,并且缩进了,在这一行结束的时候有一个表示语句结束的;
。这表明这条赋值语句是if语句的一部分,if语句拥有和控制这条赋值语句,决定它是否要被执行。示例:
#include<stdio.h> int main(){ if (xxxx) xxxxxxxx; // 这一句是if语句的一部分 else xxxxxxx; // 这一句是else语句的一部分 return 0; }
while
循环就和if
一样,条件满足就不断做后面的句子。while
循环的流程图:循环体内要有改变条件的机会,否则就会一直进行循环。
如果我们把while翻译作“当”,那么一个while循环的意思就是:当条件满足时,不断地重复循环体内的语句。
循环执行之前判断是否继续循环,所以有可能循环一次也没有被执行
条件成立 是循环继续的条件。
我们可以通过在程序的适当位置插入
printf()
来查看各个变量的值而不使用调试。例如下面的代码:#include <stdio.h> int main() { int x ; int n = 0; x = 3000; while ( x > 0 ) { n++; x /= 10; printf("x=%d,n=%d\n", x, n); } printf("位数为%d位。\n", n); return 0; }
do-while循环 : 在进入循环的时候不做检查,而是在执行完一轮循环体的代码之后,再来检查循环的条件是否满足,如果满足则继续下一轮循环,不满足则结束循环。
流程图如下:
do-while其实就是,不管你条件成不成立,先做循环内的句子,再去判断条件是否成立
do-while循环和while循环很像,区别是在 循环体执行结束的时候才来判断条件。也就是说,无论如何,循环 都会执行至少一遍,然后再来判断条件。与while循环相同的是,条件满足时执行循环,条件不满足时结束循环。
格式:
do { xxxxxxx; } while ( 条件 ); // 注意要加分号
for 循环 :
for ( 初始动作 ; 循环条件 ; 每轮循环要做的动作 ){ xxxxxxx; }
for循环像一个计数循环:设定一个计数器,初始化它,然后在计数器到达某值之前,重复执行循环体,而每执行一轮循环,计数器值以一定步进进行调整,比如加1或者减1
例如
for ( i=0; i<= 10; i++ ){ // ^初始化 ^循环条件 ^ 每轮循环要做的动作 printf("%d",i); }
for可以理解为 对于。比如说,对于以下代码
for ( count=10; count>0; count-- )
可以理解为
对于一开始的 count=10,当 count>0 时,重复做循环体,每一轮循环在做完循环体内语句后,使得 count– 。”
判断或循环后面都必须跟一个循环体。
做 求和 的程序时,记录结果的变量应该初始化为 0,而做 求积 的变量时,记录结果的变量应该初始化为 1
for循环其实是等价于while循环的。例如:
int i = 1; while (i<=5){ fact *= i; i++; }
等价于
for ( int i=1; i<=5; i++){ // [int i=1] 这一段仅适用于C99 fact *= i; }
任何一个for循环都可以改写为一个while循环。
以C语言为例,标准的
for
循环是这样的:for (初始化表达式; 循环条件表达式; 迭代表达式) { // 循环体 }
- 初始化表达式:通常用于 初始化一个或多个循环控制变量 ,这个表达式只在循环开始前执行一次。
- 循环条件表达式:在每次迭代的开始处进行评估,如果为真,则执行循环体中的代码;如果为假,则循环结束。
- 迭代表达式:在循环体的代码执行之后,对循环控制变量进行更新。
在某些情况下,这三个表达式都是可以省略的,但至少需要保留分号分隔符。例如:
int i = 0; for (; i < 10; ) { // 循环体 i++; // 循环体内需要确保循环条件最终会变为假,否则会形成无限循环 }
在上面的例子中,初始化表达式被移动到了循环外,而迭代表达式在循环体内完成。
但是,如果 省略了循环条件表达式 ,默认的条件是 真 ,这会导致一个 无限循环 ,除非在循环体内部有
break
语句或者修改循环控制变量来退出循环:int i = 0; for (;;) { // 这将创建一个无限循环 if (i >= 10) { break; // 使用break语句来退出循环 } // 循环体 i++; }
此条来自于 ChatGLM
三种循环的流程图: