学习目录
1.【掌握】返回指针的函数程序员
2.【掌握】指向函数的指针数组
3.【掌握】结构体的声明ide
4.【掌握】结构体与数组函数
5.【掌握】结构体与指针学习
6.【掌握】结构体的嵌套ui
7.【掌握】结构体与函数spa
1、返回指针的函数
指针做为函数的返回值3d
指针是能够做为函数的返回值的,不能返回局部变量的指针,由于当函数执行结束后指针变量就释放了。若是咱们真的须要返回一个指针变量,那就要保证咱们的函数执行完毕以后,指针指向的变量仍然存储在内存之中。那咱们能够将变量建立在堆空间中,使用malloc或者calloc申请空间。或者直接声明为全局变量或者用static修饰的局部变量。指针
若是函数须要返回一个字符串,咱们能够返回(char *)类型字符串,不要使用字符数组,由于字符数组在函数执行结束后,就释放了。而使用(char *)声明的字符串是存储在数据段的,直到程序执行结束才会释放。code
1
2
3
4
5
6
7
8
9
10
|
#include <stdio.h>
#include <stdlib.h>
char
*getWeekDay
(
int
day
)
{
return
"星期N"
;
//返回的是字符串在数据段(常量区)中的地址
}
int
main
(
)
{
char
*weekDay
=
getWeekDay
(
2
)
;
return
0
;
}
|
2、指向函数的指针
程序在运行的时候,函数是存储在内存(代码段)之中的,存储函数的空间确定也是有地址的,因此咱们能够用指针指向函数。
语法:返回值类型 (*指针名)([参数列表]);
注意:
1.函数的地址就是函数名。
2.指向函数的指针变量,本质上仍是一个变量,那么咱们就能够声明、赋值给另一个同类型的指针变量使用。
无参无返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
#include <stdio.h>
void
testFunction
(
)
{
printf
(
"这是一个无参无返回值的函数\n"
)
;
}
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
//指针指向函数
void
(
*pFunction
)
(
)
=
testFunction
;
//存储没有返回值没有参数的地址,函数名就是函数的地址
//指针调用函数
(
*pFunction
)
(
)
;
pFunction
(
)
;
//简写
return
0
;
}
|
有参有返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <stdio.h>
int
getSum
(
int
num1
,
int
num2
)
{
return
num1
+
num2
;
}
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
//指针指向函数,参数列表能够省略
int
(
*pFunction
)
(
)
=
getSum
;
//指针调用函数
int
sum
=
pFunction
(
10
,
12
)
;
printf
(
"sum = %d\n"
,
sum
)
;
return
0
;
}
|
应用场景:多种方式对字符串数组进行排序
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
|
#include <stdio.h>
#include <string.h>
/**
* 对字符串进行各类排序
*
* @param countries 须要被排序的字符串数组
* @param length 字符串数组的长度
* @param pCompare 指向控制排序方式的函数指针
*/
void
sort
(
char
*countries
[
]
,
int
length
,
int
(
*pCompare
)
(
)
)
{
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
for
(
int
j
=
0
;
j
<
length
-
1
-
i
;
j
++
)
{
//调用比较字符串的函数进行比较
int
res
=
pCompare
(
countries
[
j
]
,
countries
[
j
+
1
]
)
;
if
(
res
>
0
)
{
//交换位置
char
*temp
=
countries
[
j
]
;
countries
[
j
]
=
countries
[
j
+
1
]
;
countries
[
j
+
1
]
=
temp
;
}
}
}
}
/**
* 比较字符串大小
*
* @param str1 第一个字符串
* @param str2 第二个字符串
*
* @return 第一个大字符串大返回正数,第二个字符串大返回负数,相同返回0
*/
int
compare
(
char
*str1
,
char
*str2
)
{
return
(
int
)
strcmp
(
str1
,
str2
)
;
}
/**
* 比较字符串的长度
*
* @param str1 第一个字符串
* @param str2 第二个字符串
*
* @return 第一个字符串大返回1,第二个字符串大返回-1,相同返回0
*/
int
compare1
(
char
*str1
,
char
*str2
)
{
unsigned
long
len1
=
strlen
(
str1
)
;
unsigned
long
len2
=
strlen
(
str2
)
;
if
(
len1
>
len2
)
{
return
1
;
}
else
if
(
len1
<
len2
)
{
return
-
1
;
}
return
0
;
}
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
char
*countries
[
]
=
{
"fldjfljfaf"
,
"fdahfiyyyyfh"
,
"aadjflui"
,
"jabfaf"
}
;
//计算字符串数组长度
int
length
=
sizeof
(
countries
)
/
sizeof
(
char
*
)
;
//传入字符串数组,数组长度,指向函数的指针。按字符串大小排序
sort
(
countries
,
length
,
compare
)
;
//传入字符串数组,数组长度,指向函数的指针。按字符串长度排序
sort
(
countries
,
length
,
compare1
)
;
//遍历打印字符串
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
printf
(
"%s\n"
,
countries
[
i
]
)
;
}
return
0
;
}
|
3、结构体的声明
在实际应用中,咱们一般须要由不一样类型的数据来构成一个总体,好比学生信息这个总体能够由姓名、年龄、身高等数据构成,这些数据都具备不一样的数据类型,姓名能够是字符指针类型,年龄能够是整型,身高能够是浮点型。C语言提供了一种构造类型来解决这个问题,由程序员本身声明多个数据类型组成一个总体当作一种新的数据类型,这个玩意就是结构体。结构体里的声明的多个数据类型变量叫作结构体的成员。
声明结构体类型语法:
struct 类型名 {
数据类型1 成员名1;
数据类型2 成员名2;
..........
};
声明结构体变量语法:struct 类型名 变量名;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//声明类型的同时声明变量
struct
Student
{
char
*name
;
int
age
;
float
heigth
;
}
stu
,
stu1
;
//能够同时声明多个变量
//匿名结构体。声明类型的同时声明变量,能够省略类型名,可是这种方法不能再次声明新的变量了
struct
{
char
*name
;
int
age
;
float
heigth
;
}
stu
,
stu1
;
//也能够同时声明多个变量
//声明类型,再声明变量
struct
Student
{
char
*name
;
int
age
;
float
heigth
;
}
;
struct
Student
stu1
,
stu2
;
//变量名是stu1,stu2.能够同时声明多个变量
struct
Student
stu2
;
//变量名是stu3
|
为结构体变量中的成员赋值
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
|
#include <stdio.h>
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
//声明一个结构体Student1
struct
Student1
{
char
*name
;
int
age
;
float
heigth
;
}
;
struct
Student
stu1
;
stu1
.
name
=
"zhoujianfeng"
;
//单独为变量的每一个成员赋值
stu1
.
age
=
18
;
stu1
.
heigth
=
1.9f
;
//声明一个结构体Student2
struct
Student2
{
char
*name
;
int
age
;
float
heigth
;
}
;
struct
Student
stu2
=
{
"zhoujianfeng"
,
18
,
1.9f
}
;
//声明变量的同时初始化
struct
Student
stu3
=
{
"zhoujianfeng"
,
18
}
;
//初始化部分
struct
Student
stu4
=
{
.
age
=
18
}
;
//指定成员初始化
struct
Student
stu5
=
stu2
;
//将stu2赋值给stu5
return
0
;
}
|
使用结构体注意:
1.这个新声明的结构体也是一个数据类型,由程序员本身声明的新类型,因此能够声明这个结构体类型的变量。
2.定义在大括号之中的变量,叫新类型的成员。必需要先声明结构体类型,再声明结构体变量。
3.结构体类型名首字母大写,而且结构体末尾须要加分号,
4.声明一个结构体变量没有初始化,成员的值是垃圾值,若是声明的同时初始化了部分,其余成员初始化为0。
5.相同类型的结构体变量是能够相互赋值的,赋值是将原结构体中的每个成员的值挨个拷贝给目标结构体变量。
6.结构体变量名,直接表明整个结构体变量。在外面学习到的全部数据类型中,只有数组名、函数名才表明他们的地址。其余都是表明变量自己
4、结构体与数组
语法:struct 结构体类型名 数组名[长度];
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
|
#include <stdio.h>
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
struct
Student
{
char
*name
;
int
age
;
int
score
;
}
;
//stuArray数组的每个元素的类型是一个struct Student结构体类型
struct
Student
stuArray
[
]
=
{
{
"小明"
,
19
,
99
}
,
{
"小芳"
,
19
,
99
}
,
{
"小东"
,
18
,
20
}
}
;
//单独初始化一个元素,须要作类型强转,否则编译器不知道赋值给数组仍是结构体
stuArray
[
0
]
=
(
struct
Student
)
{
"小明"
,
19
,
100
}
;
//数组长度 = 数组占的总字节数 / 每一个元素占的字节数
int
length
=
sizeof
(
stuArray
)
/
sizeof
(
struct
Student
)
;
//遍历数组,打印3个学生的信息
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
printf
(
"%s %d %d\n"
,
stuArray
[
i
]
.
name
,
stuArray
[
i
]
.
age
,
stuArray
[
i
]
.
score
)
;
}
return
0
;
}
|
5、结构体与指针
结构体变量也是一个变量,那么这个结构体变量必定是有内存地址的,因此咱们就能够搞个指针指向这个结构体变量。而后咱们就能够经过指针间接操做结构体变量。
语法:struct 结构体类型名 *指针名;
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
|
#include <stdio.h>
struct
Student
{
char
*name
;
int
age
;
int
score
;
}
;
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
//初始化变量
struct
Student
stu
=
{
"静静"
,
19
,
100
}
;
//p指针指向stu变量
struct
Student
*p
=
&
stu
;
//第一种方式
(
*p
)
.
name
=
"芳芳"
;
(
*p
)
.
age
=
18
;
(
*p
)
.
score
=
99
;
//第二种方式
p
->
name
=
"东东"
;
p
->
age
=
18
;
p
->
score
=
99
;
printf
(
"%s %d %d\n"
,
p
->
name
,
p
->
age
,
p
->
score
)
;
return
0
;
}
|
6、结构体的嵌套
咱们在为结构体写成员的时候,发现某个成员也是一个须要多个数据组成一个总体的数据,这个时候咱们就可使用结构体嵌套。在结构体内声明另外一个结构体类型的变量做为成员来使用。
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
|
#include <stdio.h>
//日期结构体类型
struct
Date
{
int
year
;
int
month
;
int
day
;
}
;
//人结构体类型
struct
Person
{
char
*name
;
int
age
;
struct
Date
birthday
;
}
;
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
//建立一我的并赋值
struct
Person
zhouJianFeng
=
{
"周剑峰"
,
23
,
{
2015
,
9
,
18
}
}
;
// struct Person zhouJianFeng = {"周剑峰",23,2015,9,18};//能够成员的省略大括号
//打印出这我的的信息
printf
(
"姓名:%s\n年龄:%d\n生日:%d年%d月%d日\n"
,
zhouJianFeng
.
name
,
zhouJianFeng
.
age
,
zhouJianFeng
.
birthday
.
year
,
zhouJianFeng
.
birthday
.
month
,
zhouJianFeng
.
birthday
.
day
)
;
return
0
;
}
|
7、结构体与函数
结构体做为函数的参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
#include <stdio.h>
//人结构体类型
struct
Person
{
char
*name
;
int
age
;
}
;
void
test
(
struct
Person
*stu
)
{
stu
->
name
=
"周剑峰"
;
stu
->
age
=
18
;
}
int
main
(
)
{
struct
Person
zhou
=
{
"静静"
,
19
}
;
test
(
&
zhou
)
;
//调用函数,传入地址
printf
(
"%s %d\n"
,
zhou
.
name
,
zhou
.
age
)
;
return
0
;
}
|
结构体做为函数的返回值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
#include <stdio.h>
//人结构体类型
struct
Person
{
char
*name
;
int
age
;
}
;
struct
Person
getStu
(
)
{
struct
Person
stu
=
{
"静静"
,
19
}
;
return
stu
;
//是返回一个变量的值
}
int
main
(
)
{
struct
Person
stu
=
getStu
(
)
;
printf
(
"%s %d\n"
,
stu
.
name
,
stu
.
age
)
;
return
0
;
}
|