言简意赅C语言教案(轻松学C语言)

山东体育学院计算机技术交流玩机社 是阿文ayaya & 潍坊学院 Cookie 联合出品

序:作者想说的话

+ 此文档是由山东体育学院计算机技术交流玩机社(下面简称为 山体玩机社)的社长与他在潍坊学院的一名好朋友共同创作,纯属于为爱发电,如有错误,请联系山体玩机社社长或者加入玩机社群聊679383826进行反馈,我们看到后会进行修改,此外,由于创作人数较少,更新速度比较慢,需要予以谅解。 + 除了该文档以外,我们还会制作配套PPT,开讲座。 + B站 山体玩机社 已经更新讲座录播:

【山体玩机社】手把手带你理解C语言!言简意赅C语言 1.概述_哔哩哔哩_bilibili

【山体玩机社】言简意赅C语言 2.数据的存储与计算(上)_哔哩哔哩_bilibili

【山体玩机社】言简意赅C语言 2.数据的存储与计算(下)_哔哩哔哩_bilibili

  • 由于该文档为爱发电,我们也清楚的知道这个项目的回本周期很长(包括但不限于时间成本 精力成本 运维成本),甚至不回本,因此,需要麻烦看到该文档的同学支持一下,哪怕说一句“社长加油”,我们也是需要得到正反馈的。
  • 如果有想要加入创作团队的同学,请联系山体玩机社社长****加入玩机社群聊679383826联系我们。
  • 我们的教材使用的是谭浩强老师的《C语言程序设计 第四版》清华大学出版社。
  • 我们引用的文章会在每一章最后标注,十分感谢各位作者。

概述

什么是C语言?

计算机语言的三大变革:机器语言汇编语言高级语言

机器语言:由0,1构成,二进制代码。

汇编语言:低级语言,利用机器指令直接向处理器发送请求。

高级语言:更强的表述能力,容易学习。

编写高级语言后,由编译器转换为计算机理解的机器语言,并执行。

C语言为什么适合初学者?(不从语言本身特性,从学习的角度)

只有32个关键字,语言简练。有一部分暂时用不到。(Java有 53个)

语法限制不严格。

模块化,结构化,清晰明了。(前提是你得规范空格换行-_-,不然代码的可读性不会很高)

直接访问内存地址。(不急着了解)

C语言的主要单位是函数。(很快就能体会到)

是一种面向过程的编程语言,相对初学者来言比较简单,不会像面向对象~~(不是你想的那个对象)~~编程(全称为Object Oriented Programming,简称为OOP)语言的一样需要实现构造函数与析构函数。

课本与课堂均使用C99版本(C语言的版本在一直更迭),如果在编写的时候出现不一样的情况,很有可能是C语言的版本变化所致。

用什么软件编写C语言程序?

Dev-C++/Codeblocks 简洁,开箱即用,适合学习用途(蓝桥杯一般使用Dev-C++ 5.11版本)

Clion/Visual Studio 专业,自动补全代码,适合做项目。

Visual Studio Code 轻量化,功能强大,支持自动补全代码,内置Git,不过需要一定的动手能力(指配置开发环境)。

