chapter 1 顺序结构


C语言程序设计

chapter 1 顺序结构

0. 前言

人类区别于动物的主要特性就是有自己的文化,懂得学习和交流,而这一切都无法离开“语言”这一工具。人与人之间可以通过中文、英文亦或是日文等进行沟通交流。随着机器的诞生,解放了很大的人力,于是人类开始希望借助于机器来完成某些工作,最大程度上实现“偷懒“,其实我更愿意理解为 "人类将一些低级的、机械的工作交给机器完成,而人类自身将更多的精力耗费在更具有挑战性的工作上。那么由此就催生出了一个问题 “人类怎样同机器进行交流呢?”。

于是人类就通过使用一串一串的指令来指挥机器进行某项活动,随着不断的升级和完善,计算机程序语言也开始诞生了,人类可以通过计算机程序语言和机器进行交互。
1972—1973年间,美国贝尔实验室的D.M.Ritchie 在B语言的基础上设计出了C语言。最初的C语言只是为描述和实现UNIX操作系统提供一种工作语言而设计的。随着UNIX的日益广泛使用,C语言也迅速得到推广。
1978年以后,C语言先后移植到大、中、小和微型计算机上。C语言便很快风靡全世界,成为世界上应用最广泛的程序设计高级语言。以UNIX第7版中的C语言编译程序为基础。
并且在之后人们对其新增了一些特性,于是就有了一个新的名字“C++”,意指是对C语言的增强。C++由美国AT&T贝尔实验室的本贾尼·斯特劳斯特卢普博士在20世纪80年代初期发明并实现(最初这种语言被称作“C with Classes”带类的C)。开始,C++是作为C语言的增强版出现的,从给C语言增加类开始,不断的增加新特性。今天C/C++已成为世界主流编程语言之一。

接下来我们将学习C语言,上车请系好安全带,即将开车了。

1. 编程的概念

程序:为实现特定目标或解决特定问题而用计算机语言编写的一系列指令序列。

计算机语言:人与计算机之间通信的语言。计算机语言有很多种,比如BASIC语言、PASCAL语言、C语言、C++语言、Java语言等,每种计算机语言都有自身定义的规则,即使是同一种语言也有不同的版本,内部规则也会有少许不同。

编程:可以简单的理解为程序员为了解决特定问题,按照自己的思路,在遵循特定的计算机语言规则下编写程序的过程。

面向过程:以解决问题本身作为解决目标。

面向对象:以问题根源作为解决目标。

2. 编程软件

工欲善其事,必先利其器,一个好的编译软件可以使我们的学习事半功倍。

现在对于初学者常用的编译软件很多, 如:VC6.0,CodeBlocks,Dev-C++

本次课程使用Dev-C++软件,主要是使用方便,小巧,对于如何下载和安装,请查看以下链接,点击可跳转:

Dev-C++软件的安装使用教程

程序语言都是在某个环境下编译运行的,我们需要配置编译器,目前有很多IDE(Integrated Development Environment),集成了代码编写功能、分析功能、编译功能、调试功能等一体化的开发软件服务,所以我们只需要下载一个即可。目前市面上较多的有Dev-C++、VScode等,初学者建议使用Dev-C++。
Dev-C++下载链接:https://pc.qq.com/detail/16/detail_163136.html

VScode:https://code.visualstudio.com/
VSCode(全称:Visual Studio Code)是一款由微软开发且跨平台的免费源代码编辑器。该软件支持语法高亮、代码自动补全(又称 IntelliSense)、代码重构、查看定义功能,并且内置了命令行工具和 Git 版本控制系统。用户可以更改主题和键盘快捷方式实现个性化设置,也可以通过内置的扩展程序商店安装扩展以拓展软件功能。

3. 键盘和鼠标的使用

鼠标的介绍

鼠标分为:左右键,滚轮

左键用于选择和确认,一般可单击(表示选择),双击(表示确认)

右键用于项目提示和调出选项选择框,一般将其放在我们要操作的项目上,右键单击,就会出现一个新的小框,供我们选择,这时候选择应当使用:左键

滚轮用于上下翻页(部分可以左右翻页),如果和 Ctrl 结合使用,会出现大小缩放的效果,即放大缩小。

