C

1. 概述

1.1 诞生

K&B ---> (美国国家标准协会)ANSI C --->

1.2 特点

  • 简洁紧凑
  • 运算符丰富
  • 自由度大
  • 允许直接访问物理地址,直接进行位操作,实现汇编语言大部分功能
  • 可移植性好

1.3 书写原则

  1. 一个说明或一个语句占一行;

  2. {}一般与结构语句第一个字母对齐;

  3. 低一层次的语句或说明要比高一层次或说明缩进若干格后书写;

    总之:书写要使结构更加清晰,增加程序的可读性。

1.4 面向对象

#include<stdio.h>    //include:文件包含命令;.h:拓展名为文件/头文件
void main(){        //main:主函数
    printf("Hello, World!\n");  //输出函数
    return 0;            //返回值
}           //{ } 函数体

1.5 输入输出函数

scanf(" %d", &x);
printf(" %d", x);
/*"格式控制串",表示输入输出量的数据类型。多个量用 , 隔开;其中非格式字符原文打印。
*/

1.6 字符集

  • 字母:小写a~z(26个)

    ​ 大写A~Z(26个)

  • 数字:0~9(10个)

  • 空白符:空格符、制表符、换行符

  • 标点和特殊字符

1.7 词汇

1. 标识符

程序中使用的变量名、函数名、标号等的统称。

规定:只能由字母、数字、下划线(_)组成;

第一个字符只能是字母和下划线

注意:

  1. 标准C原则上不限制标识符长度,但受不同版本C编译系统和机器限制;
  2. 区分大小写;
  3. 命名要做到“顾名思义”。
2. 关键字
  1. 类型说明符:int, double···
  2. 语义定义符:if else···
  3. 预处理命令符:include···
3. 运算符
4. 分隔符

​ 逗号、空格

5. 常量
  1. 数字常量

  2. 字符常量

  3. 字符串常量

  4. 符号常量

  5. 转义字符

    ···

6. 注释符

​ // 、/* ... */

2. 算法

为解决一个问题而采取的方法和步骤。

2.1 特点

  1. 有穷性
  2. 确定性
  3. 有效性
  4. 有0个或多个输入
  5. 有1个或多个输出
  6. 得到确定结果

2.2 表示

1.流程图

表示相应操作的框+流程线+框外必要的文字说明。

  • 椭圆形:起止框;
  • 平行四边形:输入输出框;
  • 菱形:判断框;
  • 矩形:处理框;
  • 带箭头的线:流程线;
常见结构
  • 顺序结构:A ---> B

  • 选择结构:

  • 循环结构:

    先判断,后执行;

    先执行,后判断;

特点:只有一个出口,一个入口;

​ 结构中每部分都有机会被执行;

​ 不存在死循环。

2. N-S流程图
3. 计算机语言

结构化程序设计方法:

  • 自顶向下;
  • 逐步细化;
  • 模块化设计;
  • 结构化编码。

3. 数据类型

按被定义变量的性质、表示形式、占据存储空间的多少、构造特点来划分的。

1. 基本数据类型

不可分割、自我说明

  1. 整型
  2. 字符型
  3. 实型/浮点型
    • 单精度
    • 双精度
  4. 枚举类型
2. 构造类型

可分

  1. 数组类型
  2. 结构体类型
  3. 共用体(联合)类型
3. 指针类型

表示某个变量在内存储器中的地址

4. 空类型:

​ 调用函数值时,通常应向调用者返回一个函数值,但也有一类函数调用后无需向调用者返回函数值,这种函数可视为“空类型”,其说明符为 void

3.1 常量、变量

程序执行过程中,其值不变的的量称常量,其值可变的量称变量

整型常量/变量、浮点(实型)常量/变量、字符常量/变量、枚举常量/变量

  • 常量

    符号常量:用一个标识符表示一个常量

    ​ 须先定义,一般形式:#define 标识符 常量

    #define PI 3.14

    ​ 注意:习惯上,常量标识符用大写字母,变量标识符用小写字母。

    ​ 值在其作用域内不能改变,也不能再被赋值。

  • 变量

    一个变量须有一个名字,占据一定存储单元。

    定义变量,一般放在函数体的开头部分。

1. 整型

