例 数组元素的引用方法( 1 )
int main()// 下标法和地址法
{ int a[5], *pa, i;
for (i = 0; i < 5; i++)
a[i] = i + 1; pa
pa = a; a[0] 1
for (i = 0; i < 5; i++) a[1] 2
printf("*(pa+%d):%dn", i, *(pa+i)); a[2] 3
// 通过指针找地址法
a[3] 4
for (i = 0; i < 5; i++)
printf("*(a+%d):%dn", i, *(a+i)); a[4] 5
// 通过指针找地址法
for(i = 0; i < 5; i++)
printf("pa[%d]:%dn", i, pa[i]);
// 下标法
for (i = 0; i < 5; i++)
printf("a[%d]:%dn", i, a[i]);
// 下标法
return 0;
} 14
15.
例 数组元素的引用方法( 2 )
// 指针法
int main() 三种方法的比较:
{ 下标法和地址法的执行效率相同
int a[10]; ,都是先计算数组元素的地址,
int *p, i; 再访问数组元素的值,费时。
for (i = 0; i < 10; i++) 指针法利用指针变量直接访问数
scanf(“%d”, &a[i]); 组元素的值,不必计算数组元素
printf(“n”); 的地址,执行效率高。
for (p = a; p < a+10; p++) 下标法直观,指针法与地址法不
printf(“%d,”, *p); 够直观。
return 0;
}
15
16.
基于指针的数组程序设计
指针运算是处理数组元素的一种有效方式。设有 int 数
组a 和指针 p1,p2 ,下面代码都打印 a 的元素:
for (p1 = a; p1 < a+10; ++p1)
printf("%dn", *p1);
for (p1 = a; p1 - a < 10; ++p1)
printf("%dn", *p1);
for (p1 = a, p2 = a+10; p1 < p2; ++p1)
printf("%dn", *p1);
for (p1 = p2 = a; p1 - p2 < 10; ++p1)
printf("%dn", *p1);
16
17.
数组参数的意义
C 规定,数组参数就是相应类型的指针参数:
intf(int n, int d[]) {... ...}
和 int f(int n, int *d) {... ...}
意义相同。
数组参数就是利用指针实现的!
这也使采用数组参数的函数能修改实参数组。
17
18.
函数里也可用指针方式做元素访问。
int intsum (intn, int a[]) m+=a[i];
{ int i, m = 0;
for (i = 0; i < n; ++i) m += *(a+i);
return m;
}
int intsum (int n, int *a)
{ int i, m = 0;
for (i = 0; i < n; ++i) m += *(a+i);
return m;
}
函数里不能用 sizeof 确定数组实参大小:函数的数组形
参实际是指针,求 sizeof 算出的是指针的大小。
另一方面, sizeof 的计算是在编译中完成的。实参是动
态运行中确定的东西。 18
19.
使用数组的一段元素
以数组为参数的函数可处理一段元素。求元素和:
doublesum(int n, double a[]);
设有双精度数组 b , 40 个元素已有值:
用 sum 可求 b 所有元素之和 / 前一段元素之和:
x = sum(40, b);
y = sum(20, b);
sum 不知道 b 的大小,它由参数得到数组首元素地址,从这
里开始求连续 40 或 20 个元素的和。
也可用 sum 求 b 中下标 12 到 24 的一段元素之和。
z = sum(13, b+12);
19
20.
例 1 下面的程序的输出结果是什么?
#include <stdio.h>
int a[] = {2,4,7,8,9};
int main()
{ int i,*p = a;
for (i = 0; i < 4; i++)
a[i] = *(++p);
printf("%dn", a[2]);
return 0;
} 运行结果为: 8
20
21.
例 2 inta[] = {1,2,3,4,5,6,7,8,9,10}, *p = a, i;
数组元素地址的正确表示:
( A ) &(a+1) ( B ) a++ ( C ) &p √( D ) &p[i]
数组名是地址常量
p++,p-- ()
a++,a-- (×)
a+1, *(a+2) ()
21
22.
例 3 注意指针变量的运算
例 int main()
{ int a[] = {5,8,7,6,2,7,3}; a
p 6 0
5
int y, *p = &a[1]; p
8 1
y = (*--p)++;
printf(“%d ”, y); 7 2
printf(“%d”, a[0]); 6 3
return 0; 2 4
} 7 5
•*p++ ⇔*(p++) 3 6
•*p++ 、 *++p 、 (*p)++ 作用不同
输出: 5 6 *p++ 先取 p 指向变量的值再指针变量加 1
*++p 先使指针变量加 1 再取 *p
(*p)++ 使 p 指向的元素值加 1
22
23.
例 4 注意指针的当前值
int main()
{ int i, *p ,a[7]; a
p
p = a; 5 0
p
for (i = 0; i < 7; i++) 8 1
p
scanf("%d", p++); 7 2
printf("n"); p
6 3
p = a; p
2 4
for (i = 0; i < 7; i++, p++) p
7 5
printf("%d", *p); p
return 0; 3 6
p
}
指针变量可以指到数组后的内存单元
23
例 5 将数组a 中的 n 个整数按相反顺序存放( 1 )
void inv(int x[], int n)
{ int t, i, j, m = (n-1)/2;
for (i = 0; i <= m; i++) m=4
{ j = n-1-i;
t = x[i]; x[i] = x[j]; x[j] = t; 0 1 2 3 4 5 6 7 8 9
} 3 4 5 11 0 0 11 95 7 2
2 7 9 7 6 6 7 4 3
}
i i i i i j j j j j
int main()
{ int i, a[10] = {3,7,9,11,0,6,7,5,4,2};
inv(a, 10);
printf("The array has been
reverted:n");
for (i = 0; i < 10; i++)
printf("%d,", a[i]); 实参与形参均用数组
printf("n");
return 0;
}
28
29.
例 5 将数组a 中的 n 个整数按相反顺序存放( 2 )
void inv(int *x, int n) x i
a 数组
{ int t,*p,*i,*j, m = (n-1)/2; 3 2 a[0]
i
i = x; j = x+n-1; p = x+m; 7 4 a[1]
i
9 5 a[2]
for(;i <= p; i++, j--) i
11 7 a[3]
{ t = *i; *i = *j; *j = t; } p=x+m
i 0 6 a[4]
} j
6 0 a[5]
int main() j
7 11 a[6]
{ int i,a[10] = {3,7,9,11,0,6,7,5,4,2}; j
5 9 a[7]
j
inv(a, 10); 4 7 a[8]
j
printf("The array has been 2 3 a[9]
reverted:n");
for (i = 0; i < 10; i++)
printf("%d,", a[i]); 实参用数组 , 形参用指针变量
printf("n");
return 0;
} 29
30.
例 5 将数组a 中的 n 个整数按相反顺序存放( 3 )
void inv(int *x, int n)
{ int t,*i,*j,*p,m=(n-1)/2;
i=x; j=x+n-1; p=x+m;
for(;i<=p;i++,j--)
{ t=*i; *i=*j; *j=t; } 实参与形参均
} 用指针变量
int main()
{ int i, a[10], *p = a;
for (i = 0; i < 10; i++, p++)
scanf("%d", p);
p=a; inv(p, 10);
printf("The array has been reverted:n");
for (p = a; p < a+10; p++)
printf("%d", *p);
return 0;
} 30
31.
例 5 将数组a 中的 n 个整数按相反顺序存放( 4 )
void inv(int x[], int n)
{ int t, i, j, m = (n-1)/2;
for (i = 0;i <= m; i++)
{ j = n-1-i;
t = x[i]; x[i] = x[j]; x[j] = t;
}
} 实参用指针变量
int main() 形参用数组
{ int i, a[10], *p = a;
for (i = 0; i < 10; i++, p++)
scanf("%d", p);
p = a; inv(p, 10);
printf("The array has been reverted:n");
for (p = a; p < a+10; p++)
printf("%d ", *p);
return 0;
} 31
32.
例 6 分析程序写出结果
#include <stdio.h>
#define MAX 5
void fun1();
void fun2(int []);
int a[MAX];
int main()
{ fun1();
fun2(a);
printf("n"); 运行结果为: 0 4 8
return 0;
}
void fun1()
{ int k, t = 0;
for (k = 0; k < MAX; k++, t++) a[k] = t+t;
}
void fun2(int b[])
{ int k;
for (k = 0; k < MAX; k += 2)
printf("%4d", *(b+k));
} 32
33.
例 7 分析程序写出结果
#include <stdio.h>
void fun(int *s)
{
static int j = 0;
do{
s[j] += s[j+1];
} while(++j < 2);
}
int main()
{int k, a[10] = {1,2,3,4,5};
运行结果为: 3 5 7 4 5
for (k = 1; k < 3; k++)
fun(a);
for (k = 0; k < 5; k++)
printf(“%4d”, a[k]);
return 0;
} 33
34.
一级指针变量与一维数组的关系
int *p 与 int q[10]
数组名是指针(地址)常量
p = q; p+i 是 q[i] 的地址
数组元素的表示方法 : 下标法和指针法, 即
若 p=q, 则 p[i] ⇔ q[i] ⇔ *(p+i)
⇔ *(q+i)
形参数组实质上是指针变量,即 int q[ ] ⇔ int *q
在定义指针变量(不是形参)时,不能把 int *p
写成 int p[];
系统只给 p 分配能保存一个指针值的内存区 ( 一
般 4 字节);而给 q 分配 sizeof(int)*10 字节的内
存区
34
35.
字符指针与字符数组
常用字符指针指向字
符数组元素
定义字符指针时可用字符串常量初始化,如:
char *p = "Programming";
1 )定义了指针 p
2 )建立了一个字符串常量,内容为 "Programming"
3 )令 p 指向该字符串常量。图 (a)
char a[] = "Programming";
1 )定义了一个 12 个字符元素的数组
2 )用 "Programming" 各字符初始化 a 的元素,图 (b)
指针 p 数组 a
p r o g r a m m i n g 0 p r o g r a m m i n g 0
35
(a) (b)
36.
指针 p 数组 a
p r o g r a m m i n g 0 p r o g r a m m i n g 0
(a) (b)
1 )指针 p 可重新赋值(数组不能赋值 :a=“…” ):
p = "Programming Language C";
2 ) p 和 a 类型不同,大小不同。 a 占 12 个字符的空间。
3 ) a 的元素可以重新赋值。如:
a[8]='e'; a[9]='r'; a[10]='0';
a 的内容现在变成“ Programmer”
36
37.
// 字符串用字符数组实现 string
I string[0]
int main( ) string[1]
{ char string[] = " I love China! "; l string[2]
printf(" %sn ", string); o string[3]
printf(" %sn ", string+7); v string[4]
return 0; e string[5]
string[6]
}
C string[7]
// 字符串用字符指针实现 h string[8]
int main( ) i string[9]
{ char *string = "I love China!"; n string[10]
printf("%sn", string); a string[11]
string += 7; ! string[12]
while (*string) 0 string[13]
{ putchar(string[0]);
string++; I love China!
} China!
return 0;
} 37
字符指针作函数参数 a a b b
from I to y I
例 用函数调用实现字符串复制 o
( 1 )用字符数组作参数 a u a
m m
void copy_string(char from[],char to[])
a
{ int i = 0;
while (from[i] != '0') a r a
{ to[i] = from[i]; e
i++; t t
} e a e
to[i] = '0'; a a
} c s c
int main() h t h
{ char a[] = "I am a teacher."; e u e
char b[] = "You are a student.";
r d r
printf("string_a=%sn string_b=%sn", a, b);
copy_string(a, b); . e .
0
printf("nstring_a=%snstring_b=%sn", a, b); n 0
return 0; t t
} . .
43
0 0
44.
字符指针作函数参数 a a b b
from I to y I
例 用函数调用实现字符串复制 o
( 2 )用字符指针变量作参数 a u a
m m
void copy_string(char *from, char *to) a
{ for (; *from != '0'; from++, to++) r a
a
*to = *from;
e
*to = '0';
t t
}
int main() e a e
{ char a[] = "I am a teacher."; a a
char b[] = "You are a student."; c s c
h
printf("string_a=%snstring_b=%sn", a, b); t h
copy_string(a, b); e u e
printf("nstring_a=%snstring_b=%sn", a, b);
r d r
return 0; . e .
这里字符数
} n 0
组直接替换 0
为指针变量 t t
会出错 . .
44
0 0
作业(要求用指针方式处理)
1. 输入 10 个整数,将其中最小的数与第一个数对换,
把最大的数与最后一个数对换。要求写三个函数
a. 输入 10 个数(用指针法)
b. 进行处理(用指针操作)
c. 输出 10 个数(用指针法)
2. 从键盘输入若干(如 10 )个数,写一个函数对这组
数从第 begin (如 3 )个数到第 end (如 7 )个数
之间的数进行排序,要求形参用指针,实参用指针
或数组。
3. 有一个包含 n 个字符的字符串,写一个函数将这个
字符串中从第 m 个字符开始的其余 n-m+1 个字符修
改成为另一个特定的字符 c 。并在主程序中调用该
函数进行测试。
函数原型 void ChangStr(char *string, int n, int m, char
c); 47
4. P261 页第 4 题