键盘快捷键

作用 快捷键 作用 快捷键 作用 快捷键
缩放 Ctrl+滚动滚轮 缩小 Ctrl + '-'(键盘按键) 放大 Ctrl + '+'(键盘按键)
中英文切换 Ctrl + 空格 输入法切换 Ctrl + shift 大小写切换 CapsLock
全选 Ctrl + A 复制 Ctrl + C 粘贴 Ctrl + V
删除 Delete / Backspace 剪切 Ctrl + X 查找 Ctrl + F
新建 Ctrl + N 保存 Ctrl + S 回退 Ctrl + Z

如果我们要使用:#, %, /, "",+,(), * 等键盘上的复合型按键怎么调出来呢?
需要先按住 Shift ,再按对应的按键(记住:此时 Shift不能松开, 上述快捷键 Ctrl 也是一样)

如果程序编辑页面的定位符变成了一个黑色小方块,那么按一下键盘上的:Insert

注意:书写程序时,全部的代码都是在英文状态下编写的,也就是输入法的状态为 English

4. 注释

注释是指在程序中,写给我们开发者自己看的内容,这部分内容不被编译器编译运行。即使我们不写或者删除都不会对程序产生影响。

也就是说编译器在编译代码时,会忽略注释的内容
注释通常放在一行代码的上方,或者一条语句的末尾。

// 注释内容 :单行注释符,用于单独一行的注释;
/* 注释内容 */ :多行注释符,用于对多行进行注释,也称 块注释。注释内容可以为中文,外文,乱码等任意符号,且可以换行,即使你突然灵感爆发,在这里写上一个千字文章也未尝不可。

在devC++编译器中注释的快捷键为:Ctrl +/


5. 常用的数据类型

数据类型 类型标识符 存储大小 数据范围
字符型 char 1B [-2^7, 2^7-1]
短整型 short 2B [-2^15, 2^15-1]
整型 int 4B [-2^31, 2^31-1]
单精度浮点数 float 4B [-2^128, 2^128]
双精度浮点数 double 8B [-2^1024, 2^1024]
长整型 long 4B [-2^31, 2^31-1]
长长整型 long long 8B [-2^63, 2^63-1]
无符号整型 unsigned int 4B [0, 2^32-1 ]
无符号长整型 unsigned long 4B [0, 2^32-1]
无符号长长整型 unsigned long long 8B [0, 2^64-1]

补充知识: sizeof 关键字
作用:利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof(数据类型或变量)

6. 变量名

变量:类似于我们数学上所学习的 x、y
作用:给一段指定的内存空间起名,方便操作这段内存
语法:数据类型 变量名 = 初始值;

变量名:在计算机语言中变量表示某个存储数据空间的名称。
它的命名有如下规则:
(1)变量名中只能出现字母(A~Z,a~z)、数字(0~9)或者下划线。
(2)第一个字符不能是数字。
(3)不能是C++关键字。所谓关键字,即C++中已经定义好的有特殊 含义的单词。
(4)区分大小写。

变量名补充:
(1)对变量名(也就是标识符)的长度没有统一规定,随着系统的不同而有不同的规定,一般来说,C++编译器可以识别前31个字符,所以标识符的长度不要超过31位。
(2)给标识符命名时,争取做到见名知意的效果,方便自己和他人的阅读。

关键字
关键字(keyword)又称保留字,是整个语言范围内预先保留的标识符。
每个关键字都有特殊的含义。经过预处理后,关键字从预处理记号(preprocessing-token)中区别出来,剩下的标识符作为记号(token),用于声明对象、函数、类型、命名空间等。不能声明与关键字同名的标识符(变量,函数等)。

C语言一共有32个关键字,如下表所示:

关键字 说明
auto 声明自动变量
short 声明短整型变量或函数
int 声明整型变量或函数
long 声明长整型变量或函数
float 声明浮点型变量或函数
double 声明双精度变量或函数
char 声明字符型变量或函数
struct 声明结构体变量或函数
union 声明共用数据类型
enum 声明枚举类型
typedef 用以给数据类型取别名
const 声明只读变量
unsigned 声明无符号类型变量或函数
signed 声明有符号类型变量或函数
extern 声明变量是在其他文件正声明
register 声明寄存器变量
static 声明静态变量
volatile 说明变量在程序执行中可被隐含地改变
void 声明函数无返回值或无参数,声明无类型指针
if 条件语句
else 条件语句否定分支(与 if 连用)
switch 用于开关语句
case 开关语句分支
for 一种循环语句
do 循环语句的循环体
while 循环语句的循环条件
goto 无条件跳转语句
continue 结束当前循环,开始下一轮循环
break 跳出当前循环
default 开关语句中的“其他”分支
sizeof 计算数据类型长度
return 子程序返回语句(可以带参数,也可不带参数)循环条件

补充: C++关键字如下

作用类型 关键字
数据类型 void,int,char,float,double,bool,w_char
类型定义 struct,union,enum,class,typedef
常量值 true,false
类型修饰符 long,short,singed,unsigned
类型限定符 const,volatile,restrict
存储说明符 auto,register,static,extern,thread_local,mutable
其它修饰符 inline,asm
循环控制 for,while,do
跳转控制 break,continue,return,goto
分支结构 if,else,switch,case,default
内存管理 new, delete
运算符 sizeof,and,and_eq,bitand,bitor,compl,not,not_eq,or,or_eq,xor,xor_eq
访问限定符 this,friend,virtual,mutable,explicit,operator
类访问修饰符 private,protected,public
模板 template,typename
命名空间 namespace,using
异常处理 throw,try,catch

7. 运算符

算术运算符

符号 作用 使用 备注
+ 1+2=3
- 1-2=-1
* 1*2=2
/ 1/2=0
1.0/2=0.5
如果/两边都为整数,则结果取整;
如果有一个是浮点数,则结果为浮点数
% 模,取余数 1%2=1 %符号两边必为整数
++ 加1 a++;
++a;
a++:先使用再加
++a :先加再使用
-- 减1 a--;
--a;
a--:先使用再减
--a:先减再使用

赋值运算符

符号 使用 作用
+= a += 2; 等同于 a = a + 2;
-= a -= 2; 等同于 a = a - 2;
*= a *= 2; 等同于 a = a * 2;
/= a /= 2; 等同于 a = a / 2;
%= a %= 2; 等同于 a = a % 2;

算数运算符的4个注意

  1. a / b,若 a,b均为整数,则结果为整数,若其中一个为浮点数,则结果为浮点数;
  2. a % b ,要求:a, b均为整数;
  3. 遵循算数的自然特征,如分母不为0;
  4. 防止数据长度溢出。

补充:赋值运算符

  1. 由于赋值运算符=右边的表达式也可以是赋值表达式,因此,下述形式 :变量=(变量=表达式);
    是成立的,从而形成嵌套的情形。其展开之后的一般形式为:变量=变量=…=表达式;
    例如a=b=c=d=e=5;,它实际上等价于:e=5;d=e;c=d;b=c;a=b;

  2. 在进行赋值运算时,如果赋值运算符两边的数据类型不同,系统将会自动进行类型转换,即将赋值运算符右边的数据类型转换成左边的变量类型。当左边是整型而右边是实型时,将去掉小数部分并截取该整型对应的有效位数。

8. 数学表达式

函数名 格式 功能 举例
向下取整 floor(x) 不大于x的最大整数 floor(3.14)=3
向上取整 ceil(x) 不小于x的最小整数 ceil(3.14)=4
指数函数 pow(x,y) 计算y个x的乘积 pow(3,2)=3*3=9
平方根函数 sqrt(x) 求x的平方根 sqrt(9)=3
绝对值函数 abs(x) 求x的绝对值 abs(-3)=3
随机值函数 rand() 随机生成一个0~pow(2,16)-1的整数 rand()=41
自然数指数函数 exp(x) 求实数x的自然指数ex exp(1)=2.718282
自然对数函数 log(x) 求实数x的自然数对数 log(1)=0

使用前需导入头文件:#include<math.h>

9. 常量

常量的作用:用于记录程序中不可更改的数据
常量的书写:大写
常量的特性:只读不可写

两种定义常量的方式
方式一: const int X = 2;
定义的常量X=2,且不能修改,否则报错,如以下程序就会报错:

const int X = 2;
X = 3;     //error

一般我们将常量定义在外面,但是也可以定义在main中。

方式二:#define 常量名 常量值
预编译指令,也称宏定义,通常在文件上方定义,表示一个常量
如:#define PI 3.14,相当于PI = 3.14,以后就可以直接使用 PI。

注意:const所谓的常量是指只读变量,并不是真正意义上的常量。

10. 运算符补充

类型 作用
1.算术运算符 用于各类数值运算。包括加(+)、减(-)、乘(*)、除(/)、求余(或称模运算,%)、自增(++)、自减(--)共七种。
2.关系运算符 用于比较运算。包括大于(>)、小于(<)、等于(==)、大于等于(>=)、小于等于(<=)和不等于(!=)六种。
3.逻辑运算符 用于逻辑运算。包括与(&&)、或(||)、非(!)三种。
4.位操作运算符 参与运算的量,按二进制位进行运算。包括位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)六种。
5.赋值运算符 用于赋值运算,分为简单赋值(=)、复合算术赋值(+=,-=,*=,/=,%=)和复合位运算赋值(&=,|=,^=,>>=,<<=)三类共十一种。
6.条件运算符 这是一个三目运算符,用于条件求值(?:)。
7.逗号运算符 用于把若干表达式组合成一个表达式(,)。
8.指针运算符 用于取内容(*)和取地址(&)二种运算。
9.求字节数运算符 用于计算数据类型所占的字节数(sizeof)。
10.特殊运算符 有括号(),下标[],成员(->,.)等几种。

说明:大体的运算顺序是:先乘除,再加减,后赋值

或者:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

如果真的记不住,那么可以通过()来改变运算优先顺序,()内先运算。

优先级 运算符 名称或含义 使用形式 结合方向 说明
1 [ ] 数组下标 a[100] 左到右
( ) 圆括号 a*(b+c)
. 成员选择(对象) a.b
-> 成员选择(指针) a->b
2 +, - 正运算符,负运算符 +a,-a 右到左 单目运算符
! 逻辑非运算符
~ 按位取反运算符
++,-- 自增运算符,自减运算符 ++a, a++,--a, a--
*,& 取值运算符,取址运算符 *a,&a
(type) 强制类型转换 (int)a
sizeof 长度运算符 sizeof(float)
3 *,/,% 乘,除,取余 a%b 左到右 双目运算符
4 +,- 加,减 a+b
5 << ,>> 左移, 右移 a>>1, b<<c
6 >, >= 大于, 大于等于 a > b, a >= b
<, <= 小于, 小于等于 a < b, a <= b
7 ==, != 等于,不等于 a == b, a != b
8 & 按位与 a&b
9 ^ 按位异或 a^b
10 | 按位或 a|b
11 && 逻辑与 a&&b
12 || 逻辑或 a||b
13 ? : 条件运算符 a?b:c 右到左 三目运算符
14 = 赋值
*=, /=, %= 乘(除/取余)后赋值
+=, -= 加(减)后赋值
<<=, >>= 左(右)移后赋值
&=, |=, ^= 按位与(或/异或)后赋值
15 , 逗号运算符 int a, b; 左到右

运算符优先级baike

11. 类型转换

  1. 自动类型转换
  2. 强制类型转换
  3. 字符型和整型的转换

1.自动类型转换
在不同数据类型的混合运算中,编译器会隐式地进行数据类型转换,称为自动类型转换。
自动类型转换遵守以下规则:
(1)若参与运算的数据类型不同,则先转换成同一类型,然后进行运算。
(2)转换按数据长度增加的方向进行,以保证精度不降低。例如int类型和long long类型运算时,先把int转换为long long后再运算。
(3)在赋值运算中,赋值号两边的数据类型不一样时,将把右面表达式的类型转换为左边变量的类型。如果右边表达式的数据类型长度比左边的长时,将丢失一部分数据。
即:char -->short -->int --> float -->double

2.强制类型转换
当自动类型转换不能实现目的时,可以显示的进行类型转换,称为强制类型转换。
强制类型转换的一般形式是: (类型名)(表达式) (类型名)变量
如(double)a 是将a转换为double型,
(int)(x + y) 是将 x+y 的值转换为整型,
(float)5/3 是将 5 的值转换成float型,再与 3 运算。
double为双精度浮点型,float为单精度浮点型,区别在于他们的精度不同。