(1)整型常量
  • 表示:

    程序中是根据前缀来区分各种进制数的。

    1. 十进制,无前缀;范围:无符号065535;**有符号**-32768+32767
    2. 八进制,以 0 为前缀;范围:无符号0~0177777
    3. 十六进制,以 0X0x 为前缀;数码取值:09,AF或af;范围:*0x00XFFFF*
  • 长整型,以 Ll后缀

    整型的长度一般为16位,所以数的表示有一定范围。如果使用的数超过上述范围,须使用长整型数来表示。

    长整数 158L 和 158 在数值上并无区别,但对 158L ,因为是长整型量,编译系统将给他分配4个字节存储空间;而对158,因为是基本整型,只分配2个字节的存储空间。

  • 无符号数,后缀为 Uu

    无符号数比有符号数省去一位符号位,所以表示数值范围更宽。

(2)整型变量
  • 分类:

    • 基本型:类型说明符为“ int ”,占2个字节,范围:(-215) ~(215-1);

    • 短整型:类型说明符为“ short int ”或“ short ”,占字节和取值范围均与基本型相同;

    • 长整型:类型说明符为“ long int ”或“ long ”,占4个字节;

    • 无符号型:类型说明符为“ unsigned ”,

      可与上述三种类型组合成:

      • 无符号基本型:类型说明符为“ unsigned int ”或“ unsigned ”;
      • 无符号短整型:类型说明符为“ unsigned short ”;
      • 无符号长整型:类型说明符为“ unsigned long ”。

      所占内存空间字节与相应符号类型相同,由于省去符号位,所以不能表示负数。

  • 整型变量的定义:

    • 一般形式:类型说明符 + 变量名标识符 + +变量名标识符 + ··· +

      int x,y;    //变量定义
      long z;
      unsigned = i;
      i=10;   //赋值,初始化
      
    • 注意:

    ​ 1. 类型说明符与变量名标识符之间至少用一个空格隔开;

    ​ 2. 允许在一个类型说明符后,定义多个相同类型的变量,各变量名之间须用逗号隔开;

    ​ 3. 变量定义必须放在变量使用之前,一般放在函数体开头部分。

    • 数值以补码表示;
(3)码值知识
  1. 机器数

​ 一个数在计算机中以二进制表示,这个数就为机器数。机器数带符号,用最高位存放符号,正数记 0 ,负数记 1 。

  1. 真值

​ 由于第一位为符号位,所以机器数形式值并不等于真值

将带符号位的机器数对应的真正数值称为机器数的真值。

  1. 原码

​ 符号位加真值绝对值。

[+1]原 = 0000 0001

[-1]原 = 1000 0001

​ 所以其取值范围为 [1111 1111 , 0111 1111],即 [-127 , 127]

▲原码是人脑最容易理解和计算的表达方式。

  1. 反码
  • 正数的反码是其本身;

  • 负数的反码是在其原码的基础上,符号位不变,其余各个位取反。

    [+1]=[0000 0001]原 =[0000 0001]反

    [ -1]=[1000 0001]原 =[1111 1110]反

▲如果一个反码表示的是负数,人脑无法直观的看出它的数值。

  1. 补码
  • 正数的补码是其本身;

  • 负数的补码是在其原码的基础上,符号位不变,其余各个位取反,然后加1(在反码的基础上加1)。

    [+1]=[0000 0001]原 =[0000 0001]反 =[0000 0001]补

    [ -1]=[1000 0001]原 =[1111 1110]反 =[1111 1111]补

▲补码人脑也是无法直观的看出其数值。

  1. 为什么使用反码、补码

​ 人脑可以知道第一位是符号位,设计一台能辨别“符号位”的计算机,其电路设计很麻烦,人们就想让符号位参与运算。1-1=1+(-1)=0

1-1=1+(-1)=[0000 0001]原+[1000 0001]原=[1000 0010]原=-2

显然不正确。

为解决原码做减法问题,出现了反码。

1-1=1+(-1)=[0000 0001]原+[1000 0001]原

​ =[0000 0001]反+[1111 1110]反

​ =[1111 1111]反

​ =[1000 0000]原

​ =-0

如果用反码计算,结果真值部分正确,唯一的问题出现在 “0” 上,

虽然人脑能理解 “+0” 和 "-0" 是一样的,但 0 带符号无任何意义,而且两个编码表示 “0” 。

为解决0的符号及两个编码问题,出现了补码。

1-1=1+(-1)=[0000 0001]原+[1000 0001]原

​ =[0000 0001]补+[1111 1111]补