> 此处放一下潍坊学院某位大牛学长手搓的文档,此处仅提供相关文档,后期 > > [C/C++开发环境搭建(VSCode)](https://www.yuque.com/ruwang-rdeg8/wfustudy/set_c_environment) >

至于VC6.0++,支持C89标准,上古时代的产物,能不用就不用吧。

这里说的编程软件为IDE(Integrated Development Environment,集成开发环境),而不是编译器,针对Windows的编译器一般为Mingw64,请区分开编译器与编程软件

工具可以在山体玩机社QQ群文件获取。

开始编写第一个C语言程序!

理解一下函数

y=x+1 数学上的函数——x:自变量 y:因变量

设x=2

计算后得出 y=3

返回

C语言也是一样的

以y=x+1为函数名

1
2
3
4
5
6
TheWayToSolveTheFunction()
{
x=2;
y=x+1; //y=2+1
return y; //y=3
}

基于逻辑顺序,一步一步执行并获得结果。

Hello World!

准备工作:浅浅理解头文件

头文件本质上也是函数,提供一系列神奇的妙妙工具。
相当于预制菜,人家做好了相关的函数,等你加热。
例如printf() scanf()等输入输出函数。
当你在printf函数内填入数字等,会先将数据送到头文件内部的函数进行计算,随后将结果返回到原文件的函数。
用头文件前,先告知编译器我要使用这个头文件,使用命令 #include(常用)

开始编写

首先编写引用头文件:#include
编写主函数:main()(主函数每个C语言程序必须有,且他是主入口)
函数由大括号引起来:{ }
编写输出函数:printf(“Hello world!”);
要输出的内容用引号引起来。
每一条在大括号内的函数,结束了要用分号隔开。
编写返回函数return 0;
虽然这个程序只有一个函数,但是当多个函数存在时,需要获取另一个函数的结果,就得用到return语句返回结果给下一个函数。
可以省略,未来会用到。
开始编译运行。
1
2
3
4
5
6
#include <stdio.h>
int main()
{
printf("Hello World!");
return 0;
}

需要注意的问题:

关键字要小写,否则编译器识别不出来。
括号,分号,引号等标点需要用英文输入法的标点。
写一条语句就换行,直观,方便查找错误。
每一条不要忘记写使用分号结尾!
可以用//写注释,方便理解。注释内容不会被编译器识别。

程序基本上都是这个结构,往main函数里塞东西,吐出需要的数据

例题:课本P4 例1.2 例1.3

(虽然有些内容是后面才能学到的,但是经过讲解可以理解)

扩展阅读链接(引用链接)

[C语言头文件完全解析(连“#”我都给你讲明白)_include 含义-CSDN博客](https://blog.csdn.net/CRAZY_eyes/article/details/104868178)

[c语言变量详解-CSDN博客](https://blog.csdn.net/m0_74195174/article/details/135744401)

[深入理解计算机系统(十三):汇编语言和机器语言 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/37524989)

[C语言32个关键字-最详解释_c语言32个关键词的意思-CSDN博客](https://blog.csdn.net/qq_38972634/article/details/108398953)

[CodeBlocks安装与使用入门_code::blocks-CSDN博客](https://blog.csdn.net/cnds123/article/details/119963302)

[Visual Studio 2022安装与使用教程_visual studio在哪里打开-CSDN博客](https://blog.csdn.net/InnerPeaceHQ/article/details/121716088)

[DevC++ 软件下载及安装教程(详细、具体)_devc++下载-CSDN博客](https://blog.csdn.net/m0_54158068/article/details/124080083)

数据的存储与计算

进制概述(二、八、十、十六)

定义

二进制:0,1,逢二进一。(例:110=6)

八进制:01234567,逢八进一。(例:O12=10)

十进制:0123456789,逢十进一。(例:...不太想例)

十六进制:0123456789 ABCDEF。(从A-F分别为10,11,12,13,14,15)逢十六进一。(例0xff=255)

进制转换

十转二

十进制数除以2,余数为权位上的数,得到商继续除以2,直到商为0终止,然后反向取余数。

十转八、十转十六

十转二原理一样,十进制数除以8/16,余数为权位上的数,得到商继续除以8/16,直到商为0终止,然后反向取余数。

(二进制、八进制、十六进制)转十进制

按权展开、相加即得十进制数。

二转八、二转十六

3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)

八转二

八进制数通过除2取余法,得到二进制数,对每个八进制为3个二进制,不足时在最左边补零。

十六转二也是相同方法

1 位 八进制数值可以转换为 3 位 二进制数值

1 位 十六进制数值可以转换为 4 位 二进制数值

反之同理

同样,此处放一篇潍坊学院某位学长写的进制转换的文档

进制转换基本文档

常量与变量

变量

变量的类型

整型类型int short long(意味着以它们声明的变量,都是整数,没有小数)
实型(浮点)类型float double(意味着以它们声明的变量,可以包含小数)
字符类型char (以它声明的变量可以存储一个单词或者一个符号(在ASCII码内)
unsigned(无符号整数类型)学习过程不常用,用于表示非负数的时候使用。

变量的作用

变量就是一个小盒子,装运算需要用到的数据。
变量可以通过语句修改自己内部的数据,而常量不可以。

变量的命名规则

变量名只能包含字母、数字、下划线。
变量名不能以数字开头。
不要使用C语言的关键字作为变量名。
尽量做到见名知意:例如年龄Age,分数Score,总和Sum。

常量

变量可以在定义后反复变更值,而常量不可以。

数字,字符等就是常量(不变的量),而定义的常量(例如PI=3.1415926)必须事先定义好才能用,称为符号常量。

符号常量用于一些特殊的值,例如π,e等。或一些预写的文本。

符号常量是文本替换操作(很生硬的替换),因此可能会改变运算规则。

#define定义符号常量 后面不跟分号(因为这不是函数,这是与#include一样的命令)!

整型运算(例2.1)

问题分析

鸡兔同笼,求方程组。

根据已知,限定条件范围。

编写程序,解问题。

计算器也是根据程序一步步执行获得答案的。

C语言中基本的算术运算都可以使用,加减乘除,且运算顺序与日常一致。

printf的作用

在引号内的字符信息原封不动输出

遇到%d等特殊字符,则意味着将根据指定的变量输出。

遇到\n等特殊的转义字符,则意味着会对输出格式进行改变。

实型计算(例2.2)(例2.3)

问题分析(根据计算公式,将其结构化)

使用数学函数(如abs绝对值,sqrt开平方根)要引用math头文件。

%后,d为整型,f为浮点型(保留6位小数),c为字符型。

从高精度向低精度赋值可能会丢失一部分数据(double给float),建议根据情况为变量赋值。

含e的形式为指数形式,通常表示10的x次方。口诀是:e前e后必有数,e后必须为整数。

单精度float对于小数点后的数值精度不够,可能会出现偏差,因此根据情况使用双精度浮点型double类型。

字符运算(例2.4)

char类型的变量只能承接一个字符,多了塞不下。(可以填入的字符参照ASCII码)

为char类型赋值,需要用单引号将字符括起来。(例如 char ch='a';)

printf中每一个%c都对应逗号后的一个变量。

ASCII码与特殊字符

ASCII码是什么?

> 在计算机中,所有的数据在存储和运算时都要使用[二进制](https://zhida.zhihu.com/search?content_id=211451468&content_type=Article&match_order=1&q=%E4%BA%8C%E8%BF%9B%E5%88%B6&zhida_source=entity)表示。例如,像a、b、c、d这样的52个字母(包括大写)以及0、1等数字还有一些常用的符号(例如*、#、@等)在计算机中存储时也要使用[二进制数](https://zhida.zhihu.com/search?content_id=211451468&content_type=Article&match_order=1&q=%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%95%B0&zhida_source=entity)来表示,而具体用哪些二进制数字表示哪个符号,这就是编码。值得注意的是编码是信息从一种形式转换为另一种形式的过程;解码则是编码的逆过程。 >

不同的计算机要想互相通信并且不造成混乱,那么每台计算机就必须使用相同的编码规则,于是美国国家标准学会(American National Standard Institute,ANSI)制定了ASCII编码。

简单来说:在计算机内部有一个字典,将你输入的字符通过字典翻译成机器码,告诉计算机你要输入(或者输出)的字符是什么。

这样的字符有好几本,例如ASCII、Unicode、UTF-8等。

ASCII码的范围为0-127,超过这个范围会报错。

在C语言中,我们输入输出的字符遵循ASCII码的规则,字符因此还获得了一些“变量”的功能。

——ASCII码需要背吗?——理论来说需要,但是目前我们只要记住一小部分(推荐记住大写字母 A(97),小写字母 a(65),空格字符 (32),数字字符 0(48),

如果是需要其它字符,根据前面的向后推就行,比如小写字母 c 是在小写字母 a 后面,那么就是 a+2=65+2=67)

字符常量与字符变量(例2.5 例2.6)

字符常量是用单引号括起来的一个字符('a'),单引号只是一个起止符,并不是字符常量的一部分。

字符变量则是用来承接字符常量(例如 声明变量char = ch后 ch='a'),并且只能存放一个字符。

理论来说,字符变量承接的其实是字符的ASCII码,因此你也可以用数字替代字符。

1
2
3
4
5
6
7
#include <stdio.h>
main()
{
char ch = 97;// a的ASCII码 等效于char ch = 'a';
printf("%c",ch);//输出结果是a
return 0;
}

因此,你可以用加减乘除去动这个变量,获得别的字符。(不能超过127,不然会报错)

(例如a不停地+1+1,可以加到z,在未来学习的循环运算里可以一口气输出26个小写字母)

字符串常量(浅了解,数组会细讲)

单引号括起来的 一个字符 是 字符常量

双引号括起来的 一串字符 是 字符串常量

没有能保存字符串常量的字符串变量,我们会使用数组对字符串进行操作(未来会学到)

符号常量(之前已经说明过:[点击跳转](https://www.yuque.com/shiawenayaya/gdindg/fvslnq8ursl9oegg#Yph1I))

将常用的数学符号设为常量,方便反复调用,并便捷修改。

例如:π,e,r(圆的半径)。

使用#define定义,生硬的文本替换操作,所以注意定义不要有差错。

算数运算符和算数表达式

基本算术运算符

加减乘除,多了个模除(除法,但是结果是余数)

与数学计算方法一致,先乘除再加减,被除数不能为0(模除左右两边必须为整数)

自增自减运算符(经常用于循环语句)

①根据++(--)的位置,有不一样的运算方式。

i++,该语句结束前i的变量不变化,结束后i则变化。

++i,该语句结束前i的变量已经变化,结束后无变化.(因为已经加完了)

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
main()
{
int i=1;
printf("%d",i++);//输出为1,结束后为2
printf("%d",i);//此时为2
printf("%d",++i);//输出为3,加了之后输出出来的
printf("%d",i);//输出仍是3,上一条语句的自增操作已经结束
return 0;
}

②只能用于变量,不能作用于常量(常量是变不动的)

算术表达式(变量常量函数大乱斗!)

①例:a*b+sin(x)-π(其中a,b为定义的整型变量,sinx为数学函数(之后会讲到),π为定义的符号常量)

②遇到跟小数运算怎么办?不用担心,C语言会自动将结果换成当前最高精度的数据类型(小的用float大的用double)

③强制类型转换:将表达式的结果换成你想要的样子——(小数点部分可能会直接抹去)

1
2
3
4
5
6
7
8
#include<stdio.h>
main()
{
int a=10;
double b,c;
b=(double)a;//将变量a的值转换为double类型赋给变量b,请注意这不会改变a本身的数据类型。
c=(float)(a+b);//强制类型转换的格式为(类型名)(表达式)
}

C运算符与C表达式

C运算符(关系,逻辑的运算)

算术运算符: + - * / %(加减乘除 模除)//注:回来记得把一、换成圈1

关系运算符:> < ==(是否相等)>= <= !=(不等于)

逻辑运算符: !(取反。非真即假,非假即真)&&(与运算符。同真为真,一假为假) ||(或运算符。一真为真,同假为假)

赋值运算符: = (将运算后的值赋给变量:b=a+c;)

条件运算符:(后面会学到)A?B:C(如果条件 A 成立,执行 B,否则执行 C)

逗号运算符:,(用逗号连接多个运算符,顺序执行)

指针运算符:(c语言直接访问内存的核心,暂时不用了解太多) &(取址符号,用于scanf,将数据存入相应变量中)

强制类型转换符:(类型)(例如:(double)a,是将 a 强制转换成 double 数据类型)

下标运算符:(数组会用到)[]

其他运算符(暂时学不到的)位运算符,求字节运算符,成员运算符,函数调用运算符()(对没错函数名后的这个括号是用来调用函数的运算符)

其他运算符可在课本P48页或书附录中查看

关系运算符、逻辑运算符的结果只有真、假两种,即 true false

C语言表达式

算术表达式:2*a+sin(x)/0.5

关系表达式:(结果都是逻辑值0或1)x>0,y

逻辑表达式:(基于关系运算)x>0&&y<0(x大于0与y小于0是否同时成立)

赋值表达式:a=3.1

逗号表达式:在定义变量时,逗号表达式可以一次性定义多个变量的数据类型和值,例如:int a=3,b=5,c=6;在运算中,如:a=(b+1,c+2,d-1)中,逗号表达式的最后一个表达式的值(d-1)会赋给a。

扩展阅读链接(引用链接)

1. [超详细进制转换(二进制、八进制、十进制、十六进制)详解-CSDN博客](https://blog.csdn.net/weixin_53564801/article/details/123665194) 2. [C语言中的运算符大全(内附优先级表)_c语言运算符号-CSDN博客](https://blog.csdn.net/m0_50919743/article/details/115755380) 3. [ASCII码详细介绍 - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/554933865) 4. [C语言学习(八)整数(int、short、long)的具体介绍、不同进制表示、输出,sizeof、unsinged的使用_short int long-CSDN博客](https://blog.csdn.net/qq_37655329/article/details/120433772) 5. [float 与 double 的区别_double和float的区别-CSDN博客](https://blog.csdn.net/mid_Faker/article/details/105388466)

顺序结构程序设计

基本数据类型的认识

需要了解 C 语言中常见的数据类型,包括:
  • char
  • short
  • int
  • long
  • long long
  • float
  • double
  • (bool)

如何写注释

注释内容是给程序员看的,用来给程序内容做解释,编译器在进行编译期间不回去管注释内容

注释包括两种

1
2
3
4
5
6
7
8
// 这是一个单行注释,只能写一行注释

/*
这个叫做多行注释
可以写N多行注释
也可以写一篇小文档,
可以介绍一下一个函数的功能
*/

如何定义变量

所谓变量,即支持修改数值

所谓常量,即定义后,数值不可进行修改(极个别特殊情况除外)

上文介绍过了常见的数据类型,以及变量名的定义规则,这里可以直接讲一下如何定义一个变量并且进行赋值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
模板是:
数据类型 变量名 (赋值语句)

如果在定义的同时,不指定数值,根据编译器的不同,有的会给赋值0,有的会赋值随机数
*/
#include <stdio.h>
int main()
{
int a = 5;
int c;
printf("a = %d\n", a);//定义一个名字为a,数值为5的变量
printf("c = %d\n", c);//定义一个变量,数值不确定
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#define N 100
int main()
{
// const int N = 100; 也可以使用const 变量定义一个常量N
// N = 25; // error:N是一个常量,不可进行修改
printf("N = %d\n", N);
printf("-------------------------\n"); // 这是分割线
int n = 200;
// 定义一个变量n,并且赋值为200
printf("n = %d\n",0 n);
n = 40; // 将变量n的数值修改为40
printf("n = %d\n", n);

return 0;
}

算法概述

什么是算法

算法就是解决问题的方法,构思问题的解决方式

数据结构就是规定数据的类型与组织形式。

算法+数据结构=程序

计算机算法分为两种:数字运算与非数值运算(类似于数据库管理)

如何表示算法

自然语言 用人话描述(有歧义)

流程图 直观形象,但耗时耗力

N-S流程图 占用面积小,作图简单(常考常用)

伪代码 用编程语言的方式讲人话,然后再一步步改成编程语言的样子

程序的三种结构

顺序结构 逻辑向下不绕弯

选择结构 判断语句停一停,判断完成接着向下执行

循环结构 在循环体中绕圈,结束循环再往下走

C语句概述

C程序由若干个源文件组成

源文件由预处理文件(#include)、数据声明(int a)、若干个函数组成

函数由函数首部(main())、函数体({})组成

函数体由数据声明(int a)与执行语句(C语句)组成

C语句分为以下5类(P63)

控制语句 用于选择、循环结构。负责进入循环,跳出循环,控制循环

函数调用语句 printf() scanf()等函数语句

表达式语句 赋值操作,算数操作,加上分号就变成了语句。

空语句 只有一个分号,什么也不做,用于特殊用途)

复合语句 用{}扩起多条语句,常用于if判断后执行的语句

赋值表达式和赋值语句

赋值运算符 = (a=3 将3赋予给变量a)

复合的赋值运算符

a+=3 等价于 a=a+3

x*=y+8 等价于x=x*(y+8) (相当于后面带上括号)

加减乘除模除等都可以和赋值符号一起复合

赋值表达式与赋值语句

形式

变量 赋值运算符 表达式

即 int a=5

也可以是 int b=(a=5) (相当于b=a=5)

表达式没有分号 语句有分号

用法

赋值操作 a=7;

复合赋值操作 a=b=5;

其他语句 printf(“%d”,a=b); 相当于将b的值赋给a后,输出a的值

但是不能为printf(“%d”,a=b;)(语句) 因为printf后面只能承接表达式

表达式能嵌入很多语句中,而语句本身不能嵌入到别的语句里

类型转换

当两个变量类型不一致的变量进行赋值操作时,会进行内部的类型转换

实型转整型 直接截取整数部分

整型转实型 将整数部分放入后,添0

双精度浮点型转单精度浮点型 截取7位有效位数

字符转整型 将ASCII码值带入

整型转字符 小于128的,直接换成ASCII码对应字符 大于128的 减去128,直到减不掉后,换成ASCII码对应字符

变量赋初值

可以在定义时赋值 int a=6;

可以在定义后赋值 int a; a=6;

可以一次性定义多个变量后赋予初值 int a=2,b=3,c=4;

可以分开定义 int a,b,c=2;

数据输入输出

C语言本身不提供输入输出语句,而C标准函数库提供(stdio.h)因此,需要在程序开头声明调用库文件(#include stdio.h)

字符数据的输入输出

putchar(字符) 一次输出一个字符

可以直接输入字符,也可以用ASCII码(需要转换,如'\101')

getchar(字符)一次输入一个字符

使用方法: a=getchar()

请注意:回车为控制字符,所以也会被getchar记录

简单的格式输入输出

输出格式printf

printf(格式控制,输出表列)

格式控制是用双引号括起来的字符串,他可以有普通字符与格式声明(%d等)

普通字符输出时原封不动保留,格式声明输出时会根据输出表列输出对应变量内容

printf(“%d,%d”,a,b);

格式字符类型

d格式 按十进制整型数据输出
i格式 与d格式相同,通常使用d格式
c格式 输出一个字符(单引号引起)
s格式 用于输出字符串(双引号引起)
f格式 用于输出实数(单精度双精度) %m.nf m为输出总位数,n为小数点后位数
e格式 输出指数形式的实数

输入格式scanf

scanf(格式控制,地址表列)

格式控制同printf,地址表列是由变量的地址组成的(&a&b)

&为地址运算符

请注意:在格式控制中怎么写的字符串,就要在输入数据的时候写入一样的字符串

1
2
scanf("my age is %d",&a);
//输入的时候要写:my age is 5

遇到%c%c%c这样的连续输入,不要用空格或换行隔开,因为空格与换行算控制字符

顺序结构的认知(例3.7 3.8 3.9)

在 C 语言中,默认从 main 函数开始执行

从上到下,逐条执行

顺序结构就是这样的,从上到下逐条进行进行执行代码

多实操,多练习。

扩展阅读链接(引用链接)

[什么是算法,表示算法的4种方法(小白必读)-CSDN博客](https://blog.csdn.net/x15297649174/article/details/137055815)

数据结构:基本概念【详解】_什么是数据结构-CSDN博客

分支结构程序设计

条件判断

概念含义

在顺序结构里,语句是按排列顺序依次执行的,但是生活经常有二选一的情况:

我去餐厅还是点外卖?(判断是去餐厅还是去点外卖)

考试如果不及格,是不是要补考?(判断考试的成绩是否及格,如果是,就不执行,如果否,则补考)

条件判断的结果是逻辑值:是 或 否,计算机用 真(1) 或 假(0) 来表示。

1
2
3
4
if (x>0)//如果x的值大于0,则执行第一条printf语句
printf("%d",x);
else//否则 则执行else下面的printf语句
printf("%d",-x);

关系运算符和关系表达式

C语言提供的关系运算符

<(小于)
<=(小于或等于)
>(大于)
>=(大于或等于)
==(等于)
!=(不等于)
前四种关系运算符的优先级别相同,并且高于后两种(等于与不等于)

比较大小,后比较相等关系

关系运算符的优先级低于算术运算符(先加减乘除,算完再比较)

关系运算符的优先级高于赋值运算符(比较完了之后再将真假情况赋予变量中)

1
2
b=c>a+b(先算a+b,然后算c>(a+b),最后将真值情况赋予b)
如果c大于a与b的和,则将1赋予b

关系表达式

表达式也可以进行关系比较

用的是表达式的值进行计算

1
2
a+b>b+c (先算a+b的值,再算b+c的值,最后将两个值比较)
(a>b)>(b<c) (先算a>b的真假,再算b<c的真假,最后将两个值比较

得到的值也是逻辑值(0,1)

容易出现的错误:

1
2
3
int a=3,b=2,c=1
d=a>b>c//先算a>b,得到1,再拿1与c进行比较,1>1不成立,便得到了0的结果
printf("%d",d);//输出0

逻辑运算符和逻辑表达式

概念

有些判断需要的条件不止一个,且也不是能够比较大小的关系

例如:

课程不能挂科,并且体测必须大于80分才能评奖评优

1
2
if(课程!=挂科&&体测>80
评奖评优

逻辑运算符及其有限次序

C语言提供3种逻辑运算符
&& 逻辑与
|| 逻辑或
!逻辑非
&&与||是双目运算符,要求在运算符两侧都必须有运算对象

!是一目(一元)运算符,只要求在它的右侧有一个运算对象即可

1
2
3
a&&b (读作a与b)如果a与b都是真的,则这个表达式的值为真,有一个假的则整个表达式为假
a||b (读作a或b)如果a或b有一个是真的,则这个表达式的值为真,如果两边都是假的,则整个表达式为假
!a (读作非a)如果a一开始为真,加上逻辑非后则为假值,反之,则为真值

优先级情况:!(非)> &&(与)>||(或)

&&与||低于关系运算符(>、<、==等)(也就是先计算逻辑后再判断关系)

!高于算术运算符(也就是先取反逻辑值后再开始比较逻辑或关系)

1
2
!a||a>b
先计算!a,后计算a>b,最后进行两者的逻辑运算

逻辑表达式

与关系表达式类似,也可以用表达式进行逻辑运算,结果也是0与1
1
2
3
4
5
6
7
8
5>3&&8<4-!0
表达式先从左往右求解
首先5>3是真的,因此值为1
来到&&右面,8<4-!0,由于算术运算符优先级高,因此先算4-!0
在这里,!0的优先级高,先运算,因为0为逻辑值0(只要不是0的值都是真的)所以取反为1
所以4-13
8<3,假,取0
因此最后为1&&0 为假

用if语句实现选择结构

用if语句实现选择结构举例(例4.1 例4.2)

需要注意的点

不要把相等(==)变成赋值(=),( if (a=1) )否则if会读取表达式的值(永远都是真的),不会执行不符合的情况下的语句

如果if后有多条需要执行的语句,需要用花括号括起来{ }

if语句的一般形式

if(表达式)语句
1
if(x>y) printf("%d",x);
if(表达式)语句1 else 语句2
1
2
3
4
if(x>y)
printf("%d",x)
else
printf("%d",y)//比大小算法

if语句使用的说明(例4.3)

if语句后面的表达式,一般为逻辑表达式或关系表达式,因为这样能根据其真值情况执行相应的语句
简言之,if语句括号内最好是以逻辑值计算的表达式

变量等也可以在括号内,非0的值都为真值,因此会直接执行if下的语句

if后面的语句要用分号隔开,但是if和else语句不用分号隔开
1
2
3
4
if(x>0)//不能加分号
printf("%f",x);//加分号
else//不能加分号
printf("%f",-x);
else不能单独用,它属于if语句的一部分
if后面的语句要执行多条语句的话,用大括号括起来

使用嵌套if语句实现多层判断(例4.4)

1
2
3
4
5
6
7
8
9
10
11
if(a>b)
if(a>c)
printf("%d",a)
else
printf("%d",c)
else
if(b>c)
printf("%d",b)
else
printf("%d",c)
//else永远与与他最近的未配对的if匹配
1
2
3
4
5
6
7
8
if(xxx>x)
printf...
else
if(xxxx>x)
可以改为
if(xxx>x)
printf...
else if(xxxx>x)

利用switch语句实现多分支选择结构

一般形式

1
2
3
4
5
6
7
8
switch(表达式)
{
case 常量表达式1:语句1
case 常量表达式2:语句2
...
case 常量表达式n:语句n
default(可有可无): 语句
}

switch后面的表达式可以是数值型或者字符型(用于匹配case内的常量表达式)

表达式的值与case的常量表达式相同时,则执行相应case的语句,若无,则执行default(默认)的语句

不能有重复的case常量表达式(不然到底执行谁?)

case与default的顺序不影响执行结果

case的语句结束后会继续执行下面的case,不会进行语句结束的判断,因此应当在语句后加上break;

由五得,可以多条case共用一组执行语句

1
2
3
case 'A':
case 'B':
case 'C': printf(">60\n");break;

程序综合举例(例4.5 例4.6)

课堂讲解

扩展阅读链接(引用链接)

[C语言的关系运算符、逻辑运算符和条件运算符-CSDN博客](https://blog.csdn.net/2402_88427700/article/details/143245268)

循环结构程序设计

循环结构用在哪里?

遍历数据

例如获取班里10名同学的数学成绩之和,需要先获取每一位同学的成绩。

处理重复事物

例如将所有成绩除以5、输出每一位同学的成绩等。

循环的三种结构

while语句(例5.1)

基本结构

1
2
3
4
5
while(表达式)
{
语句;
}

同if,如果需要执行多条语句需要用花括号括起来。

注意事项

需要对表达式的值进行变化,否则会变成死循环。

while循环先判断循环条件是否成立,再执行循环体。

do while语句(例5.2)

基本结构

1
2
3
do
循环体语句;
while(表达式);

注意事项

需要对表达式的值进行变化,否则会变成死循环。

do while循环先执行循环体语句,再判断表达式的循环条件是否成立。

while与do while可以转换,但是逻辑需要变化一点。

表达式为循环继续的条件,不是循环结束条件。

for语句(例5.4)

一般形式

1
2
3
4
5
6
7
8
for(表达式1;表达式2;表达式3
语句;
//表达式1为循环变量初始化
//表达式2类似while的循环判断
//表达式3为循环变量的改变(防止出现死循环)
可理解为
for(循环变量赋初值;循环条件;循环变量增值(减值))
语句;

执行过程

首先 执行表达式1(一般为循环变量的初始化)(如 int i=0)

然后 判断表达式2的循环条件是否成立(如 i>=0)

如果成立 则执行循环体内部的语句

在循环体内部语句全部执行完毕后,执行表达式3

表达式3一般为对循环变量的控制(如i++,i–等)

目的是为了不让整个for循环为死循环(永远出不去的循环)

注意事项

需要对表达式的值进行变化,否则会变成死循环。

do while循环先执行循环体语句,再判断表达式的循环条件是否成立。

while与do while可以转换,但是逻辑需要变化一点。

表达式为循环继续的条件,不是循环结束条件。

表达式1与表达式2在特定条件下可省略,如:

1
2
3
4
5
6
7
8
9
10
11
12
for(int i=0;i<5;i++)
{
//语句;
}
//改为
int i=0;
for(;i<5;)
{
//语句;
i++;
}
//因为变量初始化与变量控制已经在for循环内外定义过了

for循环经常用于数组的遍历(相当于一个一个地看数组里的值是什么),赋值等操作

循环嵌套

定义

循环内部再套一个循环,称为多层循环

while do..while for三种循环都可以互相嵌套

1
2
3
4
5
for(i=1;i<8;i++)
for(j=1;j<8;j++)
语句;
相当于8*8执行64次语句内容

注意事项

两个for循环的循环变量应不同(例如上方的定义示例),否则会达不成预期甚至出现死循环

经常用于二维数组、冒泡算法(一种将数值从大到小排序的排序算法(一维数组))等。

注意多条语句用花括号括起来

Continue与Break(例5.6)

用于满足特地条件下对循环的控制,比如提前结束本轮循环或结束整个循环

类似于排队抢物品,如果物品没了,自然后面的人就已经拿不到了(break)

例如:

1
2
3
4
5
6
7
8
9
10
11
12
for(i=1;i<6;i++)
{
if(i==2)
continue;//选择性跳过
printf("%d",i);
}//输出1345
for(i=1;i<6;i++)
{
if(i==4)
break;//跳出整个循环)
printf("%d",i);
}//输出123

注意:continue结束本轮循环后,依旧会执行表达式3的循环变量控制(i++/i–等)

循环程序举例(例5.8 例5.9 例5.10与九九乘法表输出)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>

int main()
{
int i, j;
for (i = 1; i <= 9; i++)
{
for (j = 1; j <= 9; j++)
{
printf("%d*%d=%2d\t", i, j, i * j);
}
printf("\n");
}
return 0;
}

扩展阅读链接(引用链接)

[for的用法详解,for循环完全攻略-CSDN博客](https://blog.csdn.net/wounler/article/details/117817554)

三种循环语句的详解和使用(for,while,do-while)_while循环-CSDN博客

利用数组处理批量数据

数组是什么?

假设,一名同学有1个成绩,100个同学就有100个成绩。

如果以我们之前的做法,就会去定义100个变量。

诚然,这是有简化方法的,即为:数组

用一个名字命名该数组,如score,数组的下标(即数组的序号,比如a[0]为a数组的第一个数据)为学生的序号

由此可得,score[15]=32 为 第十五位学生的成绩是32

而通过对数组下标的操作,我们可以批量化处理数据

一维数组

一维数组的定义

1
2
int a[10]
变量类型 数组名[常量表达式]

1.数组名的命名规则与变量名的规则是一致的

2.易错点:

1
2
3
int a[10]
//表明a数组有10个元素,但是不能访问到a[10]
//能访问到a[0] a[1] a[2] a[3]...a[9]

3.常量表达式中只能是常量和符号常量,不能是变量(会报错)

数组定义好后,不能再随意变更大小(不能用变量的原因)

一维数组的引用(例6.1)

必须先定义后使用

一次只能引用一个数组元素

1
2
3
4
5
int a[10];
t=a[6];
变量 赋值符号 数组名[下标]
下标可以是整形表达式(结果是整数)
例如:a[2+1] a[2+i] a[2*3]

一维数组的初始化

1
2
3
4
5
6
7
8
9
//对全部元素赋初始值
int a[10]={0,1,2,3,4,5,6,7,8,9};
//部分赋值
int a[10]={0,1,2,3,4};//剩余没赋值的元素自动设为0
//可以根据初始值的长度赋予数组长度
int a[5]={1,2,3,4,5}
//可以写成
int a[]={1,2,3,4,5}

一维数组程序举例(例6.2)(例6.3冒泡排序)

此处建议做题的时候在草稿纸上画出来,方便记忆

此外,一定要注意:下标不能越界

二维数组

二维数组的定义

一维数组可以类比成条形码,二维数组可以类比成二维码,多一个维度
1
2
3
4
5
int a[3][4];
3为行
4为列
可承载3*4=12个元素
类型名 数组名[常量表达式][常量表达式]

甚至还有多维数组a[2][3][4](两页三行四列),很少用到。

二维数组的引用

1
2
变量 赋值符 数组名[下标][下标]
b=a[2][2]

需要注意的是,二维数组可用的下标范围依然是0到n-1

例如:

1
2
3
4
5
6
a[3][4]
则行的取值范围为0-2
列的取值范围为0-3
则a[3][3] 是不可取的
a[2][4]是不可取的
最大到a[2][3]

二维数组的初始化

可以分行给数组赋值
1
2
3
4
int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
把第一个花括号赋给第一行的元素
以此类推
即按行赋值

可以将所有数据写在一个大括号内,按数组排列自动分配

1
2
3
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
第一行赋值四个,满了后换行接着赋值
容易遗漏,不易检查

可以对部分元素赋初值

1
2
int a[3][4]={{1},{2},{3}};
只对各行第一个元素(即下标为0的列)赋值,其余未赋值的数均为0

也可以各行中的某一元素赋值

1
2
3
int a[3][4]={{1},{0,6},{0,0,11}};
int a[3][4]={{1},{5,6}};
int a[3][4]={{1},{},{9}};

同一维数组,可以根据长度自动分配,但是第二维不能省(一维二维都省了,无法得知能排几行几列)

1
2
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}
int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12}

二维数组程序举例(例6.4,例6.5)

二维数组用法:学生成绩数组——【第n科目】【科目对应的分数】

维度越多,承载的信息量越多

字符数组

字符数组定义

1
2
3
4
char a[10]={'h','e','l','l','o'}
将五个字符送入数组中
如果元素没有填满数组,则会将下一个数组元素放入'\0'空符号
遇到空符号,会自动停止读取

注意:空格也算字符,如果元素有’ ‘,也算一个元素

同样的,可以省略数组长度,看元素个数自动赋长度:3一维数组的初始化

二维数组同理

字符数组引用

与一维数组二维数组类似,获取的是字符。[2一维数组的引用(例6.1)](#NdlBK)

字符串与字符串结束标志(课本例子)

在C语言中,字符串作为字符数组来处理

如:hello 处理后是 ‘h’,’e’,’l’,’l’,’o’,’\0’

‘\0’就像队伍的最后,有一个人举着牌子:最尾处,表示这个数组/字符串到了最后

因此,字符数组不看重长度,长度可以一开始定很长,然后用’\0’截取,获取到’\0’所在的下标,也就获得了数组的长度。

字符数组输入输出

使用%s输入输出

1
2
3
char c[]={"china"};
scanf("%s",&c);
printf("%s",c");

使用%c输出

1
2
3
4
5
6
char a[10]={};
for(i=1;i<9;i++)
scanf("%c",&a[i]);
a[i]='\0'//scanf不加停止符,需要自己加
for(i=1;a[i]!='\0';i++)
printf("%c",a[i]);

字符串函数(选择题常用,程序题不常用)

课本183-188

字符数组应用举例(例6.7,例6.8)

扩展阅读链接(引用链接)

[【排序算法】史上最通俗易懂的【冒泡排序】详解-CSDN博客](https://blog.csdn.net/k_kuo_k/article/details/111650681)

C语言 数组定义和使用 - C语言零基础入门教程_c语言中数组的定义和使用-CSDN博客数组(Array)——数组介绍-CSDN博客

常用的字符串函数详解_写出并解释字符串常用函数-CSDN博客

使用函数实现模块化程序设计

多函数的意义

在之前的学习过程中,我们可以发现,一部分运算也包含在主程序中。

如果要反复利用这部分的运算,就需要复制,粘贴,再写一遍。效率很低。

所以多函数的意义在于,他将程序——模块化。使用对应功能,只需要在主程序里调用。

好处是,修改算法只在模块内实现,不用大刀阔斧对整个程序进行修改

类似于上游加工厂和下游组装厂的关系。

多函数举例/函数的定义(例7.1 例1.3)

函数由以下几个要素组成
1
2
3
4
5
6
7
8
9
10
11
无参函数(不需要向函数提交数据(参数),即可调用)
返回的数据类型 函数名()
{
函数体
}
有参函数
返回的数据类型 函数名(数据类型 函数形参,数据类型 函数形参....)
{
函数体
return 0;
}

返回的数据类型:即这个函数结束后,向其他函数递交的数据的数据类型

函数名:函数的名字,尽量做到见名知意,能想到这个函数对应的什么功能

函数形参:只是表明这个函数需要 什么数据类型的数据,在调用的时候,如果不给数据则会报错

函数体:与之前写main函数一致,不过最后的return语句一定要加(不能总是return 0了),他代表了这个函数返回的数值。

函数的调用

有两种函数的调用

在main函数中,首先要声明自己要使用的函数,随后,无参函数可以直接以函数()调用,有参函数需要一个变量承接它的返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include<stdio.h>
int main()
{
int a,b,c;
int max(int x,int y);//表示要在main函数里调用max函数
void printstar();
printstar()//直接调用无参函数
c=max(a,b)//有参函数,参数类型要对应
}
int max(int x,int y)
{
....
return max;//return 将最大值返回给主函数
}
void printStar()//void类型代表该函数没有返回值(只做打印工作)
{
printf("*****");
}

函数调用:变量=函数名(实际参数)

实际参数与形式参数:简单理解为,我们递交数据(实际参数)给函数,函数方将我们的数据以他们的方式定义(形式参数),并参与函数运算中。

将要调用的函数放在main函数前,可不用声明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<stdio.h>
int max(int x,int y)
{
....
return max;//return 将最大值返回给主函数
}
void printStar()//void类型代表该函数没有返回值(只做打印工作)
{
printf("*****");
}
int main()
{
int a,b,c;
printstar()//直接调用无参函数
c=max(a,b)//有参函数,参数类型要对应
}

函数的用法

函数语句

调用没有返回值的函数,函数调用作为一个语句存在:printstar();

函数表达式

有参函数只要有返回值,他的单独存在也可成为表达式。
1
c=2*max(a,b)//首先计算max函数,将函数的值作为表达式的值,与2相乘,最后将整个表达式的值带入c变量中

作为函数的参数

1
printf("%d",max(a,b));

函数的嵌套调用和递归调用

函数嵌套调用(例7.3)

简单来说,函数里面套函数,最简单

main函数都能调用别的函数,函数内部为什么不能再调用别的函数?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
int main()
{
int max_4(int a,int b,int c,int d);
int a,b,c,d,max;
printf("please enter 4 integer numbers:");
scanf("%d %d %d %d",&a,&b,&c,&d);
max=max_4(a,b,c,d);
printf("max=%d",max);
return 0;
}
int max_4(int a,int b,int c,int d)
{
int max(int,int);
int m;
m=max(a,b);
m=max(m,c);
m=max(m,d);
return (m);
}
int max(int x,int y)
{
if(x>y)
return x;
else
return y;
}

函数递归调用(例7.4,例7.5)

基于函数嵌套调用,不过是自己调用自己。

逻辑一定要清晰,对于达成目的要明了,否则可能绕不出来。

数组作为函数参数

数组元素作为函数参数(例7.6)

与变量作为函数参数一致,主要区别是可以利用for循环将不同数组元素带入函数运算

数组名作函数参数(例7.7)

要注意的是,定义函数时,形参为:数据类型 数组名【数组长度】

调用函数时,只需要将数组名放入函数内

1
2
3
4
5
6
7
8
9
float average(float array[10])
{
...
}
int main()
{
float s,score[10]
s=average(score);
}

局部变量与全局变量

一句话概括:函数内部的变量只能在函数内部运作,全局变量可以在所有函数里操作

局部函数定义在函数内部

1
2
3
4
int main()
{
int a,b,c;//局部变量
}

全局变量定义在函数外部,一般定义在所有函数的最开始

1
2
3
4
5
6
#include<stdio.h>
int a,b,c,d;//全局变量
int main()
{
...
}

如果全局变量与局部变量名字冲突,则屏蔽全局变量,只使用函数内部的局部变量。

静态变量与自动变量(例7.12)

一句话概括:自动变量的值在函数结束时不会保存,如果重新进入函数,静态变量的值会保持不变(还是上一次的结果),但自动变量会重新初始化。

扩展阅读链接(引用链接)

[递归详解——让你真正明白递归的含义-CSDN博客](https://blog.csdn.net/weixin_44572229/article/details/119909728)

c语言中的局部变量和全局变量_c语言全局变量-CSDN博客

看完这篇文章一定弄懂C语言数组作为函数参数的用法_c语言数组在函数参数中的表示-CSDN博客

致谢

是阿文ayaya想说:

感谢大家阅读这份教案,我在创社的设想就是:提升大学生的计算机素养!专业的也好不专业的也好,计算机已经成为了大家生活不可或缺的部分。特别是学习与工作上。所以如果有人真的能因为我们所做的努力而喜欢计算机,甚至加入我们的社团贡献自己的一份力量,我真的会很欣慰,我不在是一个人在战斗。

创办本课程的原因有几点:

1.老师的教学方式让人难以理解。

2.培养我们学院专业的计算机素养与编程基础。

3.想吸引更多人加入我们社团。

因此我们创办了这个课程,这个课程企划、执行基本上都由我一人创建,自己的精力有限,找了我的好朋友Cookie帮忙,做这个东西蛮辛苦的。(

我们社团也还在起步阶段,如果你对社团有什么想说的欢迎在群聊里说出来,不要有什么顾虑。(群没人水就沉了5555)

最后感谢你的支持,希望你学业进步!

Cookie想说:

感谢国家,感谢党,感谢这个美丽的祖国,感谢CCTV,感谢这个世界

感谢食堂不杀之恩

感谢我那从未出现的女朋友,感谢她没有阻挡我本科时期的脚步,智者不入爱河,建设美丽中国!


言简意赅C语言教案(轻松学C语言)
http://sdpei-ctca.github.io/2025/02/23/言简意赅C语言教案 (完结)/
作者
ItsAyaya
发布于
2025年2月23日
许可协议