main函数
main函数的基本信息
数顾名思义其实与数学的函数类似,只不过C语言的函数是更为广义的函数,表示为一种处理问题的方法。下面是函数的常见形式,且下面的函数是主函数。
|
|
其中:
int
部分是返回类型。
main
部分是函数名,类似数学函数中的f、g。
void
部分是参数,类似于数学函数中的自变量,如f(x,y)。
return 0;
表示返回一个0的数值。
关于返回类型,是用于告诉计算机函数返回值的类型,如:整型、浮点型、字符型、无返回(实际上无返回不代表真的无返回,知道即可)。类似于数学的整数、小数。更详细的解释看下面的变量。
在此,只需了解到此即可。重点是记住主函数的基本形式。缺斤少两不一定不能运行,但这是一个不好的习惯。
main函数的作用
对于一个程序,我们通常会存放很多函数。如果我们直接将一个程序从头到尾执行,必然会导致很多问题,比如:我们无法多次使用同一个函数,他的逻辑会非常混乱,难以移植等等。
因此C语言规定,在初始化完成后,程序只执行main函数里的内容,如果其中调用到其他函数,则再跳到其他函数执行里面的内容,并将返回值返回给主函数或其他函数。
变量与赋值
变量的定义
在程序中,我们通常需要一些变量来存储一些数值,来计算。这与数学中的变量类似。
变量的类型
由于计算机的存储的原理,我们无法像现实一般,将变量表示成为任何类型。计算机存储的变量通常是有界的。因此我们将变量分为不同类型,方便计算机识别。
变量类型 | 定义符 | 范围 | 例子 |
---|---|---|---|
整型 | int | -32,768 到 32,767 | 2 |
长整型 | long,long int | -2,147,483,648 到 2,147,483,647 | 666666 |
单浮点型 | float | 1.2E-38 到 3.4E+38 | 3.14 |
双浮点型 | double | 2.3E-308 到 1.7E+308 | |
长双浮点型 | long double | 3.4E-4932 到 1.1E+4932 | |
字符型 | char | -128 到 127 | 哈哈6 |
在此简单的叙述一下变量的类型,实际上还能更加细分,剩下的内容,如:细分类型、范围、存储原理等,请自行查询。
变量的存储类型
默认为auto。
变量的初始化
下面为变量的初始化。
|
|
通常,初始化一个变量的步骤为: (修饰)+ 定义符 + 变量名 + (初始化的数值)
值得注意的是,我们可以单独定义变量而不用初始化。
即:int number;
我们也可以定义多个变量,变量中间用,
隔开。
对于字符型,我们规定使用""
表示一句话或单个字符,用''
表示单个字符。
我们还可以用unsigned修饰定义符,表示无符号,即非负。用unsigned修饰时,变量类型的范围也会发生变化。
变量的赋值
变量的赋值是自右向左的,即右边的值(以后简称右值)赋予给左边的值(以后简称左值)。
|
|
运算
与数学类似的我们用+
表示相加,-
表示相减,*
表示相乘,/
表示相除,%
表示求余。
注意事项
一、类型转换
不同类型变量进行运算,低级类型的变量会先转换成高级类型的变量,再进行运算,最后再转换成要赋值的变量的类型。字符串无法转换,但单个字符会根据ASCII码转换成相应的整型。
在C语言中,浮点数比整数高级,范围越大的越高级,但低于int类型的都会转换成int类型再计算。
常量的小数默认是double型。
|
|
二、运算符+等于号
对于运算符加等于号,表示左值与右值先运算,然后再赋予给左值。
|
|
三、求余的限制
在C语言中,只能对整数求余,如果需要对小数求余,则需要调用math.h 中的fmod
函数。
四、自增/自减符
++表示变量递增1,–表示变量递减1。自增/自减可以放于变量前,表示先加/减再用;放于变量变量后,先用再加/减。我们常用自增和自减优化算法。
|
|
stdio.h
库文件
C语言规定.h文件为库文件,库之所以叫库,是因为其中有别人写好的函数,你调用便可以使用。达到一定水平后,我们也可以自己写自己的库。
调用函数
之前我们认识到函数会有返回值,函数名及参数。对于定义一个函数或写主函数,这些都是必不可少的。
但在调用函数时,我们只用像数学一般,直接调用,输入参数即可使用。如果我们要获取其返回值,我们只用将其赋值给变量即可。假如该函数无参数需要输入,那也要带上括号,让编译器知道这是个函数。
|
|
printf
printf的作用
printf的字面意思就是打印,即将文字输出到输出缓冲区(一段系统特定的内存)中,表现为输出文字。
格式控制符
printf拥有多个参数,具体数目根据格式控制符所定。如下所示:
|
|
观察就可以知道所谓的格式控制符,就是 %???
,
一般而言,格式控制符的格式如下:
%[标志][输出最小宽度][.精度][类型长度]类型
方框[]
的部分表示可选。
之所以要有标识符,其实是告诉程序应该在哪打印变量,没有标识符他就会打印出字符,而非变量的值。
标志符
标 志 | 意义 |
---|---|
- | 结果左对齐,右边填空格 |
0 | 输出的字符长度不够时,用0补全 |
+ | 输出符号(正号或负号) |
空格 | 输出值为正时冠以空格,为负时冠以负号 |
# | 对c、s、d、u类无影响; 对o类,在输出时加前缀o; 对x类,在输出时加前缀0x; 对e、g、f 类当结果有小数时才给出小数点。 |
对于标志符,现实中少用到,了解即可。
|
|
最小宽度
用于控制变量输出的长度,对于长度不足的字符,用空格补全。但在标志符中用 0
可以使其用0补全。
|
|
精度
精度主要用于控制小数的位数,遵循四舍五入的原则。
|
|
类型长度
长度格式符为 h
、l
两种,h
表示按短型量输出,l
表示按长型量输出。如果长度格式符与变量类型不匹配,则可能会导致错误。如:%ld
表示输出long
型, %lf
表示输出double
型。
|
|
类型
类型表示一种输出格式,但其也需要与变量类型对应,否则会出错。如:char
对应 c
,字符串对应 s
,整形对应 d
,浮点数对应 f
。
格式字符 | 意义 |
---|---|
d | 以十进制形式输出带符号整数(正数不输出符号) |
o | 以八进制形式输出无符号整数(不输出前缀0) |
x,X | 以十六进制形式输出无符号整数(不输出前缀Ox) |
u | 以十进制形式输出无符号整数 |
f | 以小数形式输出单、双精度实数 |
e,E | 以指数形式输出单、双精度实数 |
g,G | 以%f或%e中较短的输出宽度输出单、双精度实数 |
c | 输出单个字符 |
s | 输出字符串 |
这里仅需记住常用的即可,如:整型、小数、字符串。用法相信经过上面的例子演示,大家也会使用了。这里就不再演示。
转义字符
转义字符的存在,是因为C语言占用了一些字符来表示特定含义,也包括一些无法通过键盘输入的字符或命令。值得注意的是,转义字符也是字符。
转义字符 | 意义 | ASCLL码值(十进制) |
---|---|---|
\a | 响铃(BEL) | 007 |
\b | 退格(BS) ,将当前位置移到前一列 | 008 |
\f | 换页(FF),将当前位置移到下页开头 | 012 |
\n | 换行(LF) ,将当前位置移到下一行开头 | 010 |
\r | 回车(CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表(HT) (跳到下一个TAB位置) | 009 |
\v | 垂直制表(VT) | 011 |
\' | 代表一个单引号 | 039 |
\" | 代表一个双引号字符 | 034 |
\ | 代表一个反斜线字符''' | 092 |
? | 代表一个问号 | 063 |
\0 | 空字符(NUL) | 000 |
\ddd | 1到3位八进制数所代表的任意字符 | 三位八进制 |
\xhh | 十六进制所代表的任意字符 | 十六进制 |
scanf
scanf的作用
scanf是用于读取输入缓冲区的函数,表现为读取输入的内容,包括字符串和数字等。是较为常用的读取函数。
scanf的用法
与printf类似,有多个参数,相同的格式。但不同的是,读取数值或单个字符时,需要加上取地址符 &
。
|
|
还有一个需要注意的地方是,scanf是严格的,即scanf会严格匹配输入的内容。
而且scanf不会读取空格,一旦出现空格,它会认为读取完成(对于读取字符串也是如此)。因此对于读取字符串,我们常用gets而不是scanf,除非是单个单词或者单个字符。
|
|
对于读取多个数据时,scanf会以空格,TAB(缩进),回车,或者非法字符(即与数据类型不相符的数据)作为该数据结束标志。
|
|
格式控制符
对于scanf的格式控制符如下:
%[标志][输入最大宽度][类型长度]类型
方框 []
的部分表示可选。
标志符
scanf的标志符据我了解,只有 *
,用于表示该输入项,读入后不赋予相应的变量,即跳过该输入值。
|
|
输入最大宽度
限制输入的数字或字符串的最大长度。
|
|
类型长度和类型
这两项与printf完全相同,在此就再重复了。
高级格式控制符
持续更新中…
gets 与 puts
gets 与 puts 也是一组读取输出的函数,他们与scanf和printf不同的是,他们只能处理字符串,参数只有一个,即字符串。值得注意的是gets与scanf不同,gets会读取空格,同时也不用清空输入缓冲区。
|
|
getchar 与 putchar
getchar 与 putchar 也是一组读取输出的函数,但只能读取和输出单个字符。getchar无参数(不要忘了括号),putchar的参数是一个字符。
|
|
需要知道的是,虽然我们不常用这两个函数读取或输出字符,但我们常用getchar清空输入缓冲区。
清空缓存区主要是因为用户有时候可能会多输入,不仅如此,对于scanf它读取完内容后会遗留一个回车。如果不清空缓存区,下一次就会直接读取缓冲区的内容,而不会暂停等待用户输入。
所以每使用一次scanf,尽量清空一次缓冲区,这是一个良好的习惯。
|
|
选择判断与布尔运算
布尔运算
布尔运算也称逻辑运算,即只有“真”与“假”的运算。左值与右值满足条件则为真,否则为假。
运算符 | 意义 |
---|---|
== | 等于 |
!= | 不等于 |
>= | 大于等于 |
<= | 小于等于 |
> | 大于 |
< | 小于 |
&& | 与 |
|| | 或 |
! | 非 |
^ | 异或 |
值得注意的是,布尔运算也有优先级。
运算优先级总结
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | -- |
() | 圆括号 | (表达式)/函数名(形参表) | -- | ||
. | 成员选择(对象) | 对象.成员名 | -- | ||
-> | 成员选择(指针) | 对象指针->成员名 | -- | ||
| |||||
2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 |
~ | 按位取反运算符 | ~表达式 | |||
++ | 自增运算符 | ++变量名/变量名++ | |||
-- | 自减运算符 | --变量名/变量名-- | |||
* | 取值运算符 | *指针变量 | |||
& | 取地址运算符 | &变量名 | |||
! | 逻辑非运算符 | !表达式 | |||
(类型) | 强制类型转换 | (数据类型)表达式 | -- | ||
sizeof | 长度运算符 | sizeof(表达式) | -- | ||
| |||||
3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | |||
% | 余数(取模) | 整型表达式%整型表达式 | |||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 | |||
5 | << | 左移 | 变量<<表达式 | 左到右 | 双目运算符 |
>> | 右移 | 变量>>表达式 | |||
| |||||
6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | |||
< | 小于 | 表达式<表达式 | |||
<= | 小于等于 | 表达式<=表达式 | |||
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!= 表达式 | |||
| |||||
8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
| |||||
13 | ?: | 条件运算符 | 表达式1? 表达式2: 表达式3 | 右到左 | 三目运算符 |
| |||||
14 | = | 赋值运算符 | 变量=表达式 | 右到左 | -- |
/= | 除后赋值 | 变量/=表达式 | -- | ||
*= | 乘后赋值 | 变量*=表达式 | -- | ||
%= | 取模后赋值 | 变量%=表达式 | -- | ||
+= | 加后赋值 | 变量+=表达式 | -- | ||
-= | 减后赋值 | 变量-=表达式 | -- | ||
<<= | 左移后赋值 | 变量<<=表达式 | -- | ||
>>= | 右移后赋值 | 变量>>=表达式 | -- | ||
&= | 按位与后赋值 | 变量&=表达式 | -- | ||
^= | 按位异或后赋值 | 变量^=表达式 | -- | ||
|= | 按位或后赋值 | 变量|=表达式 | -- | ||
| |||||
15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 | -- |
总结: 同一优先级的运算符,运算次序由结合方向所决定。 简单而言: ! > 算术运算符 > 关系运算符 > && > || > 赋值运算符
选择结构
if
选择结构
对于 if
选择结构由基本的三个语句构成,分别是:if(条件)
、else if(条件)
、else
。选择结构必须有 if
,但其他两个视情况而定。选择语句可以无限嵌套,简称套娃。但如果 if
选择结构超过了五层,请你好好思考,你的程序设计得合不合理。
以下是常见的 if
选择结构语句。
|
|
程序先判断 if
的条件,如果满足则执行 if
中的代码,并跳出选择结构执行选择结构后的代码;如果不满足 if
的条件,则再判断第一个 else if
的条件,满足则执行其中的代码并跳出;如此判断下去,如果 if
和 else if
的条件都不满足,则直接执行 else
的代码。else
其实就相当于程序的保底。
对于选择结构,如果只有单句代码需要执行,则可以去掉大括号,但别忘了加上分隔符。
|
|
switch
选择结构
|
|
循环语句与结构
循环是程序之所以广泛应用的根本,毫不夸张的说,循环把现代人从许多重复的工作中解脱,极大解放了生产力。现代的编程语言,基本都有选择结构和循环结构,并且他们的语句无比惊人的相同,基本每个语言都有 if
判断、for
循环、while
循环。
但循环虽好,他也有一些需要注意的问题。如果掉以轻心,你可能会写出一个死循环,无限运行循环内的代码,导致计算机死机。
for
循环
对于一个循环,我们很容易想出,要想循环不进入死循环,只需要初始化一个计数变量,用于记录触发的次数,再对计数变量进行判断即可。
下面是 for
循环的基本结构
|
|
同样的,for
循环如果只需执行单个语句,也可以把大括号去掉。
初始化代码
顾名思义就是就是在进行for循环前,执行的代码,通常用于初始化计数变量。在例子中,我便初始化了一个i变量用于计数,当然你也可以像平常初始化变量那样初始化多个变量用于计数,你也可以什么都不写,但不能少了分隔符。
|
|
值得注意的是,对于部分老式编译器,不支持在for循环中进行变量的声明,尤其是在学校的机房里~~(说的就是你大工)~~。这个时候就要将变量的声明放在main函数的下面。
|
|
循环条件
循环条件同选择结构的条件一般,即布尔运算。满足条件则继续循环,否则结束循环。
单次循环结束执行的代码
之所以要有这一步,主要是用于防止循环进入死循环。
观察上述例子我们可以发现,我们通常将计数变量递增作为该部分的代码,用来限制循环的次数。
当然啦,你也可以不写,直接空出来,但你就要在循环体内的代码的结尾手动写上。除非你很清楚自己在干什么。
while
选择结构
了解了for循环,那学会while循环更是易如反掌。他其实就相当于一个不填"初始化代码"和"单次循环结束要执行代码"的for循环。
其实就相当于自己要另外实现这两个功能罢了。
|
|
do...while...
循环
do...while...
循环其实就是先执行一边再判断的 while
循环,与while循环并无太大不同。
但别忘了 while
后有分号。
|
|
数组
对于一维声明数组时初始化,可以不用标明元素个数。对于方括号内的值,仅能为正整数常量及其表达式。
多维数组
对于n维数组,至少要定义n-1维的长度,且定义的维度必须为低维度(即排后面的维度),否则无法初始化。
数组与字符串
函数
对于函数而言,它可以嵌套调用,但不能嵌套定义。
返回值
不论return所返回的值的类型是什么,返回值都会转化为函数类型相同的类型。
字符串处理
strcpy函数
strcat函数
文件处理
fopen函数
FILE *fopen(const char *filename, const char *mode)
模式 | 描述 |
---|---|
“r” | 打开一个用于读取的文件。该文件必须存在。 |
“w” | 创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容,文件被视为一个新的空文件。 |
“a” | 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。 |
“r+” | 打开一个用于更新的文件,可读取也可写入。该文件必须存在。 |
“w+” | 创建一个用于读写的空文件。 |
“a+” | 打开一个用于读取和追加的文件。 |
“rb” | 打开一个用于读取的二进制文件,该文件必须存在 |