​ =[0000 0000]补

​ =[1111 1111]反

​ =[1 0000 0000]原

​ =0

对二进制数来说,先减1后取反和先取反后加1得到的结果是一样的

如此只用 [0000 0000] 表示 0 ,-0的问题就不存在了。

(-1)+(-127)=[1000 0001]原+[1111 1111]原

​ =[1111 1111]补+[1000 0001]补

=[1000 0000]补=-128

=[0111 1111]反[0111 1111]减一

=[1000 0000]原[1000 0000]取反

=-0

由于-128 由之前的 “-0” 的补码表示,所以-128并没有原码和反码表示。

▲使用了补码,不仅解决了 0 的符号及两个编码问题,而且还能够多表示一个最低数。所以8位二进制表示的范围为[-127 , 127];而使用补码表示的范围为[-128 , 127]

  • 整型数据的溢出

    ​ 不同类型的量可以参与运算并相互赋值;

    ​ 其中的类型转换是由编译系统自动完成的;

    ​ 类型转换规则未完待续

2. 实型

实型数据在内存中存放形式:

​ 小数部分占的位数愈多,数的有效数字越多,精度愈高;

​ 指数部分占的位数愈多,则表示的数值愈大。

(1)实型变量
  • 分类:

    • 单精度(float型):占4个字节,只能提供7位有效数字;
    • 双精度(double型):占8个字节,能提供15位有效数字;
    • 长双精度(long double型):占16个字节,能提供19位有效数字;
  • 实型变量定义:

    书写格式同整型。

    float x,y;
    double z;
    
  • 实型数据的舍入误差:

    由于实型变量是由有限的存储单元组成,因此能提供的有效数字总是有限的。

(2)实型常量

实型常量又称实数/浮点数;

标准C允许浮点数使用后缀,后缀为“f”或“F”,300. 和 300F 是等价的;

实型常数不分单精度、双精度,都按双精度double型处理

  1. 十进制数形式:

    注意:必须有小数点。例:300. 、0.0 ···

  2. 指数形式:十进制数 + 阶码标识符“e”或“E” + 阶码。

    ​ 2.1E-5 = 2.1*10-5

3. 字符

(1)字符常量

用一对单括号括起来的一个字符。

例:'a'、'b'、'6'、'='、'?' ···

  • 注意:
    1. 字符常量只能用单引号括起来,不能用双引号或其他括号;
    2. 字符常量只能是单个字符,不能是字符串;
    3. 字符可以是字符集中任意字符,但数字被定义为字符后就不能参与数值运算,即 '5' 和 5 是不同的。
转义字符\

一种特殊的字符常量,以反斜线 ”\“ 开头,后跟一个或几个字符,表示一些用一般字符不便于表示的控制代码

转移字符 意义 ASCⅡ代码
\n 回车换行 10
\t 横跳到下一个制表位置(空格) 9
\b 退格 8
\r 回车 13
\f 走纸换页 12
\\ 反斜线符”\“ 92
\’ 单引号符 39
\” 双引号符 34
\a 鸣铃 7
\ddd 1~3位的八进制数所代表的字符  
\xhh 1~2位16进制所代表的字符  

广义的讲,C语言字符集中任何一个字符均可用转义字符来表示,表中 \ddd 和 \xhh 正是为此提出的。ddd 和 hh 分别为八进制和16进制的ASCⅡ代码,如:\101=1*8^2+1=65,65是字符 'A' 所对应的ASCⅡ代码;\134代表反斜线;\XOA代表换行等。

(2)字符变量