3.字符型和整型的转换
将一个字符放到内存单元时,实际上并不是把该字符本身放到内存中,而是将该字符的ASCII代码放到存储单元中。
如字符变量c1的值是'a',c2的值是'b',则在变量中存放的是 'a' 的ASCII码97,'b' 的ASCII码98

12. C语言输入输出

基本输入输出格式 输入 输出
符号 scanf printf
int类型的输入输出 scanf("%d",&a); printf("%d",a);
float类型的输入输出 scanf("%f %f",&a, &b); printf("%f %f",a, b);
double类型的输入输出 scanf("%lf",&a); printf("%lf",a);

注意:使用前需要导入头文件#include<stdio.h>

#include<stdio.h>
int main(){
    int a;
    scanf("%d", &a);    //输入并赋值给a,注意输入有符号&,输出没有
    printf("a = %d\n", a);    //输出a的值,并换行

    float b;
    scanf("%f", &b);
    printf("b = %f\n", b);    //输出b,默认保留小数后6位
    printf("b = %.4f\n", b);//输出b,保留小数后4位

    double c;
    scanf("%lf", &c);
    printf("c = %6.4lf\n", c);//输出c,宽度为6,保留小数后4位

    long long d;
    scanf("%ld", &d);
    printf("d = %ld\n", d);//输出d

    //也可以一起使用
    printf("a = %d b = %f c = %lf d = %lld\n",a,b,c,d);
    printf("a = %d b = %2.3f c = %3.4lf d = %lld\n",a,b,c,d);
    return 0;
}

函数名:scanf
功 能:执行格式化输入
用 法:int scanf(char *format[,argument,...]);
scanf()函数是通用终端格式化输入函数,它从标准输入设备(键盘) 读取输入的信息。
可以读入任何固有类型的数据并自动把数值变换成适当的机内格式。
其调用格式为: scanf("<格式化字符串>",<地址表>);
scanf()函数返回成功赋值的数据项数,出错时则返回EOF

格式表示 意义
%c 一个(ASCII)字符,一个汉字实际上在内存中要占据两个字符的位置。
%s 一串字符,字符串。
%nd %ld 一个十进制整数,n为输出占位宽度。
printf(“%12d”,a); 如a为数字8,则前面补齐11个空格, ld表示 长整型数据
%nx %nX 一个十六进制整数,n为输出占位宽度。
%no 一个八进制整数,n为输出占位宽度。
%n.mf 单精度浮点数,n代表该浮点数的占位宽度,.m代表小数点后保留几位
a为12.2324,printf(“%.3”,a); 12.232,自动四舍五入。
%n.mlf 双精度浮点数,n代表该浮点数的占位宽度,.m代表小数点后保留几位
a为12.2324,printf(“%.3”,a); 12.232,自动四舍五入。
%E 输出科学计数法,12.12 输出为 1.212000E+001,只适用 float,double。
%p 指针(变量的地址)
%% 输出时有用,表示输出一个%

注意:格式在输入时不能有,在输出时可以有也可以没有
注意:%为变量占位符,\只在printf中使用,为特殊字符的转义字符


13. 转义字符

作用:用于表示一些不能显示出来的ASCII字符
现阶段我们常用的转义字符有: \n \\ \t

转义字符 含义 ASCII码值(十进制)
\a 警报 007
\b 退格(BS) ,将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF) ,将当前位置移到下一行开头 010
\r 回车(CR) ,将当前位置移到本行开头 013
\t 水平制表(HT) (跳到下一个TAB位置) 009
\v 垂直制表(VT) 011
\\ 代表一个反斜线字符"\" 092
' 代表一个单引号(撇号)字符 039
" 代表一个双引号字符 034
? 代表一个问号 063
\0 数字0 000
\ddd 8进制转义字符,d范围0~7 3位8进制
\xhh 16进制转义字符,h范围0 ~ 9,a ~ f,A ~ F 3位16进制

14. 实例练习

1.地球人口承载力估计【小学奥数7653】

