C语言第三章讲义


认识最简单的常量与变量

常量

理解

  • 没有被定义&在程序运行中不能改变&可以直接使用
(1)整型常量
  • 表现形式为整数。
(2)实型常量
  • 十进制小数形式表现,表现通式为a.b,小数点左右为整数。
  • 还有指数形式,也就是中学学过的科学计数法,表现通式为aEb或者aeb,其中a为整数或者小数,b为整数,a&b缺一不可。
(3)字符常量

普通字符

  • 由单撇号括起来的一个字符,不包含单撇号;

转义字符

  • 字符 ‘ \ ‘开头的字符序列
  • 常用转义字符如下
转义字符 意义 ASCII码值(十进制)
\a 响铃(BEL) 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 空字符(NUL) 000
\ooo 3位八进制数所代表的任意字符 三位八进制
\xhh 十六进制所代表的任意字符 十六进制
(字符串常量)
  • 由双撇号括起来的多个字符,不包括双撇号
(符号常量)| (宏)
  • 利用#define指令,指定用一个字符名称代表一个常量。如:

  • #define PI 3.1415926     // 圆周率
    #define RADIUS 4         // 半径
    
  • 显而易见,直接看出来代表啥意思!!!

注意

符号常量不占用内存,符号常量在预编译阶段就已经变成字面常量,预编译后就不存在了

常量占用内存空间

C语言区分大小写

变量

理解

  • 使用前先定义,在内存分配一块存储的空间给变量存储变量值。定义必须指出变量名字与类型。如

  • int a = 1;
    
  • 其中,a为变量名,1为变量值。

(1)整形变量
  • short int a = 1;             // 定义一个短整形变量
    int a = 1;                   // 定义一个基本整形变量
    long int a = 1;              // 定义一个长整形变量
    long long int a = 1;         // 定义一个双长整形变量
    
  • 对于整形变量所占字节数和其取值范围具体看书本

(2)字符型变量
  • char ch = 'a';            //定义一个普通字符ch,值为字符a
    signed ch = 'a';          //定义一个有符号字符ch,值为字符a
    unsigned char = 'a';      //定义一个无符号字符ch,值为字符a
    
  • 具体看书本

(3)浮点型变量
  • float x = 1;         //定义单精度浮点型变量x,值为1.000000;
    double x = 1;        //定义双精度浮点型变量x,值为1.000000
    long double x = 1;   //定义长双精度浮点型变量x,值为1.000000;
    
  • 具体看书本

常变量

理解

  • 定义变量前加入C语言关键字const,如:

  • const int a = 3;
    
  • 定义一个值恒为3的常变量a

C运算符

算术运算符

大前提

  • int A = 10, B = 20;
    
运算符 描述 实例
+ 把两个操作数相加 A + B 将得到 30
- 从第一个操作数中减去第二个操作数 A - B 将得到 -10
* 把两个操作数相乘 A * B 将得到 200
/ 分子除以分母 B / A 将得到 2
% 取模运算符,整除后的余数,取模运算的变量必须是整型 B % A 将得到 0
++ 自增运算符,整数值增加 1 A++ 将得到 11
自减运算符,整数值减少 1 A– 将得到 9

关系运算符

  • 进行关系运算符作用后的条件为(真)1或者(假)0

大前提

  • int A = 10, B = 20;
    
运算符 描述 实例
== 检查两个操作数的值是否相等,如果相等则条件为真。 (A == B) 为假。
!= 检查两个操作数的值是否相等,如果不相等则条件为真。 (A != B) 为真。
> 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 (A > B) 为假。
< 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 (A < B) 为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 (A >= B) 为假。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 (A <= B) 为真。

逻辑运算符

  • 进行关系运算的返回值为(真)1或者(假)0

大前提

  • int A = 1, B = 0;
    
运算符 描述 实例
&& 逻辑与运算符。如果两个操作数都非零,则条件为真。 (A && B) 为假。
|| 逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 (A || B) 为真。
! 逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 !(A && B) 为真。

位运算符

注意位运算符作用于二进制位,并逐位执行操作

p q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

假设如果 A = 60,且 B = 13,现在以二进制格式表示,它们如下所示:

A = 0011 1100

B = 0000 1101

-———————

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A = 1100 0011

下表显示了 C 语言支持的位运算符。假设变量 A 的值为 60,变量 B 的值为 13,则:

运算符 描述 实例
& 按位与操作,按二进制位进行”与”运算。运算规则:0&0=0; 0&1=0; 1&0=0; 1&1=1; (A & B) 将得到 12,即为 0000 1100
| 按位或运算符,按二进制位进行”或”运算。运算规则:`0 0=0; 0
^ 异或运算符,按二进制位进行”异或”运算。运算规则:0^0=0; 0^1=1; 1^0=1; 1^1=0; (A ^ B) 将得到 49,即为 0011 0001
~ 取反运算符,按二进制位进行”取反”运算。运算规则:~1=-2; ~0=-1; (~A ) 将得到 -61,即为 1100 0011,一个有符号二进制数的补码形式。
<< 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 A << 2 将得到 240,即为 1111 0000
>> 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 A >> 2 将得到 15,即为 0000 1111

赋值运算符

下表列出了 C 语言支持的赋值运算符:

运算符 描述 实例
= 简单的赋值运算符,把右边操作数的值赋给左边操作数 C = A + B 将把 A + B 的值赋给 C
+= 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 C += A 相当于 C = C + A
-= 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 C -= A 相当于 C = C - A
*= 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 C *= A 相当于 C = C * A
/= 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 C /= A 相当于 C = C / A
%= 求模且赋值运算符,求两个操作数的模赋值给左边操作数 C %= A 相当于 C = C % A
<<= 左移且赋值运算符 C <<= 2 等同于 C = C << 2
>>= 右移且赋值运算符 C >>= 2 等同于 C = C >> 2
&= 按位与且赋值运算符 C &= 2 等同于 C = C & 2
^= 按位异或且赋值运算符 C ^= 2 等同于 C = C ^ 2
|= 按位或且赋值运算符 C |= 2 等同于 C = C | 2

杂项运算符 ↦ sizeof & 三元

下表列出了 C 语言支持的其他一些重要的运算符,包括 sizeof? :

运算符 描述 实例
sizeof() 返回变量字节总数的大小。 sizeof(a) 将返回 4,其中 a 是整数。
& 返回变量的地址。 &a; 将给出变量的实际地址。
* 指向一个变量。 *a; 将指向一个变量。
? : 条件表达式 如果条件为真 ? 则值为 X : 否则值为 Y

代码演示

#include <stdio.h>
 
int main() {
   int a = 4;
   short b;
   double c;
   int* ptr;
 
   /* sizeof 运算符实例 */
   printf("Line 1 - 变量 a 的大小 = %lu\n", sizeof(a) );
   printf("Line 2 - 变量 b 的大小 = %lu\n", sizeof(b) );
   printf("Line 3 - 变量 c 的大小 = %lu\n", sizeof(c) );
 
   /* & 和 * 运算符实例 */
   ptr = &a;    /* 'ptr' 现在包含 'a' 的地址 */
   printf("a 的值是 %d\n", a);
   printf("*ptr 是 %d\n", *ptr);
 
   /* 三元运算符实例 */
   a = 10;
   b = (a == 1) ? 20: 30;
   printf( "b 的值是 %d\n", b );
 
   b = (a == 10) ? 20: 30;
   printf( "b 的值是 %d\n", b );
}

结果

Line 1 - 变量 a 的大小 = 4
Line 2 - 变量 b 的大小 = 2
Line 3 - 变量 c 的大小 = 8
a 的值是 4
*ptr 是 4
b 的值是 30
b 的值是 20

算术表达式&运算符的优先级&结合性

运算符的优先级确定表达式中项的组合。这会影响到一个表达式如何计算。某些运算符比其他运算符有更高的优先级,例如,乘除运算符具有比加减运算符更高的优先级。

例如 x = 7 + 3 * 2,在这里,x 被赋值为 13,而不是 20,因为运算符 * 具有比 + 更高的优先级,所以首先计算乘法 3*2,然后再加上 7。

下表将按运算符优先级从高到低列出各个运算符,具有较高优先级的运算符出现在表格的上面,具有较低优先级的运算符出现在表格的下面。在表达式中,较高优先级的运算符会优先被计算。

优先级 运算符 结合律
1 后缀运算符:[] () · -> ++ –(类型名称){列表} 从左到右
2 一元运算符:++ – ! ~ + - * & sizeof_Alignof 从右到左
3 类型转换运算符:(类型名称) 从右到左
4 乘除法运算符:* / % 从左到右
5 加减法运算符:+ - 从左到右
6 移位运算符:<< >> 从左到右
7 关系运算符:<<= >>= 从左到右
8 相等运算符:== != 从左到右
9 位运算符 AND:& 从左到右
10 位运算符 XOR:^ 从左到右
11 位运算符 OR:| 从左到右
12 逻辑运算符 AND:&& 从左到右
13 逻辑运算符 OR:|| 从左到右
14 条件运算符:?: 从右到左
15 赋值运算符: = += -= *= /= %= &= ^= |= <<= >>= 从右到左
16 逗号运算符:,

代码演示

#include <stdio.h>
 
main() {
   int a = 20;
   int b = 10;
   int c = 15;
   int d = 5;
   int e;
 
   e = (a + b) * c / d;      // ( 30 * 15 ) / 5
   printf("(a + b) * c / d 的值是 %d\n",  e );
 
   e = ((a + b) * c) / d;    // (30 * 15 ) / 5
   printf("((a + b) * c) / d 的值是 %d\n" ,  e );
 
   e = (a + b) * (c / d);   // (30) * (15/5)
   printf("(a + b) * (c / d) 的值是 %d\n",  e );
 
   e = a + (b * c) / d;     //  20 + (150/5)
   printf("a + (b * c) / d 的值是 %d\n" ,  e );
  
   return 0;
}

结果


(a + b) * c / d 的值是 90
((a + b) * c) / d 的值是 90
(a + b) * (c / d) 的值是 90
a + (b * c) / d 的值是 50

输入与输出

理解

  • 用户从键盘输入数据,输出数据到
  • 从文件读取数据,输入数据到文件

输入函数

  • scanf():和 printf() 类似,scanf() 可以输入多种类型的数据。
  • gets():获取一行数据,并作为字符串处理。
  • getchar()、getche()、getch():这三个函数都用于输入单个字符。

输出函数

  • puts():只能输出字符串,并且输出结束后会自动换行。
  • putchar():只能输出单个字符。
  • printf():可以输出各种类型的数据。

注意


scanf() 是最灵活、最复杂、最常用的输入函数,但它不能完全取代其他函数,大家都要有所了解。

printf() 是最灵活、最复杂、最常用的输出函数,完全可以替代 puts() 和 putchar(),大家一定要掌握。


printf()&scanf()的初级用法

scanf()

  • scanf 是 scan format 的缩写,意思是格式化扫描,也就是从键盘获得用户输入,和 printf 的功能正好相反。
  • 声明:int scanf(const char *format, …);
  • format – 这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符format 说明符

printf()

  • format – 这是字符串,包含了要被写入到标准输出 stdout 的文本。
  • 声明:int printf(const char *format, …);

scanf 类型说明符:


类型 合格的输入 参数的类型
%a、%A 读入一个浮点数、十六进制数字(仅 C99 有效)。 float *
%c 单个字符:读取下一个字符。如果指定了一个不为 1 的宽度 width,函数会读取 width 个字符,并通过参数传递,把它们存储在数组中连续位置。在末尾不会追加空字符。 char *
%d 十进制整数:数字前面的 + 或 - 号是可选的。 int *
%e、%E、%f、%F、%g、%G 浮点数:包含了一个小数点、一个可选的前置符号 + 或 -、一个可选的后置字符 e 或 E,以及一个十进制数字。两个有效的实例 -732.103 和 7.12e4 float *
%i 读入十进制,八进制,十六进制整数 。 int *
%o 八进制整数。 int *
%s 字符串。这将读取连续字符,直到遇到一个空格字符(空格字符可以是空白、换行和制表符)。 char *
%u 无符号的十进制整数。 unsigned int *
%x、%X 十六进制整数。 int *
%p 读入一个指针 。
%[] 扫描字符集合 。
%lf 读入一个double类型的变量值 double *
%% 读 % 符号。
  • 附加参数 – 根据不同的 format 字符串,函数可能需要一系列的附加参数,每个参数包含了一个要被插入的值,替换了 format 参数中指定的每个 % 标签。参数的个数应与 % 标签的个数相同。

printf 类型说明符:


格式字符 意义
%d 以十进制形式输出带符号整数(正数不输出符号)
%o 以八进制形式输出无符号整数(不输出前缀0)
%x,%X 以十六进制形式输出无符号整数(不输出前缀Ox)
%u 以十进制形式输出无符号整数
%f 以小数形式输出单精度浮点型变量
%e,%E 以指数形式输出单、双精度实数
%g,%G 以%f或%e中较短的输出宽度输出单、双精度实数
%c 输出单个字符
%s 输出字符串
%p 输出指针地址
%lu 32位无符号整数
%lf 以小数形式输出双精度浮点型变量
%llu 64位无符号整数

代码演示1

#include <stdio.h>
int main() { 
    int a,b,c; 
 
    printf("请输入三个数字:");
    scanf("%d%d%d",&a,&b,&c); 
    printf("%d,%d,%d\n",a,b,c);
    return 0; 
}

输出1

请输入三个数字:1 2 3
1,2,3

解析

  • &a、&b、&c 中的 & 是地址运算符,分别获得这三个变量的内存地址。
  • %d%d%d 是按十进值格式输入三个数值。输入时,在两个数据之间可以用一个或多个空格、tab 键、回车键分隔。

注意


如果使用 , 来分隔输入的 %d, 相应的输入时也需要添加 ,:

输入时 , 前一定要紧跟在数字后面,数字与 , 之间不能有空格。


代码演示2

#include<stdio.h>
int main() {
    int a,b,c;
 
    printf("请输入三个数字:");
    scanf("%d, %d, %d",&a,&b,&c);
    printf("%d, %d, %d\n",a,b,c);
    return 0;
}

输出2

请输入三个数字:1, 2, 3
1, 2, 3

代码演示3

  • 在用 %c 输入时,空格和”转义字符”均作为有效字符
#include<stdio.h>
int main() {
    char a,b,c;
 
    printf("请输入三个字符:");
    scanf("%c%c%c",&a,&b,&c); 
    printf("%c,%c,%c\n", a,b,c);
    return 0;
}

输出3

请输入三个字符:gdf
g,d,f

代码演示4

#include
int main() {
    char a,b,c;
 
    printf("请输入三个字符:");
    scanf("%c %c %c",&a,&b,&c); 
    printf("%c,%c,%c\n", a,b,c);
    return 0;
}

输出4

请输入三个字符:d f g
d,f,g

printf()&scanf()的高级用法

清空缓冲区

缘由

  • 因为输入缓冲区是行缓冲模式,用户按下回车键会产生换行符,结束本次输入,然后输入函数开始读取。
scanf("%*[^ ]");
scanf("%*c");
丢弃读取到的字符
  • 在 % 后面加一个*

  •  scanf("%*d");            // %*d 表示读取一个整数并丢弃;
     scanf("%*[a-z]c", &ch);      // %*[a-z] 表示读取小写字母并丢弃;
    
%*d 表示读取一个整数并丢弃;

%*[a-z] 表示读取小写字母并丢弃;

%*[^\n] 表示将换行符以外的字符全部丢弃。
匹配特定的字符
  • %s 控制符会匹配除空白符以外的所有字符,它有两个缺点:

    • %s 不能读取特定的字符,比如只想读取小写字母,或者十进制数字等,%s 就无能为力;

    • %s 读取到的字符串中不能包含空白符,有些情况会比较尴尬,例如,无法将多个单词存放到一个字符串中,因为单词之间就是以空格为分隔的,%s 遇到空格就读取结束了。

  • 要想解决以上问题,可以使用 scanf() 的另外一种字符匹配方式,就是%[xxx]

  • [ ]包围起来的是需要读取的字符集合。

%[a-z] 表示读取 abc...xyz 范围内的字符,也即小写字母;

%[A-Z] 表示读取 ABC...XYZ 范围内的字符,也即大写字母;

%[0-9] 表示读取 012...789 范围内的字符,也即十进制数字。

%[a-zA-Z] 表示读取大写字母和小写字母,也即所有英文字母。

%[a-z-A-Z0-9] 表示读取所有的英文字母和十进制数字。

%[^\n] 表示读取换行符以外的字符。
指定读取长度
  • 格式控制符的中间加一个数字,用来表示读取数据的最大长度
%2d 表示最多读取两位整数;

%10s 表示读取的字符串的最大长度为 10,或者说,最多读取 10 个字符。

代码演示1

#include<stdio.h>
int main() {
    
    
    int b, c;
    scanf("%*d");    // %*d表示读取一个整数并丢弃;
    scanf("%d %d", &b, &c);
    printf("%d %d\n", b, c);
    
    scanf("%*[^ ]");    //刷新缓冲区 
    
    scanf("%*[a-z]");    // %*[a-z] 表示读取小写字母并丢弃;
     scanf("%d %d", &b, &c);
    printf("%d %d\n", b, c);
    
    scanf("%*c");    //刷新缓冲区 
    scanf("%2d%3d", &b, &c);   //   %2d 表示最多读取两位整数;
    printf("%d %d\n", b, c); 
    
    return 0;
}

结果

23 34 5
34 5
s 4353 342
4353 342
2342893472
23 428

代码演示2

#include<stdio.h>
int main() {

    
    scanf("%*c");      //刷新缓冲区 
    char *s;
    scanf("%[^\n]", s); //表示读取换行符以外的字符。
    printf("%s\n", s);
    return 0;
}

结果


sjdhfsdjk  rfskdf  89erue 9hjdfh jk
sjdhfsdjk  rfskdf  89erue 9hjdfh jk

文章作者: Axieyun
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Axieyun !
评论
评论
  目录