1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
知识点: 1.结构体 struct
2.联合体 union
3.枚举
4.结构、联合与函数
=========================== 结构体 思考:如果现在希望保存一个学生的信息,该如何保存
sprintf
"zhangsan:18:180”
%s:%d:%d, name, height, age
char
name[10][100]
int
age[10]
int
height[10]
1.什么是结构体 struct
结构体指的是一种数据结构,是c语言中复合数据类型的一
种多种不同数据类型的集合
2.结构体的作用
结构体可以用来创建复杂的数据结构
3.结构体的定义
1)定义的语法!!
4.结构体成员声明
1)可以声明各种类型的成员
2)成员声明时需要注意的地方
练习:
struct
1.定义一个结构体,用来描述时间,
具体说该结构体有三个成员,分别描述时分秒信息
2.定义一个结构体,用来描述书本的信息,
结构体成员包括名称,单价,作者,出版社
author
price
publish
5.声明结构体类型变量和初始化
. 非指针
-> 指针
6.结构体成员的访问方式
练习:
1.初始化并输出时间结构体的信息
2.初始化并输出书本结构体的信息
3.从终端输入书本的信息,并且输出
7.结构体数组
练习:
1.2本书的名称等信息,然后按照每行一本书的信息输出
2.建立包含2个学生信息的登记表,其中包括学号,姓名,性别,住址和3门成绩
8.结构体指针变量
1)指向结构体变量的指针
int
*p;
struct
stu *p;
9.结构体的嵌套和指针成员
1)结构体中嵌套结构体
2)结构体中的成员为一个指针变量
10.结构体和函数
1)思考:结构体在函数传递时是否会和数组一样进行地址传递
2)结构体的参数传递方式,值传递和地址传递
练习:
0.实现一个函数,作用为输入某个学生的学生信息
scanf ( "%d" , &s->id);
1.实现一个函数,作用为输出某个学生的学生信息
2.实现一个函数,作用为遍历所有的学生信息
11.结构体的大小和内存对齐
1)思考:为什么会出现相同机构体,大小不同的情况
2)原因:大致可以分为2点
1>平台原因(移植):不是所有的硬件平台都能访问任意
地址上的任意数据
2>性能原因:经过内存对齐后,cpu的内存访问速度大大
提升
3)对齐方式
1>和编译器有关,一般32位系统默认以4个字节方式对齐
2>本系统以结构体中最大元素的类型进行对齐
=========================== 联合体 ip协议
192.168.1.1
fe80::72cd:60ff:fe38:308%en0
union {
struct
ipv4{
//...
};
struct
ipv6{
//...
};
};
1.什么是联合体 union
1)共享存储空间
2)同时只能使用某一种数据类型
char
int
double
2.作用
1)当多个数据需要共享内存或者多个数据每次只取其一时,可以利用联合体
3.联合体的定义
//和结构体操作一致
4.联合体成员声明
5.联合体类型变量
6.联合体大小
7.联合体成员输入和输出
=========================== 枚举 enum
size{S,M,L}
S = 0
M = 1
L = 2
1.什么是枚举 enum
所谓枚举是指将变量的值一一列举出来,变量只限于列举出来的值的范围内取值。
2.枚举的作用
关心的不是它的值的大小,而是其表示的状态
3.枚举变量的声明
4.枚举变量的初始化和输入输出
5.枚举的本质
1)用标识符表示的整数常量集合
2)枚举元素不是变量,而是常量,因此枚举元素又称为枚举常量。
因为是常量,所以不能对枚举元素进行赋值。
3)枚举元素作为常量,它们是有值的,C 语言在编译时按定义的顺序使它们的值为,1,2,…。
练习:
1.定义一个表示衣服码数的枚举集合
2.让用户选择码数,然后输出该码数
6.使用枚举需要注意的地方
1)在一个程序中不允许出现同名的枚举类型
2)在一个程序中不允许出现同名的枚举常量
=========================== |
字符串总结:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
|
知识点: 1.字符和字符处理函数
2.字符串的本质和字符串输入输出函数
3.字符串转换函数
4.常用字符串处理函数
5.字符串查找函数
6.字符串分割函数
7.字符串替换
8.常用字符串处理函数实现
9. sscanf 函数
================================= 字符和字符处理 1.复习ascii码
‘0‘ ~ ‘9‘
‘a‘ ~ ‘z‘
‘A‘ ~ ‘Z‘
48 97 65
2.字符的本质
思考: sizeof ( char ) 和 sizeof ( ‘a‘ )
1)字符的本质为一个 int 类型的ascii码
2)字符变量保存的是ascii码,但是ascii码只需要一个字节即可保存
3.使用字符判断函数
isdigit
数字字符
isalpha
字母(大小写)
isalnum
数字字符和字母
islower
小写字母
isupper
大写字母
isspace
空格字符
0 --表示测试不成立
1 --表示测试成立
练习:
1.用户输入一个字符串,统计其中数字,字母,空格的个数
2.分别统计出大小写字母的个数
4.使用字符转换函数
tolower
大写转换为小写
int
tolower ( int
c)
toupper
小写转换为大写
int
toupper ( int
c)
练习:
1.将用户输入的字符串中的大写字母转换为小写字母
2.将用户输入的字符串中的数字 小写字母全部转换为*号
3.将用户输入的字符串中的其他字符转换为?号
其他字符不包括数字,字母,空格
Hell+ world
Hell? world
================================= 字符串 char
s1[100] = "hello world" ;
char
*s2 = "hello world" ;
0.字符串
不以字符数组引用时为一个常量
//栈
char
str[] = "hello" ;
char
str[12] = { ‘h‘ , ‘e‘ , ‘l‘ , ‘l‘ , ‘o‘ , ‘\0‘ };
char
str[100];
//只读数据段
char
*p = "hello world" ;
printf ( "%s" , str); string
scanf ( "%s" ); 不包含空格的输入
scanf ( "%[^\n]" ); 包含空格的输入
printf ( "hello world" );
char
str[] = "hello world"
char
str[] = { ‘h‘ , ‘e‘ , ‘l‘ , ‘o‘ , ‘\0‘ };
1.字符串的本质
1)字符串本质为字符串常量
"hello world"
2.思考: sizeof ( ‘A‘ )和 sizeof ( "A" )
字符常量按照4个字节处理
字符串常量为了节省内存空间,字符串中的所有字符均以 char 类型处理
3.回忆 char
*str和 char
str[]区别
NSString NSMutableString
================================= 字符串的输入输出 1.字符串的输入和输出
0)字符串输入输出函数
1>回忆 scanf 获取字符串
scanf ( "%s" );
2>如何获取带空格的字符串
%[^\n]
3> puts
string
4>字符串输出
puts 函数会在字符串输出后添加换行符号
printf ( "%s\n" , str);
1)字符串的输入与溢出问题
思考:字符数组在输入时候的长度问题
2)解决方法
fgets
用法: fgets (buf, 100, stdin);
从标准输入获取指定长度的字符串,包含字符串结束符
================================= 字符串转换函数 100 + 200 需求:现在用户输入一个算术表达式,要求得到对应的结果
思考:如何将字符串中的字符数字转换为真实的数字
1.字符串转换函数
1) atol 和 atoi 和 atof 函数
atof 返回 double
2)实现 atoi 函数(支持正负数)
示例:实现个位数的负数转换
练习:实现n位数的的正负数转换
3) strtol 函数 1010 0x123456
字符串中不能出现和当前进制相悖的数据
1> atoi 的增强版 2, 8, 10, 16
2>函数说明:将指定字符串按照base的进制方式转换为10进制
base范围为2~36
==================================== 字符串常用函数 需求:用户需要知道输入的字符数的长度
1.字符串长度计算函数
1) strlen 函数使用
"hello world"
while
(str[i] != ‘\0‘ )
{
cnt++;
i++;
}
2)思考: strlen 和 sizeof 的区别
3)思考: strlen 长度的大小
需求:用户需要我们在软件中实现选中字符的复制功能
2.字符串拷贝函数
strcpy
会将src内的所有内容拷贝到
dst数组中,包括\0
strncpy
思考: strncpy 拷贝后是否会包含结束符
练习:实现一个字符串拷贝模块
需求:用户需要在软件中实现一个字符串的查找功能
3.单个字符的查找
strchr
查找字符第一次出现的地址
strrchr
查找字符最后一次出现的地址
练习:
输入一个字符串,再输入一个字符
查找并打印第一次出现和最后一次出现的字符
并输出该字符的地址
4.字符串查找到
strstr ,strcasestr,strnstr
需求:用户需要输入一个名字,判断该用户是否存在
5.字符串比较函数
strcmp ,strcasecmp
strncmp ,strncasecmp
int
strncmp ( const
char *s1, const
char *s2, int
n);
1)比较顺序:s1是否和s2相同
2)比较结果:0为相同,非0为不同,并且返回对应的差值
思考:非0的结果表示什么
3)思考:当s1比s2长度长的话会如何
返回s1最后一个字符和s2结束符的差
练习:
0.编写一个模拟登陆程序,输入用户名和密码,判断用户名和密码
是否和所设定的一致
1.编写一个验证程序,判断用户输入的字符串是否以qianfeng开头
需求:用户现在需要将输入的两个字符串组合成一个完整的字符串
6.字符串连接
strcat , strncat
练习:先输入自己的姓,再输入名字,最后将连接好的名字输出
需求:用户现在需要按照一定的格式分割一个字符串
7.字符串分割函数
1) strtok 使用
1>要分割的内容
2>分割符,分割标记
2)如何获取下一个字符串
3)注意
0>不能截取字符串常量
1>截取后的长度
2>如果在下一次截取前截取另外一个字符串会如何
练习:
1.顺序输出分割后的所有字符串
2.查找字符串中的最长单词,并且输出该单词
需求:现在用户需要实现一个文本的查找替换功能
8.单个字符替换
strchr
9.字符串替换
strstr 和 strncpy 联合实现
hello world
===================================== 常用字符串处理函数的实现 1.字符处理函数的实现
2.字符串处理函数的实现
strlen
int
mystrlen( const
char *str);
strcpy
void
mystrcpy( char
*dst, const
char *src);
strchr
char
*mystrchr( char
*str, int
c);
strrchr
char
*mystrrchr( char
*str, int
c);
strcmp
int
mystrcmp( const
char *s1, const
char *s2)
strcat
void
mystrcat( char
*s1, const
char *s2);
==================================== “11:59:59”
sprintf 和 sscanf
%[^ ‘|‘ ]
需求:用户需要将每个用户的信息按照以下格式输出
1.字符串格式化函数
1) sprintf 使用
2) printf 和 sprintf 对比
int
sprintf ( const
char *s, const
char *fmt, …)
练习:
1.按照以下格式输出时间
年-月-日 时:分:秒
需求:用户需要将刚才的用户信息重新解析为单个的属性
2.字符串格式化读取函数
1) sscanf 使用
集 strtok 和 atoi 等函数于一体
2) scanf 和 sscanf 对比
==================================== 超大数相加 “123” + “123” = “246” 2 = ’2‘ “123423413412374891374238476123846183474183” “123423413412374891374238476123846183474183” |
位操作总结:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
|
知识点: 1.位运算符
2.位移运算符
1.将指定位设置为1 2.将指定位设置为0 3.获取指定位的内容 ========================== 复习二进制 1.二进制转换
10--> /2 取余数 1010
2.原码,反码,补码
-1 0xffffffff %d %#x %#o
3.二进制高位和低位
0000 0001
4.二进制输出函数
1010
========================== 位操作 1.什么是位操作
位操作是程序设计当中对位模式按位或二进制数的一元和二元操作.
在许多古老的微处理器上, 位运算比加减运算略快, 通常位运算比乘除法运算要快很多.
在现代架构中, 情况并非如此:位运算的运算速度通常与加法运算相同(仍然快于乘法运算).
2.作用
1)加快某些算术元素操作,例如乘法和除法使用位移效率较高
2)标志位设置
========================== 位运算符 1.位运算符
<< , >>, &, |, ~, ^
1)对比逻辑运算符 &&, ||, !
2.位与操作 &
1)按位&运算符的运算方法
按顺序,每一位进行比较,如果两位都为1,结果为1,相反为0
2)十六进制表示二进制
4)作用:
1.清空某一位
2.获取某一位
示例:
0&0, 1&0, 0&1, 1&1
-1 & 1
练习:
1.手工运算,然后程序验证:
1010 1100 & 1110 0111 164—>0xa4
1110 1101 & 1010 0101 165->0xa5
3.位或操作 |
1)按位|运算的运算方法
对应位只要一个为1,结果为1,如果都为0,结果为0
练习:
1.手工运算,然后程序验证:
1010 1100 | 1110 0111 239
1110 1101 | 1010 0101 237
& 0 1
0 0 0
1 0 1
| 0 1
0 0 1
1 1 1
4.位取反 ~
1)位取反运算方法
所有位按位取反
2)注意取反结果
练习:
手工运算,然后程序验证:
1.~11011111 0xffffff20
2.~-1
5.位异或(xor) ^
1)运算方法
对应位不同为1,相同为0
^ 0 1
0 0 1
1 1 0
练习:
手工运算,然后程序验证
1. 1 ^ 1, 1 ^ 2, 1 ^ 3
2. -1 ^ 10
两数交换的位操作版本
=========================== 位移操作 2^n |0000 0001|
1.左移运算符 <<
1)运算方式
高位移出位舍弃,低位补0
示例:
1111 0001 << 1
练习:
手工运算,然后程序验证
1. 1 << 0, 1 << 1, 1 << 2, 1 << 3
2. -1 << 1
1 << 31
|0000 0010| |1111 1000|
|0000 0001| |1111 1100|0
|0000 0000|1 |1111 1110|00
0000 0001 >> 1 1 / 2 1%2
2.右移运算符 >>
1)运算方式
1>无符号右移 unsigned
高位补0
2>有符号右移 -2 2
移出位舍弃,高位补符号位
练习:
手工运算,然后程序验证
1. 1 >> 0,1 >> 1, 4 >> 1, 8 >> 1
2. -10 >> 1
-5 >> 1
======================================== 应用示例: 1.指定位清0
思考:如何设置第n位为0
n & ~(1 << num)
练习:定义一个函数,作用为设置指定为0
函数原型: int
set0( int
n, int
num)
2.指定位设置为1
思考:如何设置第n位为1
n | (1 << num)
练习:定义一个函数,作用为设置指定位为1
函数原型: int
set1( int
n, int
num)
3.获取某一位的值
n >> num & 1
00000000 思考:如何可以获取指定位的值
练习:定义一个函数,作用为获取某一位的值
函数原型: int
get_bits( int
n, int
num)
4.二进制转换函数
思考:如何利用位操作可以获取到一个数的二进制
函数原型: void
binshow(unsigned int
n, int
size)
========================================= 扩展 1.如何循环左移或者右移 int 的所有位
1 2 3 4 5
5 1 2 3 4 unsigned
1010
0101
1010
2.利用位操作实现简单的加密解密功能
^
|