C语言
浅谈C语言入门
计算机和编程语言
计算机
现在我们见到的计算机(电脑),都是由硬件部分和软件部分组成
- 硬件部分:运算器、控制器、存储器、输入设备和输出设备。
- 软件部分:分为系统软件和应用软件。
如果把计算机比喻为一个人的话,那么硬件就表示人的身躯,而软件则表示人的思想、灵魂。二者相互依存,缺一不可,共同构成一个完整的计算机系统。
编程语言
- 程序就是用特殊的编程语言告诉计算机如何做一件事,计算机能懂的只有二进制,如果我们需要让计算机去做一件事,就需要先找出计算的步骤,计算的步骤即算法,而计算机做的事情就是计算。
- 首先,把表示计算步骤的程序和计算中需要的原始数据,在控制器输入命令的控制下,通过输入设备送入计算机的存储器存储。其次当计算开始时,在取指令作用下把程序指令送入控制器。控制器对指令进行译码,在经过运算器计算并把结果存放在存储器内。在控制器的取数和输出命令作用下,最后通过输出设备输出计算结果。
为什么要学习算法
人在计算的时候会有各种各样的方式,例如明朝时万户上天,亚历山大斩断绳索之类,但对于计算机来说,他们的智慧并不高,正如其名只是具有极高的计算能力,它们更喜欢枚举,枚举的缺陷就是在大量数据面前极其缓慢,所以为了使其计算的更快,所以我们需要设计算法。
解释与编译
解释:借助某个程序,由这个程序读懂你的程序,按照你所设定的步骤执行。
- 这个程序会一条一条的执行你的源代码
编译:借助某个程序,由这个程序把你的程序翻译成计算机能懂的语言(机器语言),由计算机执行。
- 这个程序相当于一个翻译,会一次将你的所有源代码翻译成机器代码,然后再去执行这个机器代码。
如何看待解释语言与编译语言
- 语言并无翻译与解释之分,只是常用的执行方式,C语言作为编译性语言,也通过C语言的解释器进行解释,python语言作为解释性语言,也可以通过编译器进行编译。
- 解释性语言的优点:有特殊的计算能力。例如:运行过程中修改源代码。
- 编译性语言的优点:有确定的运算性能。
- 编译性语言一般快于解释性语言,其二者的速度的差距在计算机极高的速度下,对于许多程序也没有很大差异。
为什么要学c语言
c语言是一种工业语言,即一些专业的人员在做一些非常基础的工作再用此语言,我们学习c语言更看重的是它的开发效率,而不是开发是否便捷方便。 - 操纵系统
- 嵌入式系统
- 驱动系统
- 底层驱动
- 图形引擎
- 图像处理
c语言曾经是工业中使用量最多的编程语言,很多新兴的编程语言在语法上差异不大,当在说某个语言强大的时候,一般来说它是在针对你想要做的事情上有别人写好的库,所以你想要做这件事的时候就很容易。传统导致人们在遇到某个问题通常选择某个语言。而c语言则是处在一个很基础的位置。任何一个语言倘若深入学习,都是需要活到老学到老的。所以我们选择c语言二u们。
c语言的历史
C语言是由B语言发展来的,B语言是由于BCPL发展而来的,BCPL是从FORTRAN发展而来的。
1973年3月,在第三版的Unix上出现了C语言编译器,1973年11月,第四版的Unix完全用C语言重写了。(鸡生蛋,蛋生鸡)
- 1989年ANSI发布了第一个标准——ANSI C
- 1990年ISO接受了ANSI的标准 C89
- 1995年更新标准为C95
- 1999年更新为C99并沿用至今
编辑并编译C语言
C语言需要编译才能被运行,我们需要一个编辑器把代码记录到电脑,然后通过编译器进行编译运行。两个可以放在一起作为一个程序,这就是所谓的IDE(集成开发环境),推荐使用的一般是DEV-c++,当然大家可以根据自己的喜好去选择大家喜欢的IDE。
第一个c语言程序
- 避坑指南
- 输入法处于英文输入模式
- 代码错误
- 没有分号
- 缺少括号
- 关键字错误
- 确保文件名称无中文
- 确保文件创建正确
1 |
|
c语言程序框架
- 在学习函数之前所有的代码都是在这个框架下完成的。
1
2
3
4
5
6
7
int main()
{
return 0;
}
使用c语言做一个计算
1 |
|
- 计算结果如下
注释
注释就是一种解释说明,通常会告诉阅读者自己代码的意思
C语言注释方法有两种:
- 单行注释: //注释一行
1
2
3
4
5
6
7
8
// 这是我编写的第一个c语言程序
int main()
{
printf("Hello World!\n");
return 0;
} - 多行注释: /* 注释内容 */
1
2
3
4
5
6
7
8
9
/* 这是我编写的第一个c语言程序
这是我用c语言进行计算的程序 */
int main()
{
printf("%d",1+1);
return 0;
}
变量常量
超市找零的程序示例
变量的定义
为什么需要变量?
- 有地方放数字
- 有办法输入数字
- 输入的数字能参与运算
- 变量是一个保存数据的地方,当我们需要在程序里保存数据时,比如需要记录用户输入的价格时,就需要一个变量来保存它。用一个变量保存了数据,它才能参与到后面的计算中。
- 变量定义的一般形式就是: <类型名称><变量名称>;
1
2
3int price;
int amount; // 一行定义一个变量
int price amount; //也可以一行定义多个变量; - 变量需要一个名字,变量的名字是一种“标识符”,他是用来识别这个和那个的不同的名字。
- 标识符的构造规则;标识符只能由字母,下划线组成,数字不可以出现在第一个位置上,C语言的关键字不可以做标识符;
C语言的关键字
关键字如下(无需刻意记忆)
auto :声明自动变量
break:跳出当前循环
case:开关语句分支
char :声明字符型变量或函数返回值类型
const :声明只读变量
continue:结束当前循环,开始下一轮循环
default:开关语句中的“默认”分支
do :循环语句的循环体
double :声明双精度浮点型变量或函数返回值类型
else :条件语句否定分支(与 if 连用)
enum :声明枚举类型
extern:声明变量或函数是在其它文件或本文件的其他位置定义
float:声明浮点型变量或函数返回值类型
for:一种循环语句
goto:无条件跳转语句
if:条件语句
int: 声明整型变量或函数
long :声明长整型变量或函数返回值类型
register:声明寄存器变量
return :子程序返回语句(可以带参数,也可不带参数)
short :声明短整型变量或函数
signed:声明有符号类型变量或函数
sizeof:计算数据类型或变量长度(即所占字节数)
static :声明静态变量
struct:声明结构体类型
switch :用于开关语句
typedef:用以给数据类型取别名
unsigned:声明无符号类型变量或函数
union:声明共用体类型
void :声明函数无返回值或无参数,声明无类型指针
volatile:说明变量在程序执行中可被隐含地改变
while :循环语句的循环条件
常用的变量类型
- 整型int:用于储存整数
- 字符型char:用于储存单个字符
- 单精度浮点型:float:用于储存小数
- 双精度浮点型:double: 用于储存位数较多的小数
变量的赋值和初始化
变量定义后没有赋值,相当于打开一块存储空间,但里面有什么不知道。所以定义的时候需要进行赋初值。
- 变量初始化:<类型名称><变量名称>=<初始值>
1
int price = 0; //定义一个变量,变量名字是price,类型是int,初始值为0。
- price=0是一个式子,这里的“=”是一个赋值运算符(有运算符的式子叫表达式),表示将“=”右边的值赋给左边的变量。
- 在数学中,a=b表示一种关系,即a和b的值一样,而在程序设计中,a=b表示要求计算机完成一个动作:将b的值赋给a。关系是静态的,而动作是动态的。
- 变量类型:c语言是一种由类型的语言,所有的变量在使用之前必须定义或声明,所有的变量必须由确定的数据类型。数据类型表示变量中可以存放什么样的数据,变量中只能存放指定类型的数据。
变量输入
- printf用于输出,scanf用于输入
- 一个scanf可以读入一个数字,也可以读入多个数字
- 避坑指南
- 漏写&
1
scanf("%d",&price); //要求scanf这个函数读入一个整数,并把读到的结果赋给变量price。
- 漏写&
常量
- 固定不变的数,是常数。直接卸载程序里的数字,称之为直接量:
1
int change = 100 -price;
- 根据编码规范,常量名一般都大写。const是一个修饰符,加在int前面用来给这个变量加上一个const(不变的属性)。这个const的属性表示这个变量的值一旦初始化,就不再修改了
1
const int AMOUNT = 100;
- 经常量定义式放在函数中,同时代码修改为如果试图对常量修改,给它赋值,编译器就会报错。
1
int change = AMOUNT - price;
身高单位换算程序示例
- 两个整数的运算结果只能是整数,整数运算会自动四舍五入,在c语言中,而带有小数点的数称为浮点数。
- 当浮点数和整数放在一起运算时,c会将整数转换成浮点数,然后进行浮点数的运算。
- int是定义整型变量的,定义时把int换成double,可以将它改为浮点数。double就是双精度浮点数,float是单精度浮点数。
表达式
- 一个表达式是一系列运算符和算子的组合,用来计算一个值
- 运算符是指进行运算的动作,比如“=” “+” 和 “-”
- 算子是指参与运算的值,可能是常量,也可能是变量,还可能是一个方法的返回值
计算时间差程序示例
- hour*60+minute 将单位转换成分钟
- t/60 小时部分
- t%60 分钟部分
运算符号的优先级
- 单目就是只作用于一个变量,即在一个算子上进行取反,平方之类的运算。
- 在c语言中,赋值是一个运算符(赋值运算符),而在有些语言中,赋值是一个动作
- 以下列举常用的运算符
优先级 | 运算符 | 运算 | 结合关系 | 举例 |
---|---|---|---|---|
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=5,b=6交换
1
2
3t = a;
a = b;
b = t;
复合赋值
- 5个算术运算符,+ - * / %,可以可赋值运算符”=”结合起来,形成复合运算符
复合运算符 | 举例 | 运算 |
---|---|---|
+= | a += 5 | a=a+5 |
-= | a -= 5 | a=a-5 |
*= | a *= 5 | a=a*5 |
/= | a /= 5 | a=a/5 |
%= | a %= 5 | a=a+5 |
递增递减预算符
- “++ “和 “- -“ 是两个特殊的运算符,它们是单目运算符,但它所作用的算子必须是变量,它们的作用就是给变量加一或者减一
- a = 5
递增运算符 | 复合运算符 | 运算 |
---|---|---|
a ++ | a += 1 | a = a + 1 |
a++ 和++a的区别
假设a = 5
- a++是先运算后自增(先把a值输出再+1):结果a++ = 5, a = 6
- ++a是先自增再运算(先+1再把a值输出):结果++a = 6, a = 6
++和- -同理
if判断(条件判断)
- 一个基本的if语句是由一个关键字if开头,跟上括号里的一个表示条件的逻辑表达式,然后是一对大括号“{ }”之间的若干条件语句。如果表示条件的逻辑表达式的结果不为 0 ,就执行大括号中的语句。
1
2
3
4
5// 如果(im小于0),那么
if ( im <0 ) {
im = 60 + im;
ih --;
} - if判断程序示例
- 效果展示
if语句
1 | if(条件成立) { |
- 关系运算符
运算符 | 意义 |
---|---|
== | 相等 |
!= | bu相等 |
$>$ | 大于 |
$>$= | 大于或等于 |
< | 小于 |
<= | 小于或等于 |
- 效果展示
优先级
- 所有的关系运算符的优先级比算术运算低,但是比赋值运算高。
连续的关系运算时从左到右边进行的
- 效果展示
else语句
超市找零代码示例
- 不同输入运行结果示例
两数比大小程序示例
- 方案一
- 方案二
- 方案三
- 运行输出均如下
if语句没有大括号
- if 语句这一行结束的时候并没有表示语句结束的“;”,而后面赋值语句写在if的下一行,并且锁进了,在这一行结束的时候有一个表示语句结束的“;”。这表明这条赋值语句是if语句的一部分,if句拥有和控制这条赋值语句,决定它是否要被执行。
1
2if ( a > b )
max = a;
计算薪水程序示例
判断成绩及格示例
if-else嵌套
- 当if的条件满足或者不满足的时候要执行的语句也可以是一条if或者if-else语句,这就是if-else嵌套
- else总是和最近的if匹配
三个数比大小
级联的if-else if
分段函数
x<0,f(x)=1
x=0,f(x)=0
x>0,f(x)=2x
if-else常见错误
- 忘了大括号
解决:永远在if和else后面加上大括号
- if后面的分号
- 错误使用==和=
switch-case语句
sitch语句可以看作是一种基于计算的跳转,计算控制表达式的值后,程序会跳转到相匹配的case(分支标号)处。分支标号只是说明switch内部位置的路标,在执行完分支中最后一条语句时,如果没有后面的break,就会顺序执行到下面的case中去,直到遇到一个break,或者switch结束。 - 在else-if级联较多的时候可以选择switch-case语句
- 控制表达式只能是整数型的结果
- 常量可以是常数,也可以是常数计算的表达式
1 | switch (控制表达式) { |
while循环
四位数以下判断数的位数程序示例
- 人可以一眼看出这是几位数,但计算机不能,计算机需要判断数的大小来判断,但是if具有局限性,位数多了就难以实现,代码量庞大。此时就需要while循环。
while循环数位数的算法
- 用户输入x;
- 初始化n=0;
- x = x/10,去掉个位;
- n++;
- 如果x>0,回到第3部;
- 否则n就是结果。
do-while循环
- 在进入循环的狮虎不做检查,而是在执行完一轮循环体的代码之后,再来检查循环的条件是否满足,如果满足则开始下一轮循环,不满足则结束循环。
- do-while是在循环体结束之后才来判断条件,while是判断条件后再循环。无论条件满足与否,do-while一定做一次,while可能一次也不做。
1 | do |
do-while循环实现数位数
- 我们可以把while翻译为“当”,那么while循环的意思就是:当条件满足时,不断重复循环体内的语句。
计算log的程序示例
小技巧:在while循环后因为一直在进行,会改变x的值,所以当最后需要输出x的时候,可以定义一个变量将x保存下来。
倒计时循环程序示例
- 在这个程序中共进行了4次循环,循环结束时n=-1。(可通过列举变量的变化进行判断)
猜数游戏程序示例
- 计算机随机想一个数,记在变量number里;
- 一个负责记次数的变量count初始化为0;
- 让用户输入一个数字a;
- count++;
- 判断a和number的大小关系,如果a大,就输出“大”;如果a小就输出“小”;
- 如果a和number是不相等的,程序回到第三步。
- 否则,输出“猜中”和“猜中次数”,然后结束
for循环
计算阶乘的程序示例
for循环像一个计数循环:设定一个计数器,初始化它,然后计数器到达某值之前,重复执行循环体,而每执行一轮循环,计数器以一定步进进行调整,比如加一或减一。
for循环
- for中的每一个表达式都是可以省略的
1
2
3
4for(初轮动作; 条件; 每轮的动作)
{
<循环体>
} - 对于一开始的count=10,当count>0时,重复做循环体,每一轮循环在做完循环体内语句后,使得count–。
1
2
3
4for(count=10; count>0; count--)
{
<循环体>
} - 循环控制变量i只在循环里被使用了,在循环外面它没有任何作用。因此,我们可以把i的定义写到for语句里面去。(c99)
1
2
3
4for(int i=10; i>0; i--)
{
<循环体>
}
循环的计算和选择
- 对于以下的循环来说,循环的次数是n,而循环结束以后,i的值是n。循环的控制变量i,是选择从0开始还是从1开始,是判断i<n,还是判断i<=n,对循环的次数,循环结束后变量的值都有影响。
1
2
3
4for(i=0; i<n; i++)
{
<循环体>
}
for和while的循环如何选择
- 如果有固定次数,用for
- 如果必须执行一次,用do-while
- 其他情况用while
循环控制
素数判断程序示例
- 可以在循环中加break,当不满足的时候直接跳出循环完成判断,减少循环次数。
break和continue对比
- break:跳出循环
- continue:跳过循环这一轮剩下的语句进入下一轮循环
循环的嵌套
输出100以内的素数
- 程序运行效果如下
整齐输出前50个素数
- 程序运行效果如下
凑硬币
- 用1角,2角,5角的硬币凑出钱数
- 程序运行效果如下
- 只需要一种情况即可,跳出循环
break跳出循环
goto跳出循环
- 上面为break跳出,下面为goto运行跳转,从如下可以看出两者程序运行效果并无差别,goto的优点在于可以不受限制的灵活跳转,goto语句可以灵活跳转会导致破坏结构化设计风格,若一段代码多次使用goto语句会降低代码的可读性,且goto语句的执行可能会跳过变量的初始化、重要的计算语句等,甚至影响到整个程序的运行。二至使用时候需要进行选择