认识最简单的常量与变量
常量
理解
- 没有被定义&在程序运行中不能改变&可以直接使用
(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