學習目錄
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
;
}
|