學習目標
1.【掌握】字符串經常使用函數數組
2.【掌握】指針變量的聲明安全
3.【掌握】指針變量的初始化ide
4.【掌握】函數與指針函數
5.【掌握】指針的數據類型學習
6.【掌握】多級指針spa
7.【掌握】指針與數組指針
1、字符串經常使用函數
puts和gets函數的聲明在stdio.h頭文件中,strcmp、strlen、strcpy、strcat函數的聲明在string.h頭文件中。code
puts()函數blog
語法:puts(存儲字符串數據的數組名);內存
輸出一個字符串數據,並自動換行。不過只能輸出字符串,而且不能使用格式控制符。
1
2
3
|
#include <stdio.h>
char
name
[
]
=
"jack"
;
puts
(
name
)
;
//輸出name字符數組裏的字符串數據
|
gets()函數
語法:gets(存儲字符串數據的數組名);
從控制檯接收一個字符串數據,並存儲在制定的字符數組之中。而且能讀取到空格,scanf不能讀取。不過gets只能接收字符串。不管是gets函數仍是scanf函數在接收字符串的時候都是不安全的。若是輸入字符串長度不夠的時候,就會出問題。
1
2
3
|
#include <stdio.h>
char
name
[
20
]
;
gets
(
name
)
;
//接收20個字符內的字符串數據存儲到name裏
|
strcmp()函數
語法:strcmp(字符串1,字符串2);//返回int類型
根據每一個字符對應的ASCII碼依次比較兩個字符串的每一個字符的大小,若是比較到兩個字符不一樣,就返回結果。若是返回正數,說明第一個字符串大,返回負數,說明第二個大。返回0,說明每一個字符的ASCII相同。
1
2
3
4
5
|
#include <string.h>
char
name
[
]
=
"afdaf"
;
char
name1
[
]
=
"adfdg"
;
int
cmp
=
strcmp
(
name
,
name1
)
;
//比較兩個字符串的大小
printf
(
"cmp = %d\n"
,
cmp
)
;
//打印len = 5
|
strlen()函數
語法:strlen(字符串);
計算字符串的長度,一個一個字符計數,直到遇到'\0'爲止。返回值是unsigned long。
1
2
3
4
|
#include <string.h>
char
name
[
]
=
"afdaf"
;
unsigned
long
len
=
strlen
(
name
)
;
printf
(
"len = %d\n"
,
len
)
;
//打印len = 5
|
strcpy()函數
語法:strcpy(字符串1,字符串2);
將字符串2拷貝到字符串1裏,而且覆蓋掉字符串1裏的數據。若是字符串1放不下字符串2,就會保錯。
1
2
3
4
5
|
#include <string.h>
char
name
[
]
=
"afdaf"
;
char
name1
[
]
=
"adfdg"
;
strcpy
(
name
,
name1
)
;
//會覆蓋掉name
puts
(
name
)
;
//輸出 adfdg
|
strcat()函數
語法:strcat(字符串1,字符串2);
將字符串2中的數據追加到字符串1後面,不會覆蓋,只會拼接。若是字符串1放不下字符串2,就會保錯。
1
2
3
4
5
|
#include <string.h>
char
name
[
20
]
=
"afdaf"
;
char
name1
[
]
=
"adfdg"
;
strcat
(
name
,
name1
)
;
//不會覆蓋掉name,只是name1鏈接到name屁股後面
puts
(
name
)
;
//輸出 afdafadfdg
|
2、指針變量的聲明
咱們聲明一個變量,實際是在內存中申請一個指定字節數的字節空間來存儲數據,分配變量空間的時候,是從高地址到底地址來分配的。
概念:
1.變量的值:是存儲在變量空間裏的數據。
2.變量的地址:聲明變量時申請到的字節空間中低字節的地址。
3.指針:變量的地址就叫作指針,地址就是指針,指針就是地址,只是換了個說法而已。
4.指針變量:其實也就是一個變量,只不過這個指針變量的值是個地址。
訪問變量的兩種方式:
1.直接訪問:直接使用變量名來訪問。
2.間接訪問:讓一個指針指向這個變量,經過這個指針能夠間接的訪問這個變量。
指針變量的聲明
語法:
聲明普通變量:數據類型 變量名;
聲明指針變量:數據類型 *指針變量名;
1
2
3
|
int
*
p
;
//表示咱們聲明瞭一個指針變量,名字叫p,*只是說明這是一個指針變量,而不是普通變量。
int
*
p1
;
//*的位置能夠挨着數據類型,也能夠單獨空一格
int
*
p2
;
|
注意:
1
2
3
4
|
int
*
p3
;
//*在這裏只是說明這是一個指針變量,而不是普通變量。
int
*
p4
;
//p4只能存儲int類型的變量的地址
float
*
p5
;
//p5只能存儲float類型的變量的地址
double
*
p6
;
//p6只能存儲double類型的變量的地址
|
指針變量名也是一個標識符,也須要符合變量的命名規則和規範。通常狀況下,咱們變量名都以p開頭,這樣讓別人一眼都能看出是指針變量。
1
2
|
int
*
p1
,
p2
,
p3
;
//是錯誤的,這樣聲明的只有p1纔是指針變量,p2,p3是int類型普通變量
int
*
p1
,
*
p2
,
*
p3
;
//這纔是正確的。
|
3、指針變量的初始化
指針變量中只能存儲和指針變量類型相同的變量的地址,因此不能直接給指針變量賦值一個其餘非地址的數據。使用&取地址運算符能夠獲取變量的地址。
語法:數據類型 *指針變量名 = 相同數據類型的變量的地址;
1
2
3
|
int
num
=
10
;
int
*
p
=
&
num
;
//獲取num的地址並賦值給指針變量p
int
*
p1
=
p
;
//將p中存儲的值賦值給新聲明的指針變量p1。等價於 int *p1 = #
|
經過指針變量訪問指針變量指向的普通變量,使用*取值符來取出指針變量指向的普通變量。
1
2
3
4
|
int
num
=
10
;
int
*
p
=
&
num
;
//將num的地址賦值給指針變量p
*
p
=
20
;
//把20賦值給了p指向的num,這裏的*p表示取出指針(p)的值(num的地址)的變量(num變量)。
printf
(
"num = %d\n"
,
num
)
;
//打印 num = 20
|
注意:
野指針:聲明一個指針變量而沒有初始化,這個指針變量的值是一個隨機內存地址。經過這個指針去爲指針指向的空間賦值的時候,就有可能改掉別人的數據,形成崩潰。
空指針:聲明一個指針變量的時候不肯定指向哪一個變量,能夠給他賦值NULL或者0(這裏0就表明NULL,不是整型0),表明這個指針不指向任何空間。
4、函數與指針
在函數中操做實參
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
|
#include <stdio.h>
//計算最大值、最小值、平均值、高級平均值
void
getMaxAndMin
(
int
arr
[
]
,
int
length
,
int
*
max
,
int
*
min
,
int
*
sum
,
float
*
avg
,
float
*
avg2
)
;
//改變實參數據
void
ziZeng
(
int
*
num
)
;
int
main
(
)
{
int
arr
[
]
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
}
;
int
length
=
sizeof
(
arr
)
/
sizeof
(
int
)
;
int
max
=
arr
[
0
]
,
min
=
arr
[
0
]
,
sum
=
0
;
float
avg
=
0.0f
,
avg2
=
0.0f
;
//調用函數
getMaxAndMin
(
arr
,
length
,
&
max
,
&
min
,
&
sum
,
&
avg
,
&
avg2
)
;
printf
(
"max = %d min = %d sum = %d avg = %.2f avg2 = %.2f\n"
,
max
,
min
,
sum
,
avg
,
avg2
)
;
int
num
=
1
;
ziZeng
(
&
num
)
;
printf
(
"num = %d\n"
,
num
)
;
}
//計算最大值、最小值、平均值、高級平均值
void
getMaxAndMin
(
int
arr
[
]
,
int
length
,
int
*
max
,
int
*
min
,
int
*
sum
,
float
*
avg
,
float
*
avg2
)
{
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
//最大值
if
(
arr
[
i
]
>
*
max
)
{
*
max
=
arr
[
i
]
;
}
//最小值
if
(
arr
[
i
]
<
*
min
)
{
*
min
=
arr
[
i
]
;
}
//累加和
*
sum
+=
arr
[
i
]
;
}
//平均值
*
avg
=
(
float
)
*
sum
/
length
;
//去掉一個最大值和一個最小值後的平均值
*
avg2
=
(
*
sum
-
*
max
-
*
min
)
/
(
length
-
2
)
;
}
//改變實參數據
void
ziZeng
(
int
*
num
)
{
for
(
int
i
=
0
;
i
<
5
;
i
++
)
{
(
*
num
)
++
;
}
}
|
5、指針的數據類型
經過指針操做指針指向的變量的時候,只能找到被指向那個變量的低字節的地址,到底要操做幾個字節的空間是根據指針的類型來決定的。例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <stdio.h>
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
char
ch1
=
'a'
;
char
ch2
=
'b'
;
char
ch3
=
'c'
;
char
ch4
=
'd'
;
int
*
p1
=
&
ch4
;
*
p1
=
'a'
;
printf
(
"ch1 = %c\n"
,
ch1
)
;
//ch1 = 0
printf
(
"ch2 = %c\n"
,
ch2
)
;
//ch2 = 0
printf
(
"ch3 = %c\n"
,
ch3
)
;
//ch3 = 0
printf
(
"ch4 = %c\n"
,
ch4
)
;
//ch4 = a
return
0
;
}
|
原理:這裏指針操做指針指向的變量的時候,指針認爲他指向的是int類型的變量,int類型佔4個字節的空間,因此操做了4個字節的空間。
6、多級指針
一級指針:若是一個指針變量中存儲的是一個普通變量的地址,那麼這樣的指針就叫作一級指針。
1
2
|
int
num
=
10
;
int
*
p
=
&
num
;
|
二級指針:若是一個指針變量中存儲的是一個一級指針變量的地址,那麼這樣的指針就叫作二級指針。
1
2
3
|
int
num
=
10
;
int
*
p1
=
&
num
;
int
*
*
p2
=
&
p1
;
|
三級和多級同理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#include <stdio.h>
int
main
(
)
{
int
num
=
10
;
int
*
p1
=
&
num
;
//p1存儲num的地址
int
*
*
p2
=
&
p1
;
//p2存儲p1的地址
int
*
*
*
p3
=
&
p2
;
//p3存儲p2的地址
*
p1
=
100
;
//*p1取出num變量
*
*
p2
=
200
;
//**p2取出num變量
*
*
*
p3
=
300
;
//***p3也是取出num變量
printf
(
"num = %d\n"
,
num
)
;
printf
(
"num = %d\n"
,
*
*
*
p3
)
;
return
0
;
}
|
7、指針與數組
指針能夠和整數進行加減運算
1
2
3
4
5
6
7
|
char
ch
=
'a'
;
char
*
p
=
&
ch
;
p
++
;
//p的值增長了一個char類型字節數
int
num
=
10
;
int
*
p1
=
&
num
;
p1
++
;
//p1的值增長了一個int類型字節數
|
遍歷數組大法:
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
|
#include <stdio.h>
int
main
(
)
{
int
num
[
]
=
{
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
0
}
;
int
length
=
sizeof
(
num
)
/
sizeof
(
int
)
;
int
*
p
=
num
;
//第一種,傳統遍歷大法
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
printf
(
"%d "
,
num
[
i
]
)
;
}
printf
(
"\n"
)
;
//第二種,移動地址指向 並取值來遍歷
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
printf
(
"%d "
,
*
(
p
+
i
)
)
;
}
printf
(
"\n"
)
;
//第三種,由於p == num,移動地址指向 並取值來遍歷
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
printf
(
"%d "
,
*
(
num
+
i
)
)
;
}
printf
(
"\n"
)
;
//第四種,根據每一個元素的地址來獲取值
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
printf
(
"%d "
,
*
(
&
num
[
i
]
)
)
;
}
printf
(
"\n"
)
;
//第五種,根據每一個元素的地址來獲取值
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
printf
(
"%d "
,
*
(
(
&
num
[
0
]
+
i
)
)
)
;
}
printf
(
"\n"
)
;
//第六種,判斷地址大小
for
(
;
p
<=
&
num
[
length
-
1
]
;
p
++
)
{
printf
(
"%d "
,
*
p
)
;
}
//重置p的值
p
=
num
;
printf
(
"\n"
)
;
//第七種,p自增
for
(
int
i
=
0
;
i
<
length
;
i
++
,
p
++
)
{
printf
(
"%d "
,
*
p
)
;
}
//重置p的值
p
=
num
;
printf
(
"\n"
)
;
//第八種,p自增
for
(
int
i
=
0
;
i
<
length
;
i
++
)
{
printf
(
"%d "
,
*
(
p
++
)
)
;
}
//重置p的值
p
=
num
;
printf
(
"\n"
)
;
return
0
;
}
|
指針數組:
所謂的指針數組,指的是一個專門用來保存多個相同數據類型指針的數組。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
#include <stdio.h>
int
main
(
int
argc
,
const
char
*
argv
[
]
)
{
int
num1
=
10
;
int
num2
=
20
;
int
num3
=
30
;
int
*
p1
=
&
num1
;
int
*
p2
=
&
num2
;
int
*
p3
=
&
num3
;
int
*
arr
[
]
=
{
p1
,
p2
,
p3
}
;
int
*
*
p4
=
arr
;
for
(
int
i
=
0
;
i
<
3
;
i
++
)
{
printf
(
"%d\n"
,
*
*
(
p4
+
i
)
)
;
}
return
0
;
}
|