用与存储字符常量,即单个字符。

  • 类型说明符为 char

  • 书写格式与整型相同。

    char a,b;
    
  • 字符数据存储形式:

    • 每个字符变量分配一个字节(8位无符号数)内存空间,只能存放一个字符;

    • 字符值以ASCⅡ码的形式存放在变量的内存单元中;

    • C语言允许对字符变量赋以整型值、整型变量赋以字符值;在输出时也允许把字符变量按整型量输出、整型量按字符量输出,输出形式取决于printf函数格式串中的格式符。(由于整型量为2字节量,当整型量按字符型量处理时,只有低8位字节参与处理。

    #include<stdio.h>
    main(){
        char a,b;
        a='a';
        b='b';
        a=a-32;
        b=b-32;
        printf("%c %c\n%d %d",a,b,a,b); 
        return 0;
    }
    /*
    A B        //输出形式取决于printf函数格式串中的格式符
    65 66      //大小写字母的ASCⅡ码相差32,'A'-65;'a'-97
    */
    

    大小写字母的ASCⅡ码相差32,'A'-65;'a'-97

(3)字符串常量

用一对双括号括起来的字符序列。

例:"CHINA"、"$12.5" ···

  • 注意:

    1. 字符常量由单引号括起来,字符串常量由双引号括起来;

    2. 字符常量只能是单个字符,字符串常量可以含一个或多个字符;

    3. 可以把一个字符常量赋予一个字符变量,但不能把一个字符串常量赋予一个字符变量。C语言中没有相应的字符串变量(与BASIC语言不同),但可以用一个字符数组存放一个字符串常量未完待续

    4. 字符常量占一个字节的内存空间,字符串常量占内存字节数等于字符串中字节数加1,增加的一个字节用于存放字符“\0"(ASCⅡ码为0),标志着字符串的结束。

      例:"C program" 在内存中所占字节

    5. 字符常量 'a' 与字符串常量 "a" 虽然都只有一个字符,但在内存中的情况是不同的

      'a'占一个字节,表示为:|a|

      "a"占两个字节,表示为:|a|\0|

3.2 赋值

1. 初始化

  • 一般形式:类型说明符 + 变量名标识符1 + = + 值1 + , + 变量名标识符2 + = + 值2 + , + ··· + ;

    int a=3;
    int b,c=5;
    float x=3.2,y=3f,z;
    char ch1='A',ch2='B';
    
  • 注意: 定义中不允许连续赋值,例 int a=b=3; 非法的。

3.3运算

1. 类型转换

​ 变量的数据类型是可以相互转换的,但转换只是为了一次运算的需要而对变量的数据长度进行的临时性转换,不改变数据说明时对该变量定义的类型

​ 转换的方法有两种:

(1)自动转换

若参与运算的量的类型不同,则会先自动地转换成同一类型,然后进行运算

  • 规则:

    1. 转换按数据长度增加的方向进行(保证精度不降低)

      如:int型和long型同时运算时,系统会先把int量转换成long型后进行运算

    2. 所有浮点运算都是以双精度进行的,即使仅含有float单精度量运算的表达式,也会先转换成double型,再进行运算;

    3. char型和short型参与运算时,必须先转换成int型;

    4. 在进行赋值运算时,赋值号两边量的数据类型不同时,赋值号右边量的类型将转换成左边量的类型。

      实型赋予整型,舍去小数部分;

      (右边量的数据类型长于左边量,将丢失一部分数据,如此将会降低精度)

      整型赋予实型,数值不变,以浮点数形式存放,增加小数部分,小数部分为0;

      字符型赋予整型,字符型1个字节,整型2个字节,将字符的ASCⅡ码值放到整型量的低八位中,高八位为0;

      整型赋予字符型,只把低8位赋予字符量。

(2)强制转换

强制类型转换是通过类型转换运算来实现的。

  • 一般形式:( + 类型说明符 + ) + ( + 表达式 + )

  • 注意:类型说明符和表达式都必须加括号(单个变量可不加)

    (float)a   //将a转换成实型
    (int)(x+y)     //将 x+y 的结果转换成整型
    (int)b+c      //将b转换成int型后与c相加
    

2. 优先级、结合性

(1)优先级

C语言中运算优先级分15级,1级最高,15级最低。

1. () [] . ->          //特殊运算符第一
2. !(非) ~(位非) -(负号) ++ -- &(取变量地址) *(取变量内容) (type) (强制类型) sizeof(求字节)   //全体单目第二
3. * / %        //乘、除、模第三
4. + -          //加减第四
5. << >>            //左移、右移第五
6. > >= < <=       //大小第六
7. == !=         //等不等第七   关系运算符六七
8. &(位与)       //8
9. ^(位异或)     //9
10.|(位或)       //10
11. &&        //与11
12. ||        //或12
13.?:         //条件(三目运算符)倒三
14. = += -= *= /= %= |= ^= &= >>= <<=  //赋值倒二
15.,         //逗号最低
(2) 结合性
  • 右结合性:自右至左运算;

  • 左结合性:自左至右运算。

    单目运算符、三目运算符、赋值运算符具有右结合性。

3. 运算符、表达式

(1)特殊运算符

优先级最高。

​ 括号()、下标[]、成员(→,.)等

(2)算术运算
  • 算术运算符

  • 加法运算符 + ,双目运算符,左结合性。

    双目运算符即应有两个量参与运算,如:a+b,4+8

  • 减法运算时 - ,作双目运算符,左结合性;负值运算时 - ,作单目运算符右结合性

    单目运算符仅有1个量参与运算,如:-1,-a

  • 乘法运算符 * ,双目运算符,左结合性。

  • 除法运算符 / ,双目运算符,左结合性。

    参与运算量均为整型时,结果为整型,舍去小数;

    但如果运算量有一个是实型,结果为双精度实型。

  • 取余/模运算符 % ,双目运算符,左结合性。

    要求:参与运算的量均为整型。

  • 自增、自减运算符 ++、-- ,单目运算符右结合性

    //对++i,--i系统在原地址处理,输出的值也从原地址中取;对i++,i--则先产生一个临时地址,然后在原地址处理,输出的值从临时地址取。
    ++i      //等价于i=i+1,自增1后再参与其他运算
    i++      //i参与运算后,再参与其他运算
    
    #include<stdio.h>
    main(){
        int i=8;
        printf("%d\n",++i);  //i=8,自增1,i=9,输出9
        printf("%d\n",--i);  //i=9,自减1,i=8,输出8
        printf("%d\n",i++);  //i=8,输出8,自加1,i=9
        printf("%d\n",i--);  //i=9,输出9,自减1,i=8
        printf("%d\n",-i++); //i=8,-i=-8,输出-8,自加1,i=9
        printf("%d\n",-i--); //i=9,-i=-9,输出-9,自减1,i=10
        i=8;
        printf("%d,%d,%d,%d\n",++i,--i,i++,i--); 
        /*
        i--,将i地址中8放入一个临时地址,原来地址-1填入,得7
        i++,将i地址中现在值7放入一个临时地址,原来地址+1,得8
        --i,将i直接-1,得7
        ++i,将i直接+1,得8
        然后,输出:8(原地址),8(原地址),7(临时地址),(临时地址)
        */
        //8,8,7,8
    }
    
    //单目运算符++、--高于 +、-
    main(){
     int i=5,j=5,p,q;
     p=(i++)+(i++)+(i++);    //三个i=5相加,p=15,后i自加三次i=8
     q=(++j)+(++j)+(++j);    //j先自加三次(单目),j=8,三个j相加,q=24
     printf("%d,%d,%d,%d",p,q,i,j);   //15,24,8,8
    }
    
  • 算术表达式:

    由常量、变量、函数和算术运算符、括号组成起来的式子。

    求值规则:

    1. 按运算符优先级进行;

    2. 一个运算量两侧运算符优先级相同时,按结合性规定的结合方向进行。

(3)赋值运算
  • 赋值运算符 =,右结合性。

  • 赋值表达式:变量 + “=” + 表达式

    将计算表达式的值赋予左边的变量。C语言把 “=” 定义为运算符,从而组成赋值表达式,其他高级语言中,赋值构成了一个语句,称赋值语句。C中也有赋值语句(以分号结尾),例:x=8; a=b=5;

  • 注意:

    1. 如果赋值运算符两边的数据类型不相同,系统将自动进行类型转换,把赋值号右边量的类型转换成左边量的类型。

      实型赋予整型,舍去小数部分;

      整型赋予实型,数值不变,以浮点数形式存放,增加小数部分,小数部分为0;

      字符型赋予整型,字符型1个字节,整型2个字节,将字符的ASCⅡ码值放到整型量的低八位中,高八位为0;

      整型赋予字符型,只把低8位赋予字符量。

    2. 赋值表达式不同于赋值语句未完待续

(4)逗号运算符

优先级最低。

  • 逗号表达式:表达式1 + , + 表达式2
    • 功能:把两个表达式连接起来组成一个表达式,分别求两个表达式的值,以表达式1的值作为整个逗号表达式的值。

      main(){
          int a=2,b=4,c=6,x,y,z;
          y=(x=a+b),(b+c);  //先x=a+b=2+4=6,然后y=(x=a+b)=6,再然后(b+c)=10
          z=((x=a+b),(b+c)); //运算顺序同上,然后表达式2即(b+c)的值10作为逗号表达式的值赋予z
          printf("y=%d,x=%d,z=%d",y,x,z);    //y=6,x=6,z=10
      }
      
    • 注意:

      • 表达式1、2也可以是逗号表达式,嵌套。

        (表达式1,(表达式2,表达式3))=(表达式1,表达式3)=表达式3

        所以可把逗号表达式扩展为:

        ​ 表达式1,表达式2,表达式3, ··· ,表达式n

        其值等于表达式n的值。

      • 程序中使用逗号表达式,通常是要分别求逗号表达式内各表达式的值,并不一定要求整个逗号表达式的值。

      • y=a,b+c 不等于 y=(b+c),y=a为1表达式,整个逗号表达式的值为(b+c)。想要做到 y=(b+c) 的效果,须如此写:y=(a,b+c)。

      • 并不是所有出现逗号的地方都组成逗号表达式,如在变量说明中,函数参数表中逗号只是用作各变量之间的间隔符

(5)关系运算符

​ 6种:大于(>)、小于(<)、等于(==)、大于等于(>=)、小于等于(<=)、不等于(!=)

(6)逻辑运算符

​ 3种:与(&&)、或(||)、非(!)

(7)位操作运算符

参与运算的量按二进制进行运算

​ 6种:位与(&)、位或(|)、位非(~)、位异或(^)、左移(<<)、右移(>>)

(8)条件运算符

C语言中唯一1个三目运算符 "?:",用于条件求值:

a=(b>0)?b:-b;   //当b>0时,a=b;当b不大于0即b<=0时,a=-b。

优先级高于赋值、逗号运算符,低于其他运算符。

(9)指针运算符

​ 2种:用于取内容的 “*” 、用于取地址的 ”&

(10)求字节运算符

​ 用于计算数据类型所占的字节数 ”(sizeof)

​ 使用形式:sizeof(数据类型)

小结1

  1. 数据类型

    基本类型、构造类型、指针类型、空类型

  2. 基本类型的分类及特点

      类型说明符 字节 数值范围
    字符型 char 1  
    基本整型 int 2  
    短整型 short int 2  
    长整型 long int 4  
    无符号型 unsigned 2  
    无符号长整形 unsigned long 4  
    单精度实型 float 4  
    双精度实型 double 8  
  3. 常量后缀

    • 长整型:L/l
    • 无符号数:U/u
    • 浮点数:F/f
  4. 常量类型

  5. 数据类型转换

  6. 优先级、结合性

  7. 表达式

    由运算符连接常量、变量、函数所组成的式子。

  8. 表达式求值

4. C语句

4.1概述

  • 从程序流程的角度来看,程序可分为三种基本结构:顺序结构、分支结构、循环结构。三种基本结构组成所有复杂程序。

  • C程序结构:

  • C程序的执行部分由语句组成,程序的功能也是由执行语句实现。

  • C语句

    1. 表达式语句

      • 一般形式:表达式 + ;

        x=y+z;      //赋值语句
        y+z;       //加法运算语句,但计算结果不能保留,无实际意义
        i++;       //自增1语句
        
      • 执行表达式语句即计算表达式的

    2. 函数调用语句

      • 一般形式:函数名 + ( + 实际参数表 + ) + ;

      • 执行函数语句即调用函数体并把实际参数赋予函数定义中的形式参数,然后执行被调函数体中语句,求取函数

        printf("Hello, World");     //调用库函数,输出字符串
        
    3. 控制语句

      控制程序流程,实现程序的各种结构。由特定的语句定义符组成。

      1. 条件判断语句

        if 语句、switch 语句

      2. 循环执行语句

        do while 语句、while 语句、for 语句

      3. 转向语句

        break 语句、goto 语句、continue 语句、return 语句

    4. 复合语句

      把多个语句用大括号 {} 括起来的一个语句。程序中应把复合语句看成单条语句。

      {
          x=x+z;
          a=b+c;
          printf("%d %d",x,a);
      }                    //一条复合语句
      

      注意:复合语句内各条语句必须以分号结尾;在 } 外不能加分号

    5. 空语句

      只有分号组成的语句。什么也不执行,在程序中空语句可作空循环体。

      while(getchar()!='\n')  //只要从键盘输入的字符不是回车则重新输入
          ;         
      