假设地球上的新生资源按恒定速度增长。照此测算,地球上现有资源加上新生资源可供x亿人生活a年,或供y亿人生活b年。为了能够实现可持续发展,避免资源枯竭,地球最多能够养活多少亿人?

输入:一行,包括四个正整数 x,a,y,b,两个整数之间用单个空格隔开。x>y,a<b,ax<by,各整数均不大于10000
输出:一个实数z,表示地球最多养活z亿人,舍入到小数点后两位。
样例输入: 110 90 90 210
样例输出: 75.00

本题题解
本题目主要找到平衡点,也就是不变量来建立等式
本题目所求的是避免资源枯竭,地球最多能够养活多少亿人,也就是说在现有资源不被消耗的情况下,刚好将新增资源消耗完毕的时候,能养活多少人,也就是要求出新生资源的增长速度。
由于题目中说明新生资源按恒定速度增长,证明新生资源的增长速度是一个定量,那么我们假设该定量为 m.
又地球上现有资源加上新生资源可供x亿人生活a年,或供y亿人生活b年。
首先,现有资源一定是一个定量,新生资源由于ab的变化在发生变化,所以我们可以建立以下等式
现有资源 = x*a - m*a;
现有资源 = y*b - m*b;
所以 m = (x*a-y*b)/(a-b);

所以标程(针对本题的解答程序)如下:

#include<stdio.h>
int main(){
    int x,a,y,b;
    scanf("%d %d %d %d",&x, &a, &y, &b);
    double z = 1.0*(x*a-y*b)/(a-b);
    printf("%.2lf", z);
    return 0;
}

2.数学中经典的"鸡兔同笼"问题,已知头共30个,脚共90只,问笼中的鸡和兔各有多少只?

解决方案一:
    听我口令,所有动物,提起一只脚
    听我口令,所有动物,提起第二只脚
    好了,现在着地的还有90-30-30=30只脚
    由于鸡只有两只脚,所以这时候的全部鸡都是跪着的,
    这30只脚应当都是兔子的,每只兔子有4只脚,提起2只,还剩2只
    所以兔子的数量为:30/2=15只
    所以鸡的数量为30-15只

解决方案二:
    差值求解
    假设都为兔,则 缺少 30*4 - 90 = 30支脚
    所以这 缺少的脚就是鸡, 所以鸡的数量 = 30/2=15;
    兔的数量 = 30-15;

解决方案三:
    列方程,设鸡 x只,兔 y只, 则
    x + y = 30
    2*x + 4*y = 90
    解得 x = 15, y = 15

解决方案四:
    循环遍历,假设 鸡兔都为0只,每次递增+1,直到满足方案三中方程的xy出现
    输出结果
#include<stdio.h>
int main(){
    int x,y;
    x = (30*4-90)/2;
    y = 30-x;
    printf("%d %d\n", x, y);
    return 0;
}

3.计算并联电阻的阻值
对于阻值为r1和r2的电阻,其并联电阻阻值公式计算如下:R = 1/(1/r1 + 1/r2)。
输入两个电阻阻抗大小,浮点型。输出并联之后的阻抗大小,结果保留小数点后2位。
输入:两个电阻阻抗大小,浮点型,以一个空格分开。
输出:并联之后的阻抗大小,结果保留小数点后2位
样例输入:1 2
样例输出:0.67

#include<stdio.h>
int main(){
    double r1,r2,R;
    scanf("%lf%lf", &r1, &r2);
    R = 1/(1/r1+1/r2);
    printf("%.2lf\n", R);
    return 0;
}

4.海伦公式
传说古代的叙拉古国王海伦二世发现的公式,利用三角形的三条边长来求取三角形面积。已知△ABC中的三边长分别为a,b,c,求△ABC的面积。(提示:海伦公式)

\[p = {(a+b+c)}\div {2} \\ \quad \\ s = \sqrt{p*(p-a)*(p-b)*(p-c))} \]

#include<stdio.h>
#include<math.h>
int main(){
    double a, b, c, p, s;
    scanf("%lf%lf%lf", &a, &b, &c);
    p = (a+b+c)/2;
    s = sqrt(p*(p-a)*(p-b)*(p-c));
    printf("%.2lf\n", s);
    return 0;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM