- C语言学习笔记,记录所学,便于复习。 由于篇幅过大,考虑到观感,准备分多篇记录。
- 学习视频链接:《带你学C带你飞》
- IDE:Clion 2021.1.3
- 前排提醒:建议收藏
一、Hello world,进入C的世界
学习语言,每次都是从Hello world开始,这次也不例外!
printf:格式化输出
#include <stdio.h>
int main()
{
printf("Hello world");
return 0;
}
Hello world
准备好与BUG对抗了吗?
冲呀!
二、变量
命名变量的时候要避开关键词命名。
关键词有以下这些:
三、常量
1、常量的分类
- 整型变量: 110,520
- 实型变量: 3.14,5.21
- 字符常量:
- 普通字符:‘H’,‘E’,‘L’,‘L’,‘O’
- 转义字符:’\n’,’\t’
- 字符串常量:‘HELLO’
- 符号常量: 使用之前必须先定义
列举一些转义字符如下:
转义字符 | 含义 |
---|
\a | 响铃(BEL) | \b | 退格(BS),将当前位置移到前一列 | \f | 换页(FF),将当前位置移到下页开头 | \n | 换行(LF),将当前位置移到下一行开头 | \r | 回车(CR),将当前位置移到本行开头 | \t | 水平制表(HT),移到下一个TAB位置 | \v | 垂直制表(VT) | \ | 表示反斜杠本身(\) | \’ | 表示单引号(’) | \" | 表示双引号(") | \? | 表示问号(?) | \0 | 表示空字符(NULL) | \ddd | 1到3位八进制所代表的任意字符 | \xhh | 1到2位十六进制所代表的任意字符 |
\ 出现在一句的最后,没有加任何东西表示连接下一行内容
2、定义符号常量
(define的作用可以理解为,把程序中出现的标识符替换为后面的常量)
#include <stdio.h>
# define NAME "远方的星"
int main()
{
printf(NAME);
return 0;
}
- 注意:为了将符号常量与普通变量名区分开,用大写字母来代表符号常量,用小写字母来代表变量。
四、数据类型
(不完全统计,后续会补上)
1、基本类型
部分基本类型如下:
数据类型 | 含义 |
---|
char | 字符型,占用一个字节 | int | 整形,通常反应了所用机器中整数的最自然长度 | float | 单精度浮点型 | double | 双精度浮点型 | _Bool | 布尔类型 | enum | 枚举类型 |
#include <stdio.h>
int main()
{
char a;
int b;
float c;
double d;
float f;
a = 'F';
b = 521;
c = 3.14;
d = 3.1415926;
f = 3;
printf("字符:%c\n", a);
printf("神奇密码:%d\n", b);
printf("圆周率:%.2f\n", c);
printf("圆周率:%11.7f\n", d);
printf("注意看小数点后的位数:%.2f\n", f);
return 0;
}
输出:
字符:F
神奇密码:521
圆周率:3.14
圆周率: 3.1415926
注意看小数点后的位数:3.00
- 注意:
c 和f 都是float 数据类型,但是在编写的时候,c出现了警告(不影响输出结果),但是,我还是查了一下警告的内容。
Clang-Tidy: Narrowing conversion from 'double' to 'float'
但是很遗憾,我没有找到相关解释,希望大佬可以解释一下。
2、sizeof运算符
- sizeof运算符用于获得数据类型或表达式的长度(它不是一个函数)
用法:
-
sizeof(object);//sizeof(对象); -
sizeof object;//sizeof(对象); -
sizeof(type_name);//sizeof(数据类型); -
注:当获得对象的长度时,()可以加,也可以不加,但是获得数据类型的长度时,必须加上()。 -
例:
#include <stdio.h>
int main()
{
int i;
char j;
float k;
i = 521;
j = 'H';
k = 3.14;
printf("整型的长度:%d\n", sizeof(int));
printf("i的长度:%d\n", sizeof (i));
printf("字符型的长度:%d\n", sizeof(char ));
printf("j的长度:%d\n", sizeof j);
printf("浮点型的长度:%d\n", sizeof(float ));
printf("k的长度:%d\n", sizeof k);
return 0;
}
在sizeof处的警告(依然不影响输出结果)为:
Format specifies type 'int' but the argument has type 'unsigned long long'
解决方案:
3、类型限定符:signed和unsigned
signed是带符号位的 unsigned是不带符号位的
signed int
unsigned int
定义的时候,signed可写可不写,是默认的。
五、运算符
- C语言运算符优先级:优先级一览表
- 简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
表达式
1、算数运算符
Q:那什么是单目和双目呢?
A:一个符号是双目运算符还是单目运算符,取决于它起作用的有多少个操作数。
如:
- 当“+”取作加号时,1+2,此时,1和2是它起作用的操作数,共两个数,所以此时是双目运算符。
- 当“+”取作正号时,+3,此时3时它起作用的操作数,共一个数,所以此时是单目运算符。
类型转换 当运算符左右两个操作数类型不同时,编译器会将它们共同转换位某种数据类型,通常情况下,会向精度较大的那个类型转化。
#include <stdio.h>
int main()
{
printf("i的计算结果:%d\n", 1 + 2);
printf("j的整型计算结果:%d\n", 1 + 2.0);
printf("j的浮点型计算结果:%f\n", 1 + 2.0);
return 0;
}
i的计算结果:3
j的整型计算结果:0
j的浮点型计算结果:3.000000
当然,也可以进行强制转换,如,将上面的代码改一下:
#include <stdio.h>
int main()
{
printf("j的整型计算结果:%d\n", 1 + (int)2.0);
return 0;
}
输出结果便是:
j的整型计算结果:3
那如果将2.0改成1.5,那结果是不是按照四舍五入的方法转换成整型的呢?
#include <stdio.h>
int main()
{
printf("j的整型计算结果:%d\n", 1 + (int)1.5);
return 0;
}
运算结果是:
j的整型计算结果:2
结果由3变成了2,由此可见,并不是采取四舍五入的方法,而是直接将小数点后面的数字直接置零处理。
2、关系运算符
关系表达式
- 用关系运算符将两边的变量、数据或表达式连接起来,称之为关系表达式。
- 关系表达式会得到一个值,这个值是逻辑值,真或假;C语言用1表示真,用0表示假。
- 例:
#include <stdio.h>
int main()
{
printf("真--运算结果为:%d\n", 1 < 2);
printf("假--运算结果为:%d\n", 1 > 2);
return 0;
}
3、逻辑运算符
- 三种逻辑运算符
逻辑表达式
- 用逻辑运算符将两边的变量、数据或表达式连接起来,称之为逻辑表达式。
- 例:
#include <stdio.h>
int main()
{
printf("第一个运算结果为:%d\n", 1 < 2 && 2 >1);
printf("第二个运算结果为:%d\n", 3 + 1 || 2 == 0);
printf("第三个运算结果为:%d\n", !4);
printf("第四个运算结果为:%d\n", !0 + 1 < 1 || !7);
return 0;
}
第一个运算结果为:1
第二个运算结果为:1
第三个运算结果为:0
第四个运算结果为:0
短路求值
- 短路求值又称最小化求值,是一种逻辑运算符的求值策略。只有当第一个操作数的值无法确定逻辑运算的结果时,才对第二个操作数进行求值。
注:C语言对于逻辑与 和逻辑或 采用短路求值的方式。
#include <stdio.h>
int main()
{
int a = 3, b = 3;
(a = 0) && (b = 5);
printf("a=%d, b=%d\n",a,b);
(a = 1) || (b = 5);
printf("a=%d, b=%d\n",a,b);
return 0;
}
a=0, b=3
a=1, b=3
注意:这里b的值一直没变 ,而a变成了0和1,原因就是C语言中逻辑与和逻辑或采用的是短路求值。
- (a = 0) && (b =5),这个是逻辑与运算,它要求左右两边的结果均为真,它的结果才能为真,但是,如果它左边的结果不为真(因为它的运算方式是从左到右),那么就不会对它的右边进行运算了,所以不会对b进行赋值。
- (a = 1) || (b =5),这个是逻辑或运算,它要求左右两边结果有一个为真就可以了,(它的运算方式也是从左到右),这里,左边a=1已经成立了,就不需要看右边了,所以也不会对b进行赋值。
六、条件语句
1、if语句
框架如下:
if(表达式)
{
}
根据这个基本的语句,可以进一步的拓展
if(表达式1)
{
}
else if(表达式2)
{
}
else if(表达式3)
{
}
...
else if(表达式n)
{
}
else
{
}
注意:当执行的语句只有一句时,{}可省略。
- 例: 到了大学之后,有些课的成绩是以等级评定的。那么我们就用if条件语句来简单写一个分数评级的程序。其中:
90分及以上:优 80~89分:良 70~79分:中 60~69分:及格 60分一下:不及格(需要补考了嗷 )
程序如下:
#include <stdio.h>
int main()
{
int i;
printf("请输入你的分数:");
scanf("%d",&i);
if (i >= 90)
{
printf("你成绩的等级为优!");
}
else if(i >= 80 && i < 90)
{
printf("你的成绩等级为良!");
}
else if(i >= 70 && i < 80)
{
printf("你的成绩等级为中!");
}
else if(i >= 60 && i < 70)
{
printf("你的成绩等级为及格!");
}
else if(i >= 0 && i < 60)
{
printf("很遗憾,你没有及格,请及时补考!");
}
else
{
printf("你输入的成绩不符合规定哟,请重新输出!!!");
}
return 0;
}
请输入你的分数:95
你成绩的等级为优!
本例输入的成绩为95,等级评定正确,小伙伴也可以自己尝试一下,不同的成绩哟。
scanf函数的用法,可参考:C语言scanf函数用法完全攻略
条件运算符 也是C语言中唯一一个三目运算符
exp1是条件表达式 如果为真,返回exp2 如果为假,返回exp3
条件运算符只适合比较简单的语句。
if (a > b)
max = a;
else
max = b;
上述语句用条件运算符来写,即:
max = a >b ? a :b
2、switch语句
框架如下:
switch (表达式)
{
case 常量表达式1: 语句或程序块1
case 常量表达式2: 语句或程序块2
...
case 常量表达式n-1: 语句或程序块n-1
case 常量表达式n: 语句或程序块n
default:语句或程序块n+1
}
当表达式的结果与常量表达式中的结果一致时,则执行想对应的语句或程序块。当没有结果一致时,则执行default中的语句或程序块,如果没有default这部分,则编译器没有任何动作,并不会报错。
- 例: 利用switch对上述例子进行修改。 有时候,老师给的评分是ABCD这类,那我们可以这样实现查看成绩等级。
A:优 B:良 C:中 D:及格
程序如下:
#include <stdio.h>
int main()
{
char i;
printf("请输入你的分数字母等级:");
scanf("%c",&i);
switch (i)
{
case 'A': printf("你的成绩等级是优!\n");break;
case 'B': printf("你的成绩等级是良!\n");break;
case 'C': printf("你的成绩等级是中!\n");break;
case 'D': printf("你的成绩等级是及格!\n");break;
}
return 0;
}
请输入你的分数字母等级:A
你的成绩等级是优!
本例输入的分数字母等级为A,等级评定正确,小伙伴也可以自己尝试一下,不同的成绩哟。
- 注意:细心的小伙伴可能发现,这个程序,比框架中,多了一个break。其实是这样的,break语句,是用来跳出switch语句的。
如果我把break删掉,仍然输入A,让我们来看一下结果:
请输入你的分数字母等级:A
你的成绩等级是优!
你的成绩等级是良!
你的成绩等级是中!
你的成绩等级是及格!
这显然不是我们想要的结果。
3、分支结构的嵌套
也不是很难理解,就是在if语句中嵌套if语句。
直接看例子吧。
(用上面讲的两种也可以实现,但是我们要练习一下嵌套)
程序如下:
#include <stdio.h>
int main()
{
int a, b;
printf("请输入你想比较的两个数(两个数中间用空格分开): ");
scanf("%d %d", &a, &b);
if (a != b)
{
if (a > b)
{
printf("%d > %d\n", a, b);
}
if (a < b)
{
printf("%d < %d\n", a, b);
}
}
else
{
printf("%d = %d\n", a, b);
}
return 0;
}
请输入你想比较的两个数(两个数中间用空格分开):51 15
51 > 15
由此可见,结果正确。分支结构的嵌套是不是也很简单呀~
七、循环语句
1、while语句
框架很简单
while(表达式)
循环体
- 例:计算1+2+…+99+100
想必这个例子大家也非常的熟悉,那如何用while循环来实现呢?
程序如下:
#include <stdio.h>
int main()
{
int i = 1, sum = 0;
while(i <= 100)
{
sum = sum + i;
i = i + 1;
}
printf("计算结果为:%d", sum);
return 0;
}
计算结果为:5050
结果正确!
2、do…while语句
框架为:
do
循环体
while(表达式)
- 与while语句不同的是,while语句是先判断再执行,而do…while语句是先执行再判断。
3、for循环
框架为:
for(表达式1;表达式2;表达式3)
循环体
三个表达式用分号隔开,其中:
- 表达式1是循环初始化表达式
- 表达式2是循环体检表达式
- 表达式3是循环调整表达式
值得一提的是,表达式1,表达式2,表达式3可以按照需要进行省略
(但是分号不能省!!!!)如:
for(;表达式2;表达式3)
for(表达式1;;表达式3)
for(表达式1;;)
for(;;)
而for(;;)和
while(1)
{
...
}
的作用是一样的
#include <stdio.h>
int main()
{
int i = 0;
int count;
for (count = 1;count <= 100;count++)
{
i = i + count;
}
printf("计算结果为:%d", i);
return 0;
}
计算结果为:5050
结果依然是正确的!
- i++和++i是什么意思,有什么区别?
i ++ 是先赋值后加;++ i 是先加后赋值。
用例子来理解一下:
#include <stdio.h>
int main()
{
int i = 5 , j, k;
j = ++i;
printf("++i的计算结果为:%d\n", j);
i = 5;
k = i++;
printf("i++的计算结果为:%d\n", k);
return 0;
}
结果为:
++i的计算结果为:6
i++的计算结果为:5
正好验证了刚刚所说,i ++ 是先赋值后加;++ i 是先加后赋值。
4、循环结构的嵌套
既然有分支结构的嵌套,那循环结构肯定也可以。
程序如下:
#include <stdio.h>
int main()
{
int i , j;
for (i = 1;i <= 9;i++)
{
for (j = 1;j <= i;j++)
{
printf("%d*%d=%d ",i, j, i * j);
}
putchar('\n');
}
return 0;
}
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
putchar()的功能:
- 是向终端输出一个字符
- putchar()语法结构:为 int putchar(int char)
- 功能是把参数 char 指定的字符(一个无符号字符)写入到标准输出 stdout 中,包含在C标准库,包含在C 标准库 <stdio.h>中。
- 其输出可以是一个字符,也可以是用char定义好的一个字符型变量。
八、break语句和continue语句
当 break 关键字用于 while、for 循环时,会终止循环而执行整个循环语句后面的代码 。break 关键字通常和 if 语句一起使用,即满足条件时便跳出循环。
- break如果用于循环是用来终止循环
- break如果用于switch中,则是用来终止switch
- break用在多层循环中,表示退出里他最近的一次循环。
continue 语句的作用是跳过循环体中剩余的语句而强制进入下一次循环 。continue语句只用在 while、for 循环中,常与 if 条件语句一起使用,判断条件是否成立。
例:
#include <stdio.h>
int main()
{
int i, j;
for (i = 0;i < 4;i++)
{
for (j = 0;j < 4;j++)
{
if (j == 1)
{
break;
}
printf("i=%d,j=%d\n", i, j);
}
}
return 0;
}
i=0,j=0
i=1,j=0
i=2,j=0
i=3,j=0
#include <stdio.h>
int main()
{
int i, j;
for (i = 0;i < 4;i++)
{
for (j = 0;j < 4;j++)
{
if (j == 1)
{
continue;
}
printf("i=%d,j=%d\n", i, j);
}
}
return 0;
}
i=0,j=0
i=0,j=2
i=0,j=3
i=1,j=0
i=1,j=2
i=1,j=3
i=2,j=0
i=2,j=2
i=2,j=3
i=3,j=0
i=3,j=2
i=3,j=3
九、未完待续
这一阶段的笔记就先记录到这里,但学C的道路还很漫长。。。
路漫漫其修远兮,吾将上下而求索。
大家一起加油吧!
作者:远方的星 CSDN:https://blog.csdn.net/qq_44921056 本文仅用于交流学习,未经作者允许,禁止转载,更勿做其他用途,违者必究。
|