4.2 常见语句

  1. 赋值语句

    • 一般形式:变量 + = +表达式 + ;

      “赋值表达式 + ; ”,为表达式语句

    • 注意:

      1. 赋值语句中表达式也可以是赋值表达式 ,嵌套

        变量=(变量=表达式)

        展开得一般形式:变量=变量= ··· =表达式

        a=b=c=d=5;
        /*
        赋值运算符 = ,具有右结合性(从右向左进行运算)
        所以,连续赋值等效于:
        	d=5;
        	c=d;
        	b=c;
        	a=b;
        */
        
      2. 赋值表达式与赋值语句的区别:

        赋值表达式是一种表达式,可以出现在任何允许表达式出现的地方,而赋值语句不能。

        if((x=y+5)>0) z=x; //合法

        if((x=y+5;)>0) z=x; //非法,语句不能出现在表达式中

      3. 变量说明中给变量赋初值和赋值语句的区别:

        1. 变量赋初值时变量说明的一部分,赋初值后的变量与其后的同类型的变量间必须用逗号相隔;赋值语句必须用分号结尾。

        2. 变量说明中不允许连续给多个变量赋初值;赋值语句允许连续赋值。

          int a=b=c=5; //非法

          //想达到上效果可改写成如下

          int a=5,b=5,c=5;

  2. 输入、输出

    C语言中,所有数据的输入/输出都是由库函数完成的,因此都是函数语句

    使用C语言库函数时,要用预编译命令 #include ,将有关头文件包含到源文件中;

    使用标准输入输出库函数时,要用到 stdio.h 文件;

    所以在源文件开头应有预编译命令:

    #include<stdio.h>#include"stdio.h"

    stido:standard input & output (标准输入输出)

    但因为 printf 和 scanf 函数使用频繁,系统允许在使用这两个函数时不加如上预编译命令。

    • 字符数据的输入输出

      • putchar 函数

        字符输出函数

        一般形式:putchar(字符变量);

        putchar('A');   //输出大写字母A
        putchar('\101');  //\101=65,为'A'的ASCⅡ代码,所以输出字符'A'
        putchar(x);     //输出字符变量x的值
        putchar('\n');   //换行
        //对于控制字符则执行控制功能,不在屏幕上显示。
        
      • getchar 函数

        键盘输入函数

        一般形式:getchar();

        通常把输入字符赋予一个字符变量,存储输入字符:

        #include<stdio>
        void main{
            char c;
            printf("输入一个字符"\n);
            c=getchar();
            putchar(c);    //输出刚才输入的字符
            /*
            也可将后两行改成如下任一:
            putchar(getchar);
            printf("%c",getchar());
            */
        }
        

        注意:

        1. getchar 函数只能接受单个字符,输入多于1个字符时只接收第一个字符;

        2. 输入数字也按字符处理;

    • 格式输入输出

      • printf 函数

        格式输出函数,末尾 f 为 format(格式) 之意。

        把用户指定的格式,指定的数据显示到显示器屏幕上。

        一般形式:printf("格式控制字符串",输出表列);

        1. 格式控制字符串可由格式字符串和非格式字符串两种组成。

          • 格式字符串是以 % 开头的字符串,% 后跟有各种格式字符,以说明输出数据类型、形式、长度、小数位数等。

            格式字符串:

            在Turbo C中格式字符串的一般形式为:

            ​ [标志] [输出最小宽度] [.精度] [长度] 类型

            1. 类型:

              格式 意义
              d 以十进制形式输出带符号整数(正数不输出符号)
              o 以8进制形式输出无符号整数(不输出前缀0)
              x,X 以16进制形式输出无符号整数(不输出前缀0X)
              u 以十进制形式输出无符号整数
              f 以小数形式输出单精度(有效数字7位)**实数 **
              lf 以小数形式输出双精度(有效数字16位)实数
              e,E 以指数形式输出单、双精度实数
              g.G 以%f或%e中较短的输出宽度输出单、双精度实数
              c 输出单个字符
              s 输出字符串
            2. 标志

              标志 意义
              - 结果左对齐,右边填空格
              + 输出符号(正号或符号)
              空格 输出值为正时冠以空格,为负时冠以符号
              # 对c,s,d,u类无影响;对o类,在输出时加前缀0;对x类,在输出时加前缀0x,对e,g,f类当结果有小数时才给出小数点
            3. 输出最小宽度

              十进制整数来表示输出的最小位数。

              正负号也占一个宽度。

              若实际位数多于定义的宽度,则按实际位数输出;

              若实际位数少于定义宽度,则补以空格或0。

            4. 精度

              精度格式符以 . 开头,后跟十进制整数

              若输出数字,则表示小数的位数;

              若输出的是字符,则表示输出字符的个数。

              若实际位数大于所定义的精度数,则截去超过的部分。

            5. 长度:长度格式符:h ,代表按短整型量输出。 L ,代表按长整型量输出。

          • 非格式字符串在输出时原样照印,在显示中起提示作用。

        2. 输出列表中要给各个输出项,要求格式字符串和各输出项和类型上一一对应。

          注意:

          • 不同编译系统输出列表的求值顺序也不尽相同,可以从左到右,也可以从右到左。(一般为从右到左,*Turbo C 是按从右到左进行的)
          • 对++i,--i系统在原地址处理,输出的值也从原地址中取;对i++,i--则先产生一个临时地址,然后在原地址处理,输出的值从临时地址取。
        #include<stdio.h>
        void main(){
            int a=15,b=-10;
            float c=123.456789;        //float 仅7位有效数字
            double d=12345678.12345678;  //double 可有15位有效数字
            char e='Z';
            int i=8;
            printf("a=%d,%u,%5d,%-5d,%.4d,%o,%x,%f,%f\n",a,a,a,a,a,a,a,(float)a);
            printf("b=%d,%u,%5d,%-5d,%.4d,%o,%x,%f,%f\n",b,b,b,b,b,b,b,(float)b);
            printf("c=%f,%lf,%5f,%.4f,%5.4f,%5.4lf,%e\n",c,c,c,c,c,c,c);
            printf("d=%f,%lf,%5f,%.4f,%5.4f,%5.4lf,%e\n",d,d,d,d,d,d,d);
            printf("e=%c,%8c,%.5c,%8.5c,%d\n",e,e,e,e,e);
            i=8;
            printf("%d,%d,%d,%d\n",++i,--i,i++,i--); 
            /*
            i--,将i地址中8放入一个临时地址,原来地址-1填入,得7
            i++,将i地址中现在值7放入一个临时地址,原来地址+1,得8
            --i,将i直接-1,得7
            ++i,将i直接+1,得8
            然后,输出:8(原地址),8(原地址),7(临时地址),(临时地址)
            */
            //8,8,7,8
            i=8;
            printf("%d,",i--);  //8,自减1=7 
            printf("%d,",i++);  //7,自加1=8
            printf("%d,",--i);  //自减1=7,7
            printf("%d\n",++i);  //自加1=8,8
            //8,7,7,8
            i=8;
            printf("%d,",++i);  //自加1=9,9
            printf("%d,",--i);  //自减1=8,8
            printf("%d,",i++);  //8,自增1=9
            printf("%d,",i--);  //9,自减1=8
            printf("%d\n",i);  //8
            //9,8,8,9,8
        }
        /*
        a=15,15,   15,15   ,0015,17,f,0.000000,15.000000
        b=-10,4294967286,  -10,-10  ,-0010,37777777766,fffffff6,0.000000,-10.000000
        c=123.456787,123.456787,123.456787,123.4568,123.4568,123.4568,1.234568e+002
        d=12345678.123457,12345678.123457,12345678.123457,12345678.1235,12345678.1235,12345678.1235,1.234568e+007
        e=Z,       Z,Z,       Z,90
        8,8,7,8  
        8,7,7,8
        9,8,8,9,8
        */
        
      • scanf 函数

        格式输入函数,末尾 f 为 format(格式) 之意。

        按用户指定的格式从键盘上把数据输入到指定的变量中(本质:给变量赋值)

        一般形式:scanf("格式控制字符串",地址表列);

        1. 格式控制字符串作用同printf 函数,但不能显示(输出)提示字符串(非格式字符串)。

          一般形式:%[*] [输入数据宽度] [长度] 类型

          1. 类型
        2. 地址表列中要给各个变量地址,变量地址由指针运算符中用于取地址的 ”&“ ,后跟变量名组成。

          &a,&b

          分别表示变量a 和变量b 的地址。

        main(){
            int a,b,c;
            printf("请输入a,b,c的值\n");
            //由于scanf函数不能显示提示字符串,所以先用printf函数在显示器屏幕上输出提示。
            scanf("%d%d%d",&a,&b,&c);
            //由于%d和%d之间没有非格式字符,所以在输入是需要用一个以上空格或回车作为两个输入数之间的间隔。
            printf("a=%d,b=%d,c=%d",a,b,c);
        }