c语言函数指针数组(精选11篇)
1.c语言函数指针数组 篇一
讲授
9.6二维数组和指针
2课时
掌握二维数组的地址表示方法 掌握指向数组元素的指针变量
掌握指向数组元素的指针变量
掌握用指向由m个元素组成的一维数组的指针变量
指向一维数组的指针变量
无
作业见后 一、二维数组的地址
例:定义二维数组int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};
则二维数组a是数组的数组,由3个一维数组所组成的,即3个元素:a[0],a[1],a[2]。而每个元素又是一个一维数组。
二、指向二维数组元素的指针变量
1、指向数组元素的指针变量
例1 用指向元素的指针变量输出二维数组元素的值 #include
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int *p;
for(p=a[0];p
{if((p-a[0])%4==0)printf(″\n″);
printf(″%4d″,*p); }
}用指向由m个元素组成的一维数组的指针变量
例2 输出二维数组任一行任一列元素的值 #include
int(*p)[4],i,j;
p=a;
scanf(“i=%d,j=%d”,&i,&j);
printf(“a[%d,%d]=%d\n”,i,j,*(*(p+i)+j)); } 注意:
指向一维数组的指针变量的定义格式应写成:基类型(*p)[N] 上述语句int(*p)[4],代表p是一个指针变量,它指向包含4个整型元素的一维数组。*p两侧的小括号不可少,如果写成*p[4],由于[]运算级别高于*,*p[4]是指针数组。
p=a;表明p指向数组a中的第0行,此时p+1不是指向a[0][1],而是指向a[1],p的增值以一维数组的长度为单位,p+1地址就增加了8个字节。*(p+i)+j是a[i][j]的地址,这里的i是以一维数组的长度为单位,j则是以数组元素的长度为单位的。
复习
新授
讲授
复习默写
1、选择排序的基本思想
2、从键盘输入5个整数,使用选择法从小到大排序,编程实现。
一、二维数组的地址
例:定义二维数组int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};
则二维数组a是数组的数组,由3个一维数组所组成的,即3个元素:a[0],a[1],a[2]。而每个元素又是一个一维数组。设二维数组的首行的首地址为2000,则:
二、指向二维数组元素的指针变量
1、指向数组元素的指针变量
例1 用指向元素的指针变量输出二维数组元素的值
#include
{ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};
int *p;
for(p=a[0];p
{if((p-a[0])%4==0)printf(″\n″);
printf(″%4d″,*p); }
}
注意:上例中如果对p赋值p=a[0];不能写成 p=a;因为此时a 是行指针,而p是列指针只能指向一个整型变量,a[0]是第0行的数组名,即第0行的首地址就是a[0][0]的地址。请学生思考上述赋值语句还可以写成什么? p=*a;p=&a[0][0];用指向由m个元素组成的一维数组的指针变量 例2 输出二维数组任一行任一列元素的值 #include
int(*p)[4],i,j;
p=a;
scanf(“i=%d,j=%d”,&i,&j); printf(“a[%d,%d]=%d\n”,i,j,*(*(p+i)+j)); }
注意:
指向一维数组的指针变量的定义格式应写成:基类型(*p)[N] 上述语句int(*p)[4],代表p是一个指针变量,它指向包含4个整型元素的一维数组。*p两侧的小括号不可少,如果写成*p[4],由于[]运算级别高于*,*p[4]是指针数组。
小结
作业
p=a;表明p指向数组a中的第0行,此时p+1不是指向a[0][1],而是指向a[1],p的增值以一维数组的长度为单位,p+1地址就增加了8个字节。*(p+i)+j是a[i][j]的地址,这里的i是以一维数组的长度为单位,j则是以数组元素的长度为单位的。
例3:
int(*t)[4],a[3][4]={{1,3,5,7}, {11,13,15,17},{21,23,25,27}};t = a;printf(“%d,%d”, **t, t[1][2]);t++;t++;printf(“%d”, **t);
运行结果:1,1521
【课堂小练习】
1、[2010.3.27]若有:int(*p)[3];则正确的是(D)A)定义了基类型为int的三个指针变量
B)p是基类型为int的具有三个元素的指针数组 C)定义了名为*p,具有三个元素的整型数组
D)定义了一个名为p的指针变量,它可以指向每行有三个整数元素的二维数组
2、输入:1 2 3<回车>,则输出结果是 int a[3][2]={0},(*p)[2],i,j;p=a;for(i=0;i<2;i++){ scanf(“%d”,p);p++;} for(i=0;i<3;i++)for(j=0;j<2;j++)printf(“%d”,a[i][j]);
1、二维数组的地址
2、指向数组元素的指针变量
3、指向一维数组的指针变量
1、整理课堂笔记
2、完成深入研究整型指针练习题
2.c语言函数指针数组 篇二
关键词:指针,数组,C语言
对于C语言编程新手来说, 经常认为"数组和指针是相同的"。其实这种说法是不完全正确的, 他们是有区别的。ANSIC标准6.542里建议:
注意下列声明的区别:
extern int*x;
extern int y[];
第一条语句声明x是一个int型的指针, 第二条语句声明y是int型, 数组长度尚未确定, 其存储在别处定义。
标准里并没有做更细的规定, 许多C语言书籍对数组和指针何时相同、何时不同也是含糊其辞一带而过。为了更好地理解指着与数组, 在这里我们谈谈他们之间的区别。
一、数组和指针的不同之处
我们来看以下代码:
程序编译时出错, 在这里, 数组a[100]与*a是两种不同的概念, 以上的错误相当于把浮点型数据和整型数据混为一谈, 如:
从上面, 我们可以很明显地看出int和char类型不匹配, 同理指针和数组两种不同类型也是不匹配。下面我们来谈谈是数组与指针的区别:
1. 指针和数组保存数据的内容不同
在C语言中, 我把地址形象地称为"指针", 把存放地址的变量称为指针变量, 通常我们把指针变量简称为指针, 所以指针里存放的是数据的地址, 而数组里存放的是数据的值。
2. 数组和指针的访问方式不同
数组采用的是直接访问方式, 而指针采用的是间接访问方式。
如:char a[6]="China"; c=a[3];
程序编译时, 给数组分配内存, 如图:
假设编译器符号表给的一个地址是2000程序运行时, 取3的值, 将它与2000相加, 取得 (2000+3) 的内容。在这里, 每个符号的地址在编译时可知。因此, 如果编译器需要一个地址来执行某个操作得花, 它就可以直接地进行操作, 并不需要增加指令取得具体的地址。相反, 对于指针, 它必须首先在运行时取得它的当前值, 然后才能对它进行解除操作。
如:char*p="China"; c=p[3];
编译器编译时, 编译器符号表给了一个p, 其地址假设为3000, 如图:
运行时, 取得地址3000的内容, 即5000, 后与3相加, 最后取 (5000+3) 的内容。
数组和指针的不同点还在于:指针通常由于动态数据结构, 而数组通常用于存储固定数目且数据类型相同的元素;指针用malloc () 、free () 函数来动态分配空间或释放空间, 而数组则隐式分配和删除;指针通常指向匿名数据, 而数组自身即为数据名;等。
二、数组和指针的相同之处
数组和指针什么时候相同呢?
1."作为函数参数的数组名"等同于指针
The C Programming Language, 第二版, Kernighan&Ritchie, 第99页里指出:
意思是:作为函数参数定义的形式参数, char s[]和char*s是一样的。
在函数形参定义这个特殊的情况下, 编译器必须把数组形式改写成指向数组第一个元素的指针形式。在这里, 编译器只向函数传递数组的地址, 而不是整个数组的拷贝。因此以下几种:
是一样的。
所以主函数的参数中char**argv和char argv[][]可以相互替换。
2."表达式中的数组名"就是指针, 数组下标作为指针的偏移量
假设我们声明:
int a[10], *p, i=1;
就可以通过以下任何一种方式访问a[i];
p=a;p[i];
或p=a;* (p+i) ;
或p=a+I;*p;
实际上, 我们还可以采用其它更多的方法。对于数组的引用如a[i]在编译时总是被编译器改写成* (a+i) 的形式。C语言标准要求编译器必须具备这个概念性的行为。我们可以这么记着:方括号[]表示一个取下标操作符, 就像减号表示一个减法运算符一样。取下标操作符就像取一个整数和一个指向类型X的指针, 所产生的结果类型是X, 一个在表达式中的数组名于是就成了指针。
在表达式中, 指针和数组是可以相互替换的, 因为他们在编译器里的最终形式都是指针, 并且都可以进行取下标操作。编译器可以自动把下标值的步长调整到数组的大小, 如:long型数据的长度是4个字节, 那么m[i]和m[i+1]在内存中的距离就是4, 而不是1。在对起始地址执行加法操作之前, 编译器会自动负责计算机每次增加的步长。这就是为什么指针总有类型限制的原因, 每个指针只能指向一种类型的原因是:因为编译器需要知道对指针进行解除引用操作时应该取多少个字节, 和每个下标的步长应取多少个字节。
三、总结
总而言之, 当声明时 (除作为函数参数除外) , 指针和数组是不能替换的, 如:"int a[10];", 只能用"extern a[10];", 而不能使用"extern*a;", 又如"int a[10];"和"in*a;"意义也是不同的;当作为函数参数或应用时, 两者是相同的, 如:"a[i]=5;"等同于"* (a+i) =5;", 又如, 主函数的参数中char**argv和char argv[][]可以相互替换。
参考文献
[1]谭浩强, C程序设计 (第三版) [M], 北京:清华大学出版社, 2005
[2]E.Balagurusamy, 标准C程序设计 (第4版) [M], 北京:清华大学出版社, 2008
3.C语言中数组的元素 篇三
关键词:数组;元素;数据;类型
中图分类号:TP313文献标识码:A文章编号:1007-9599 (2010) 16-0000-02
Elements of the Array in C-language
Zhang Kexing
(Foreign Language Teachers College of Taiyuan University,Taiyuan030012,China)
Abstract:The array is the most commonly used programming data st-
ructure.Array can be divided into array of values(integer group,real array),a character array and pointer array and the array of structures.
This array will be examples of various types were analyzed and explained.
Keywords:Array;Element;Data;Type
一、引言
數组是相互关联的一批数据的序列,序列中的数据称为数组的元素,可按照排列顺序编号,起始编号一般为0,前后两个数据的编号有差异,通过编号可以唯一指定数组中的数据成员。数组中的元素可以是基本类型,也可以是构造类型。按照数组元素的不同可将数组分为数值数组、字符数组、指针数组、结构数组。
二、数值数组
数值数组是指数组元素是整型、实型、及其相关类型的数据,简单说,就是元素是数字的数组。
例1:
main()
{
int i,a[10];
for(i=0;i<=9;i++)
a[i]=i;
for(i=9;i>=0;i--)
printf("%d ",a[i]);
}
在该例中,第一个for语句给数组a中的10个元素赋值为整形数据0-9,赋值以后数组中数据如下:
第二个for语句将数组a中的10个数字反序输出,即9、8、7、6、5、4、3、2、1、0
数值数组是数组中使用率最高的数组,需要注意的是一个数组中的数据必须是同一种类型的数据,
{int a[3];
a[0]=3;
a[1]=2.5;
a[2]=3.0;}
是不合法的。
三、字符数组
C语言没有专门定义字符串数据类型(如其他语言中的string),它用以' '结尾的字符数组来表示一个逻辑意义上的字符串。
字符数组主要有两种用途,(1)存储字符串,(2)存储字符或字符变量。这两个是不同的,刚开始接触时很容易混淆。下面进一步分析这两者的不同。
首先初始化时不同,用于存储字符串,例如:char str[]="Hello"; 用于存储字符或字符变量,例如:char Chars[]={‘H‘‘e‘,‘1‘‘1‘,‘o‘}。这两者的存储方式是一样的,但是存储内容稍微有所不同,那就是第一种情况会在结尾加上‘ ’,存储情况类似于{‘H‘‘e‘,‘1‘‘1‘,‘o‘,‘ ‘},存储空间会比第二种情况大一点,但是这个存在空间并不被计算进字符串(其实只是字符数组)变量中。
C语言中提供的字符串操作函数其实是针对于结尾是‘ ‘的字符数组进行的。输出函数printf中的输出参数%s也是针对于结尾是‘ ‘的字符数组。
另外,还有一种方法可以定义字符串(其实也是字符数组),声明如下:
char * string = "this is a point charArray.";字符指针指向字符数据的第一个字符的位置。
最后,有两点特别说明。
(1)字符串常量给出的是地址值。如
char *p, s[10];
p="hello";//正确
(2)不能用赋值语句给字符数组整体赋一串字符,例:
char str[10];
str = "abc";//错误
例2:
char c[10]={‘c’, ‘’, ‘p’, ‘r’, ‘o’, ‘g’, ‘r’, ‘a’,’m’};
赋值后数组元素如下:
四、指针数组
在C语言中,一个数组的元素值为指针则是指针数组。 指针数组是一组有序的指针的集合。指针数组的所有元素都必须是具有相同存储类型和指向相同数据类型的指针变量。
指针数组说明的一般形式为:
类型说明符*数组名[数组长度]
其中类型说明符为指针值所指向的变量的类型。
例如:
int *pa[3]
表示pa是一个指针数组,它有三个数组元素,每个元素值都是一个指针,指向整型变量。
例3:
通常可用一个指针数组来指向一个二维数组。指针数组中的每个元素被赋予二维数组每一行的首地址,因此也可理解为指向一个一维数组。
main(){
int a[3][3]={1,2,3,4,5,6,7,8,9};
int *pa[3]={a[0],a[1],a[2]};
int *p=a[0];
int i;
for(i=0;i<3;i++)
printf("%d,%d,%dn",a[i][2-i],*a[i],*(*(a+i)+i));
for(i=0;i<3;i++)
printf("%d,%d,%dn",*pa[i],p[i],*(p+i));
}
本例程序中,pa是一个指针数组,三个元素分别指向二维数组a的各行。然后用循环语句输出指定的数组元素。其中*a[i]表示i行0列元素值;*(*(a+i)+i)表示i行i列的元素值;*pa[i]表示i行0列元素值;由于p与a[0]相同,故p[i]表示0行i列的值;*(p+i)表示0行i列的值。
在C语言中,数组元素全为指针的数组成为指针数组。
一维指针数组的定义形式为:“类型名*数组标识符[数组长度]”。
例如,一个一维指针数组的定义:int *ptr_array[10]。
指针数组的含义:
指针数组中的每一个元素均为指针,即有诸形如“*ptr_array[i]”的指针。
由于数组名本身也是一个指针,因此指针数组中的元素亦可以表示为“*(*(ptr_ayyry+i))”。又因为“()”的优先级较“*”高,且“*”是右结合的,因此可以写作**(ptr_array+i)。
五、结构数组
数组的元素也可以是结构类型的。因此可以构成结构型数组。结构数组的每一个元素都是具有相同结构类型的下标结构变量。在实际应用中,经常用结构数组来表示具有相同数据结构的一个群体。如一个班的学生档案,一个车间职工的工资表等。
方法和结构变量相似,只需说明它为数组类型即可。
例4:
struct stu
{
int num;
char *name;
char sex;
float score;
}boy[5];
定义了一个结构数组boy,共有5个元素,boy[0]~boy[4]。每个数组元素都具有struct stu的结构形式。
例5:计算学生的平均成绩和不及格的人数。
struct stu
{
int num;
char *name;
char sex;
float score;
}boy[5]={
{101,"Li ping",'M',45},
{102,"Zhang ping",'M',62.5},
{103,"He fang",'F',92.5},
{104,"Cheng ling",'F',87},
{105,"Wang ming",'M',58},
};
main()
{
int i,c=0;
float ave,s=0;
for(i=0;i<5;i++)
{
s+=boy[i].score;
if(boy[i].score<60) c+=1;
}
printf("s=%fn",s);
ave=s/5;
printf("average=%fncount=%dn",ave,c);
}
本例程序中定义了一个外部结构数组boy,共5个元素,并作了初始化赋值。在main函数中用for语句逐个累加各元素的score 成员值存于s之中,如score的值小于60(不及格)即计数器C加1,循环完毕后计算平均成绩,并输出全班总分,平均分及不及格人数。
六、总结
数组是程序设计中最常用的数据结构。数组可分为数值数组(整数组,实数组),字符数组以及指针数组和结构数组。数组可以是一维的,二维的或多维的。数组类型说明由类型说明符、数组名、数组长度(数组元素个数)三部分组成。要想将不同的数据用不同类型的数组存放,就需要深入了解每一种类型的数组及其特点,这样才能灵活运用,充分发挥每种数据类型的长处。
参考文献:
[1]谭浩强.C程序设计教程[M].北京:清华大学出版社,2007,7
[2]李岩.C语言程序设计基础与上机知道[M].北京:清华大学出版社,2006,3
[3]马秀丽等.C语言程序设计[M].北京:清华大学出版社,2008,3
[4]罗坚.C语言程序设计[M].北京:中国铁道出版社,2009,2
作者簡介:
张科星(1980-),女,山西太原人,研究生,太原大学外语师范学院,助教,研究方向:网络,计算机教育。
4.C语言函数指针变量 篇四
在C语言中,一个函数总是占用一段连续的内存区,而函数名就是该函数所占内存区的首地址。我们可以把函数的这个首地址(或称入口地址)赋予一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以找到并调用这个函数。我们把这种指向函数的指针变量称为函数指针变量。
函数指针变量定义的一般形式为:
类型说明符(*指针变量名)();其中类型说明符表示现金网96y.org被指函数的返回值的类型。(* 指针变量名)表示*后面的变量是定义的指针变量。最后的空括号表示指针变量所指的是一个函数。例如:
int(*pf)();
表示pf是一个指向函数入口的指针变量,该函数的返回值(函数值)是整型。
本例用来说明用指针形式实现对函数调用的方法。
int max(int a,int b){
if(ab)return a;
else return b;
}
main(){
int max(int a,int b);
int(*pmax)();
int x,y,z;
pmax=max;
printf(input two numbers:n);
scanf(%d%d,x,y);
z=(*pmax)(x,y);
printf(maxmum=%d,z);
}
从上述程序可以看出用,函数指针变量形式调用函数的步骤如下:
先定义函数指针变量,如后一程序中第9行 int(*pmax)();定义 pmax为函数指针变量。
把被调函数的入口地址(函数名)赋予该函数指针变量,如程序中第11行 pmax=max;
用函数指针变量形式调用函数,如程序第14行 z=(*pmax)(x,y);
调用函数的一般形式为:(*指针变量名)(实参表)
使用函数指针变量还应注意以下两点:
函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而博彩娱乐棋牌q07i5.org函数指针的移动是毫无意义的。
5.C语言全局数组与局部数组 篇五
问题描述:
在全局声明的数组与在局部声明的数组有着不同的效果。
首先来看一个程序:
#include
#include
#define MAX 10
char a[MAX];
int main()
{
int i;
char b[MAX];
char *c=(char *)malloc(MAX * sizeof(char));
printf(“ Array a: ”);
for(i=0;i
printf(“%d ”,a[i]);
printf(“ Array b: ”);
for(i=0;i
printf(“%d ”,b[i]);
printf(“ Array c: ”);
for(i=0;i
printf(“%d ”,c[i]);
printf(“ Done”);
free(c);
return 1;
}
编译运行结果:
程序主要功能是打印字符数组的Ascii码。可以发现全局数组a和动态生成的数组c有着相同的结果,而局部声明的数组b确被分配了随机的数值,也许这就是问题的所在。
解决方案:
#include
#include
#define MAX 10
char a[MAX]={0};
int main()
{
int i;
char b[MAX]={0};
char *c=(char *)malloc(MAX * sizeof(char));
printf(“ Array a: ”);
for(i=0;i
printf(“%d ”,a[i]);
printf(“ Array b: ”);
for(i=0;i
printf(“%d ”,b[i]);
printf(“ Array c: ”);
for(i=0;i
printf(“%d ”,c[i]);
printf(“ Done”);
free(c);
return 1;
}
运行结果:
在数组的初始化中,假设初始化的数值个数小于数组的大小,则全部用0来填充,
这里通过初始化一个值,就可以给数组一个确定的结果。
(在不同系统和不同的编译器可能会出现不同的结果)
还有一个小问题就是C语言中空格的问题,看下面的程序。
#include
#include
#define MAX 10
int main()
{
int i;
char b[MAX]={0};
gets(b);
printf(“ Array b: ”);
for(i=0;i
printf(“%d ”,b[i]);
printf(“ Done”);
return 1;
}
在这里,我输入了“ int”(三个空格+int),打印的结果如上图。
b中前三个记录了空格的Ascii码,即32。
b中后面没有使用的空间依然是0。
打完收工。
6.大一c语言数组实验心得 篇六
“; fori1;i10;i {printf“a[d]“,i; scanf“d“, } printf“
“; printf“原数据为
“; fori1;i10;i printf“5d“,a[i]; printf“
“; fori1;i9;i {mini; forji1;ja[j] minj; sa[i]; a[i]a[min]; a[min]s; }printf“排好序的数组为
“; fori1;i10;i printf“5d“,a[i]; printf“
7.c语言函数指针数组 篇七
关键词:C语言KM教学法指针
中图分类号:G420文献标识码:A文章编号:1674-098X(2011)06(a)-0190-01
教学方法是教师为完成教学任务所采用的手段,对教学目的的实现具有重要意义。在确定了教学目的,有了相应的教学内容之后,为了取得预期的教学效果,就必须采用适当的教学方法。教学方法要与学生的认识规律相适应,要与训练指导思想和教学原则相适应。因此,教育工作者在教学方法上作了大量的改革和创新,如问题教学法[1]、任务驱动法[2]、专题式教学、引导发现教学法、互动教学法、问答式教学法以及KM教学法[3][4]等。其中,KM 教学法符合教学赖以存在和发展的认知机理,能够系统而有重点地组织教学内容,符合学习思维的逻辑认知过程,它贯穿于教学的主要环节,具有实用性和通用性。
1 C语言指针
C语言因为其功能强大、使用灵活、可移植性好,几乎成为了高校大学生必修的一门课程,在大学生计算机知识体系中有着重要的基础性作用。
指针是C语言中非常重要的一种数据类型,也是C语言的一个重要特色,灵活掌握指针的用法是C语言使用能力的一个标志。正確而灵活地运用它可以有效地表示复杂的数据结构,能动态地分配内存。能直接处理内存地址等,可以使程序简洁、紧凑、高效。这对软件设计十分必要。但是指针概念比较复杂。应用也比较灵活且容易出错,学习者较难掌握,是C语言教学的难点。
特别对于初学者来说,指针通常比较难理解。而由指针错误引起的调试问题连富有经验的程序员都感到头痛。然而,指针是大多数C语言程序的重要组成部分,在C语言的高级编程中基本都涉及到指针的应用,而且在以后的许多C++程序中仍然受到重用。
2 KM教学法
KM是指在“知识逻辑结构”(Knowledge Logic Structure)的总体架构下融入“思维导图”(Mind Mapping)进行微观演绎[4]。知识逻辑结构(K)是通过知识逻辑结构图的形式给出所论知识系统的总体框架,表示了其中各知识子系统间的内在联系,是从宏观层面而论的,而思维导图(M)则是从微观层面揭示了知识子系统中思维过程的一种自然导向的表达。
在教学实施过程中,先讲逻辑结构或知识框架,使得学生对所要学的知识全貌一目了然,有一个宏观的认识,并且很容易理清知识总体条理;然后再在框架中填充知识,是一个微观学习的过程,而在介绍微观知识的过程中,借助思维导向启发学生对知识进行逐层深入的研究;最后再把填充知识概括起来,重新回到主框架中,使得学生加深对知识的理解和掌握,以便进入下一部分知识。从而形成以知识逻辑结构为主体贯穿、将思维导图融入进去的一种综合集成、多层次递阶的知识认知系统,完全符合学生学习和认知事物的科学规律。
本文从KM教学法入手,介绍C语言程序设计中指针的知识逻辑结构与框架,以及各知识点之间的内在联系,从而达到熟练应用指针的目的。
3 应用KM教学法的C语言指针教学
指针是C语言的重要组成部分,是C语言程序设计的难点之一。本文以清华大学出版社出版的C程序设计[5](第三版)为主,辅以程序设计中涉及到的其他指针部分,对指针涉及到的知识点进行归纳总结,设计了指针的逻辑思维图,以整型(int)为例,假设已经正确定义了整型变量x,y,z,且已经正确初始化。
教学中,首先根据程序中的变量都是要存储的,引入指针的概念:指针就是用来指向变量的,具体地说,指针就是地址,指针保存的就是其所指向的变量的地址。从而引出指针变量的定义形式(以int为例): int x;int *p=&x; 这就定义了一个整型的指针变量p,该指针指向整型变量x。进而一步一步对指针所涉及到的知识点一一展开,详述其定义方式与应用形式,最后介绍指针的运算方式等。
4 结语
指针是C语言最显著的特征,也是C语言中的重点难点内容.熟练使用指针,可以使程序质量提高,且编写程序更方便、灵活。本文根据KM教学法按照知识延伸和发展的内在逻辑性,确立以讲授知识的逻辑结构、理论框架和内在联系为主,对思维活动加以诱导,坚持“先搭架,后填充,再诱导”和少而精的原则,进行指针知识的组织和教学,是一种非常值得大力推广的教学方法。
参考文献
[1] 吕伟.应用问题教学法改革材料力学的课堂教学模式[J].力学与实践,2001.
[2] 胡宁.计算机教学中的任务驱动法[J].辽宁师专学报:自然科学版,2005.
8.C语言指针实习 篇八
一、实习目的
姓名:尹思智
学号:2012014413
完成日期:2013年4月
1.由键盘输入10个整数,将它们从小到大排序 2.将10个字符串(设其长度小于30)排序。
3.找出二维数组(设4行5列)中的最大数及其位置。
4.从键盘输入一串字符,从下标为m的字符开始,取出n个字符(m和n从键盘输入),形成一个新字符串 5.实现字符串的拷贝
6.编写一程序,将一个字符串反序存放。
二、实习步骤
1.由键盘输入10个整数,将它们从小到大排序 #include scanf(“%d”,p);for(i=0;i<10;i++)for(p=a;p if(*p>*(p+1)) { t=*p; *p=*(p+1); *(p+1)=t;} for(p=a;p printf(“%d ”,*p);} 2、将10个字符串(设其长度小于30)排序 #include str[i]=cty[i];printf(“输入十个字符串:n”);for(i=0;i<10;i++) gets(cty[i]);for(i=0;i<9;i++){ k=i; for(j=i+1;j<10;j++) if(strcmp(str[k],str[j])>0) k=j; temp=str[k]; str[k]=str[i]; str[i]=temp;} printf(“排序后:n”);for(i=0;i<10;i++) printf(“%sn”,str[i]);} 2.将10个字符串(设其长度小于30)排序。 3.找出二维数组(设4行5列)中的最大数及其位置。 4.从键盘输入一串字符,从下标为m的字符开始,取出n个字符(m和n从键盘输入),形成一个新字符串 5.实现字符串的拷贝 6.编写一程序,将一个字符串反序存放。 一、教学目标 1、通过本次课教学,学生能进一步理解二维数组的定义,二维数组的引用的方法; 2、掌握二维数组的初始化 3、技能目标:培养学生逻辑思维能力、综合运用知识的能力和自主学习能力; 二、教材分析 选用教材为李腾编著的《编程语言基础——C语言》,该教材由国防科技大学出版社出版,教材特点如下: 1、在内容上体现科学性、时代性、实用性,编排上面向应用,理论与实践有机结合; 2、采用案例教学法等教学手段,各章节均有案例,贯穿整个课程进行难点讲解,以实际应用作为突破口,使学生能够真实体验到知识的实际应用,提高兴趣,促进理解;教学与项目开发融为一体,浅显易懂,符合中职学生认知规律。 3、实验实训环节结合教学内容,实验项目丰富。课程设计中案例学生熟悉。本节课教学内容参考教材第4章的4.2节:二维数组。 三、学生分析 本课程的教学对象是中职学生,他们文化基础较差,计算机专业知识薄弱,C语言程序设计是他们学习的第一门计算机语言类课程,学习时较困难,入门较慢。本次课的教学内容中数组的概念他们容易理解,简单的一维数组对他们不太难,但涉及二维数组的编程较为困难。 另外,中职学生对于上机实际操作要比学习理论知识更为有兴趣;简单的实验项目都能完成,但解决实际应用问题的能力也较差。因此,在教学中通过演示让学生有感性认识,提高学习兴趣;通过提出问题让学生讨论议一议,主动思考如何解决;通过一个教学任务让学生动手做一做。 四、教学重点、难点及解决办法 1、本次课教学重点 1)二维数组的定义; 2)二维数组元素的引用; 在教学过程的叙述中,要抓住教学的重点、最能体现教学理念的内容和最能展示教学艺术的环节,作较为详细的叙述。 2、本次课教学难点 1)二维数组的初始化 2)二维数组的实际应用 3、难点解决办法 1)通过演示让学生有感性认识,并从一维数组入手,逐步引入二维数组的概念,弱化实用性不强的细节; 2)围绕字符数组进行难点讲解,以实际应用作为突破口,使学生能理解二维数组在实际中的应用,提高学习兴趣; 3)针对难点设置上机实际操作内容,进一步掌握二维数组程序设计方法。4)在实验实训过程中布置任务项目,通过实践环节进一步理解和掌握重点难点,达到学习目的。 五、教学理念、方法及手段 本次课采用理(论)实(践)一体化教学理念通过任务驱动(项目教学)、讲练结合等教学手段。 1、任务驱动:通过书上实例这一任务,掌握二维数组程序设计认方法。并掌握相应知识点,突出重点,分解难点。 2、讲练结合:授课地点为计算机实验室,采用边讲边练的教学互动形式。教学过程中,适当安排学生在计算机上进行进行实际程序设计,通过运行调试自己设计的程序,让学生亲自观察和体验程序设计的成功感受,加深知识的理解。 六、教学设计(时间分配) 1、任务提出,演示成果程序,明确目标,提出要求。(3分钟)(1)演示程序成果,在屏幕上输入源程序,并运行。 (2)任务分析:完成本次课的任务所需知识―――二维数组的应用。 2、知识回顾(3分钟) 数组的概念,一维数组的定义,一维数组元素的引用,一维数组的初始化,注意事项。 3、上机实训1(3分钟) 简单程序:用一维数组编程,实现在屏幕上显示1,2,3……10。 (上机技能训练的操作、指导、辅导过程,以学生实际操作动手为主,教师进行辅导指导、师生共同探讨完成,应充分体现学生的主体地位)思考提问:如何输出一个表格。 4、导入新课(6分钟) (1)通过练习1,分析在屏幕上输出中存在的问题。(2)二维数组的定义,引用与初始化。 5、上机实训2,(6分钟)输出一个二维表: 1 5 9 11 12 6、上机实训3:4.6编程将数组a[3][4]转置(8分钟)(1)调试程序时要注意观察程序运行情况。程序出错原因,提醒以后编程时注意。 7、上机实训4,从键盘输入年、月、日,计算该日是这一年的第几天(10分钟) 8、课堂小结及作业(5分钟) 9、Question & Answer(1-2分钟) 七、学法指导 1、鼓励学生自主探索和合作交流。引导学生自主地从事观察、分析、交流等活动,使学生形成对计算机语言知识有效的学习策略。 2、鼓励与提倡解决问题的多样性,引导学生在与他人的交流中去选择合适的策略,丰富自己的思维方式,获得成功的体验和不同的发展。 C是对底层操作非常方便的语言,而底层操作中用到最多的就是指针,以后从事嵌入式开发的朋友们,指针将陪伴我们终身。 本文将从八个常见的方面来透视C语言中的指针,当然,还有其他没有具体提到的方面,像指针表达式、指针安全等问题,以后有机会我再慢慢补充。 还是那句老话,重要的是实践,多写代码,才是学好C语言的关键。1.指针类型分析 分析指针,可以从变量名处起,根据运算符优先级结合,一步一步分析.int p;//这是一个普通的整型变量 int *p;//首先从P处开始,先与*结合,所以说明P是一个指针,然后再与int结合,说明指针所指向的内容的类型为int 型.所以 P是一个返回整型数据的指针 int p[3];//首先从P处开始,先与[]结合,说明P 是一个数组,然后与int结合,说明数组里的元素是整型的,所以 P是一个由整型数据组成的数组 int *p[3];//首先从P处开始,先与[]结合,因为其优先级比*高,所以P是一个数组,然后再与*结合,说明数组里的元素是指针类型,然后再与 int结合,说明指针所指向的内容的类型是整型的,所以是一个由返回整型数据的指针所组成的数组 int(*p)[3];//首先从P处开始,先与*结合,说明P是一个指针然后再与[]结合(与“()”这步可以忽略,只是为了改变优先级),说明指针所指向的内容是一个数组,然后再与int 结合,说明数组里的元素是整型的.所以P是一个指向由整型数据组成的数组的指针 int **p;//首先从 P开始,先与*结合,说明P是一个指针,然后再与*结合,说明指针所指向的元素是指针,然后再与 int结合,说明该指针所指向的元素是整型数据.所以P是一个返回指向整型数据的指针的指针 int p(int);//从P处起,先与()结合,说明P是一个函数,然后进入()里分析,说明该函数有一个整型变量的参数然后再与外面的int 结合,说明函数的返回值是一个整型数据.所以P是一个有整型参数且返回类型为整型的函数 int(*p)(int);//从P处开始,先与指针结合,说明P是一个指针,然后与()结合,说明指针指向的是一个函数,然后再与()里的int 结合,说明函数有一个int 型的参数,再与最外层的int 结合,说明函数的返回类型是整型,所以P是一个指向有一个整型参数且返回类型为整型的函数的指针 int *(*p(int))[3];//从 P开始,先与()结合,说明P是一个函数,然后进入()里面,与int结合,说明函数有一个整型变量参数,然后再与外面的*结合,说明函数返回的是一个指针,然后到最外面一层,先与[]结合,说明返回的指针指向的是一个数组,然后再与*结合,说明数组里的元素是指针,然后再与int 结合,说明指针指向的内容是整型数据.所以P是一个参数为一个整数且返回一个指向由整型指针变量组成的数组的指针变量的函数 2.指针分析 指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型、指针所指向的类型、指针的值或者叫指针所指向的内存区、指针本身所占据的内存区。 指针的类型:把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型 指针所指向的类型:把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型(在指针的算术运算中,指针所指向的类型有很大的作用) 指针所指向的内存区:从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。(一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址)指针本身所占据的内存区:用函数sizeof(指针的类型)可以测出指针本身所占据的内存区(在 32位平台里,指针本身占据了 4个字节的长度)3.指针的算术运算 指针和整数进行加减:一个指针 ptrold加(减)一个整数 n后,结果是一个新的指针ptrnew,ptrnew 的类型和 ptrold 的类型相同,ptrnew 所指向的类型和 ptrold所指向的类型也相同,ptrnew的值将比 ptrold 的值增加(减少)了n乘sizeof(ptrold所指向的类型)个字节。 指针和指针进行加减:两个指针不能进行加法运算,这是非法操作;两个指针可以进行减法操作,但必须类型相同,一般用在数组方面。4.运算符&和* &是取地址运算符,*是间接运算符。 &a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。 *p的运算结果就五花八门了,总之*p 的结果是 p 所指向的东西,这个东西有这些特点:它的类型是 p指向的类型,它所占用的地址是p所指向的地址。5.数组和指针的关系 数组的数组名其实可以看作一个指针。 声明了一个数组 TYPE array[n],则数组名称array就有了两重含义: 第一,它代表整个数组,它的类型是 TYPE[n]; 第二,它是一个常量指针,该指针的类型是TYPE*,该指针指向的类型是 TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0号单元,该指针自己占有单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似 array++的表达式是错误的。6.指针和结构类型的关系 假设我们定义了一个结构体,struct MyStruct{inta;int b;int c;};同时定义结构体的结构对象并初始化,struct MyStructss={20,30,40};那么我们如何通过指针ptr 来访问 ss的三个成员变量呢? 答案就是,我们先定义一个指向结构对象 ss的指针,struct MyStruct *ptr=&ss;然后,使用指向运算符->便可实现对结构对象ss成员的访问。ptr->a;//或者可以这们(*ptr).a,建议使用前者 ptr->b;ptr->c; 7.指针和函数的关系 可以把一个指针声明成为一个指向函数的指针,从而通过函数指针调用函数。让我们举一个例子来说明以下吧。 int fun(char *,int);int(*pfun)(char *,int);pfun=fun; int a=(*pfun)(“abcdefg”,7); 例中,定义了一个指向函数fun的指针pfun,把pfun作为函数的形参。把指针表达式作为实参,从而实现了对函数fun的调用。8.指针类型转换 当我们初始化一个指针或给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式,这就要求两边的类型一致,所指向的类型也一致,如果不一致的话,需要进行强制类型转换。语法格式是:(TYPE *)p; 这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE *,它指向的类型是TYPE,它指向的地址就是原指针指向的地址。要注意的是,原来的指针p的一切属性都没有被修改。 课题: 教学目的: 教学重点: 教学难点: 第十章 指针 §1-§2 1、了解指针与地址的概念 2、掌握指针变量的定义、初始化及指针的运算 指针变量的定义、初始化及指针的运算 指针的运算 步骤一 复习引导 指针是C语言的一个重要概念,也是C语言的一个重要特色。正确而灵活地运用它,可以有效地表示复杂的数据结构;能动态分配内存;能方便地使用字符串;有效而方便地使用数组;在调用函数时能得到多于1个的值;能直接处理内存地址等,这对设计系统软件是很必要的。 指针的概念比较复杂,使用也比较灵活,因此初学者时常会出错,务请在学习本章内容时十分小心。 步骤二 讲授新课 §10.1 地址和指针的概念 计算机的主存储器被分成一个个存储单元,为了区分各存储单元,要为每个存储单元编号,这个编号即地址。 例:i =3; 或 scanf(“%d”, &i); 是将3送给 i所在的空间。 例:将3送到变量I_pointer所“指向”的单元(即I所标志的单元)。 所谓“指向”,是通过地址来体现的,I_pointer中的值为2000,它是变量I 的地址,这样就在I_pointer和变量之间建立起一种联系,即通过I_pointer能知道I的地址,从而找到变量I的内存单元。因而在C语言中,将地址形象化地称为“指针”。 意思是通过它能找到以它为地址的内存单元。一个变量的地址称为该变量的“指针”。 内存单元的地址和内存单元的内容是两个不同的概念。 指针:就是地址,即内存单元的编号。 指针变量:用来存放另一变量的地址(即指针)的变量。 如:地址2000是变量 i的指针;i_pointer是指针变量,其值就是指针2000。 §10.2变量的指针和指向变量的指针变量 变量的指针就是变量的地址。 存放变量地址的变量是指针变量,用来指向另一个变量。 *i_pointer 表示 i_pointer 所指向的变量。 一、定义一个指针变量 指针变量的定义包含三个方面的内容: ⑴ 指针类型说明,即定义变量为一个指针变量 ⑵ 指针变量名 ⑶ 变量值(指针)所指向的变量的数据类型。格式: 存储类型 基类型 *指针变量名;例:int *pointer_1, *pointer_2; float *pointer_3; char *pointer_4; 二、指针的引用 指针变量有两个运算符: & :取地址运算符 功能:取变量地址;单目,右结合。 * :取内容运算符(“间接访问”运算符) 功能:只能跟地址,取变量所指向单元的内容;单目,右结合。 例:&a为变量a的地址,*p 为指针变量p所指向的存储单元。 例:int a=5, *p=&a; printf(“%d”, *p);main(){ int a,b; int *pointer_1,*pointer_2; a=100;b=10; pointer_1=&a; /*把变量a的地址赋给pointer_1*/ pointer_2=&b; /*把变量b的地址赋给pointer_2*/ printf(“%d,%dn”,a,b); printf(“%d,%dn”,*pointer_1, *pointer_2);} 输出结果:100, 10 100, 10 评注: 1、在第3行虽然定义了两个指针变量,只是提供了两个指针变量,但并未指向任何一个整型变量。称为指针“悬空”。 2、最后一行的*pointer_1和pointer_2就是变量a和b。 3、程序中两处出现*pointer_1等,含义不同。程序第3行中的*pointer_1表示定义指针变量pointer_1。它前面的*只是表示该变量是指针变量。程序最后一行中的*pointer_1则代表变量,即pointer_1所指向的变量。 4、第5行中的pointer_1=&a 是将a的地址赋给指针变量pointer_1,而不是*pointer_1。 注意:不应写成:*pointer_1=&a; 5、从上例中可看出,*pointer_1等价于a,*pointer_2等价于b,故凡在程序中出现a的地方均可用 *pointer_1 代替。所以,若有: int x, y, *px=&x;则下面的运算均是正确的: y=*px+1; /*把 x 的内容加1 送变量y*/ printf(“%dn”, px); /*打印当前x 的内容*/ d=sqrt((double)px); /*把x的平方根送变量d*/ px=0; /*把 x 置为0*/ *px+=1; /*把 x 的值加 1*/(*px)++; /*使 x 的值加 1*/ y=(*px)++; /*即y=x, x++*/ 6、假设px和py都被定义为指向int 对象的指针,而且px当前已指向了int 型变量x,则执行: py=px; /*把指针px的内容拷贝到指针py中去*/ 即 py和px 这两个不同的指针指向了同一对象x 7、指针不是整数,不能将它与整数混为一谈。例: # include 例如: # include b = d; printf(“%d n”, b); …… }——编译不出错,但得不到希望的值 关于&和*运算符的说明: 假设已执行 pointer_1=&a; 1、&*pointer_1含义是什么? &*pointer_1与&a相同,即变量a的地址。 2、*&a的含义是什么? 先进行&a运算,得a的地址,再进行*运算。 *&a、*pointer_1及变量a等价。 3、(*pointer_1)+ + 相当于a + +。 它与*pointer_1 + + 不同。 4、*pointer_1 + + 等价于*(pointer_1 + +),即先进行*运算,得到a的值,然后使pointer_1的值改变,这样pointer_1不再指向a了。 例10.2:输入a和b两个整数,按先大后小的顺序输出a和b。 main(){ int *p1,*p2,*p, a, b; scanf(“%d,%d”,&a,&b); p1=&a;p2=&b; if(a {p=p1;p1=p2;p2=p;} printf(“n a=%d,b=%dn”,a,b); printf(“max=%d,min=%dn”,*p1,*p2); } 运行情况: 5,9 三、指针变量作为函数参数 例10.3对输入的两个整数按大小顺序输出。先考察如下程序,看是否能得到预期的结果 swap(int p1, int p2){ int temp;temp = p1;p1 = p2;p2 =temp;} main(){ int a, b; scanf(“%d, %d”, &a, &b); if(a printf(“n%d,%dn”,a,b);} 不能得到预期的结果。改为: swap(int *p1,int *p2){ int temp; temp = *p1; *p1 = *p2; *p2 =temp;} main(){ int a,b; int *pointer_1,*pointer_2; scanf(“%d,%d”,&a,&b); pointer_1=&a; pointer_2=&b; if(a swap(pointer_1,pointer_2); printf(“n%d,%dn”,a,b);} 注:如果想通过函数调用得到n个改变的值,可以: 1、在主调函数中设n 个变量,用n个指针变量指向它们; 2、然后将指针变量作实参,将这n 个变量的地址传给所调用的函数的形参; 3、通过形参指针变量,改变该n个变量的值; 4、主调函数中就可以使用这些改变了值的变量。 四、指针(变量)的初始化 指针置初始化值的格式: 存储类型 基类型 *指针名=初始化值; 如:main() { static int a; int *p=&a, *p1=p; …… } 再如: int *p = 0; 或 int *p = NULL; 五、指针的运算 1、指针的算术运算 指针仅能进行加、减算术运算 如:p+n , p-n , p++ , p--, ++p ,--p p-= n , p+= n , p1-p2 等 其中n是整数,p、p1、p2均为指针; 施行加法运算时,指针向地址增大的方向移动; 施行减法运算时,指针向地址减小的方向移动; 移动长度取决于指针的基类型,由计算机决定; 如有:int a,b,c, *pt =&a; 则 pt++ 则指针向后移动两个字节; 再如:main() { int *p1,a=8,b=3; p1=&a; printf(“%d,%dn”,(*p1)++, *p1++); printf(“%d,%dn”,a, *p1); } 运行结果:3,8,4 注:p1+k = p1+k*sizeof(p1的基类型); p1-k = p1-k*sizeof(p1的基类型);如: strlen(char *s) { char *p=s; while(*p!=„‟)p++; return(p-s); } 2、指针的关系运算 设指针p1,p2指向同一数组中的元素,则 p1 p1 p1= =p2: 表示p1、p2指向数组中的同一元素; 同理可推出>、>=、<=、!=比较的意义; 不可将指针与其他类型的对象作比较; 若两指针指向不同数组中的元素,也不可比较; 允许将指针与NULL或数值0进行= =或!=的比较,以便判定一个指针是否为空指针。 步骤三 课堂小结 本课介绍了指针与地址的概念,指针变量的定义、初始化及指针的运算。 指针:就是地址,即内存单元的编号。 指针变量:用来存放另一变量的地址(即指针)的变量。 例如:int a=5, *p=&a; printf(“%d”, *p); 注意:运算符*和&的用法,指针变量的自加自减运算。步骤四 布置作业 课后作业:第十章课后练习10.1 10.2 课题: 教学目的: 教学重点: 教学难点: 第十章 指针 §3 掌握指针与数组的知识 指向数组的指针变量 指向二维数组的指针 步骤一 复习引导 上节课介绍了指针变量的定义及其赋值。一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组和数组元素(把数组起始地址或某一元素的地址放到一个指针变量中)。 步骤二 讲授新课 所谓数组的指针是指数组的起始地址,数组元素的指针是数组元素的地址。 引用数组元素可以用下标法(如a[3]),也可以用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序质量高(占内存少,运行速度快)。 一、指向一维数组的指针 定义形式: int a[10]; int *p; p=&a[0]; 或 p=a; 含义:把数组的首地址赋给指针变量p。 也即: int *p=&a[0]; 或 int *p=a; 二、通过指针引用数组元素 按C的规定:如果指针变量p已指向数组中的一个元素,则p+1指向同一个数组中的下一个元素(而不是简单地加1)。 如果p的初值为&a[0],则: p+i a+i &a[i],即指向a数组的第i个元素。 *(p+i) *(a+i) a[i]。 指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价 引用数组元素时,可以用: 1、下标法,如:a[i] 2、指针法,如:*(a+i) 或 *(p+i) 其中,a是数组名,p是指向数组的指针 例10.5:输出数组中的全部元素 假设有一个a数组,整型,有10个元素。用三种方法输出各元素的值: 1、下标法: main(){ int a[10], i; for(i=0;i<10;i++) scanf(“%d”,&a[i]); printf(“n”); for(i=0;i<10;i++) printf(“%d”,a[i]);} 2、利用数组名计算数组元素地址,找出元素的值。main(){ int a[10], i; for(i=0;i<10;i++) scanf(“%d”,&a[i]); printf(“n”); for(i=0;i<10;i++) printf(“%d”,*(a+i));} 3、用指针变量指向数组元素。main(){ int a[10], *p, i; for(i=0;i<10;i++) scanf(“%d”,&a[i]); printf(“n”); for(p=a;p<(a+10);p++) printf(“%d”,*p);} 评注: 1、第1和2种方法执行效率是相同的。 2、第3种方法效率高。 3、用下标法比较直观。 在使用指针变量时,有几个问题要注意: 1、指针变量可以实现使本身的值改变。如:for(p=a;p<(a+10);p++) 2、要注意指针变量的当前值。 如:要通过指针变量输出a数组的10个元素。main(){ int a[10], i , *p=a; for(i=0;i<10;i++) scanf(“%d”, p++); printf(“n”); for(i=0;i<10;i++,p++) printf(“%d”, *p);} 这个程序输出的并不是a数组中各元素的值。因为第一个 for 循环结束时,p已经指向数组的末尾。再继续下去,p指向的是a数组下面的10个元素,是不可预料的。可加一句为:p=a; 3、用指针变量p指向数组元素,可以指到数组以后的内存单元。C编译程序不作下标越界检查。 4、注意指针变量的运算。如果p指向数组a,⑴ p++(或 p+=1),使p指向下一元素a[1]。⑵ *p++ 等价 *(p++)。作用是先得到p指向的变量的值(即*p),然后再使p+1→p。⑶ *(p++)与*(++p)不同。前者为a[0],后者为a[1] ⑷(*p)++表示p指向的元素值加1,即(a[0])++ ⑸ 如果p当前指向a数组中第i个元素,则: *(p--)相当于a[i--],先对p进行*运算,再使p自减; *(+ + p)相当于a[+ +i],先使p自加,再作*运算。*(-){ temp=*i;*i = *j;*j =temp;} return;} main(){ int i, a[10],*p=a;printf(“The original array: n ”);for(i=0;i<10;i++,p++)scanf(“%d”, p);printf(“n”);p=a;inv(p,10);printf(“The array is : n”);for(p=a;p 例10.10:用选择法对10个整数排序。main(){int *p, i, a[10];p=a;for(i=0;i<10;i++)scanf(“%d”,p++);p=a;sort(p,10);for(p=a, i=0;i<10;i++){ printf(“%d”,*p);p++;} } sort(int x[],int n){ int i, j, k, t;for(i=0;i 四、指向二维数组的指针和指针变量 1、二维数组的地址如: int a[3][4] A a[0] a[0] [0] a[0] [1] a[0] [2] a[0] [3] A+1 a[1] a[1] [0] a[1] [1] a[1] [2] a[1] [3] A+2 a[2] a[2] [0] a[2] [1] a[2] [2] a[2] [3] 例:int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; 设首地址为2000。 a[k]+p(0<=k< i , 0<=p a+k与&a[k][0]等价,而a[0]+k与&a[0][k]等价; *(a+i)可理解为a[i],故有如下等价关系: a+0 等价于 a[0]、a[0]+0、&a[0][0]、*(a+0) a+1 等价于 a[1]、a[1]+0、&a[1][0]、*(a+1) a+(i-1)等价于 a[i-1]、a[i-1]+0、&a[i-1][0]、*(a+i-1) *(a+k)与*a[k]是不同的,前者相当于a[k],是一个地址值;后者相当于*(a[k]+0)或*&a[k][0],是数组元素a[k][0]中存储的值。 数组元素a[k][p]就是*(a[k]+p),即*(*(a+k)+p) 步骤三 课堂小结 本课介绍了指向数组的指针,主要是指向一维数组的指针。用指针变量p指向数组a,指针变量p可以++、--,表示指向数组的上一元素或下一元素。但C编译程序不作下标越界检查。使用指针既方便有灵活,但初学者容易搞错。 步骤四 布置作业 课后作业:第十章课后练习10.31 10.5 课题: 教学目的: 教学重点: 教学难点: 第十章 指针 §3-§4 在掌握指针与数组的基础上,掌握字符串的指针与指向字符串的指针变量 指向字符串的指针变量 用指针处理字符串 步骤一 复习引导 上节课介绍了指向一维数组的指针及二维数组的地址,指向一维数组的指针也即指向元素的指针,那么指向二维数组的指针是怎样的呢?它有两种类型。 步骤二 讲授新课 2、指向二维数组的指针变量 ——(1)指向数组元素的指针变量 设指针变量p=a[0] (&a[0][0]、a、a+0、*(a+0))计算a[i][j]在n*m数组中的位置: 例:…… for(i=0;i<3;i++) {for(j=0;j<4;j++)printf(“%4d”, *(p+i*m+j)); printf(“n”);} …… 例:用指针变量输出数组元素的值。main(){ int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23}; int *p; for(p=a[0];p {if((p-a[0])%4 == 0)printf(“n”); printf(“%4d”, *p); } } 计算a[i][j]在n*m数组中的位置:a[0]+i*m+j ——(2)行指针(指向由m个元素组成的一维数组的指针变量) 定义:指针基类型 (*指针名)[m] 其中,m表示二维数组每行有m列; 如: int(*p)[3]; 于是,p 指向第0行元素的起始存储地址; p+1 指向第1行元素的起始存储地址;…… p+I 指向第i 行元素的起始存储地址; 而每一行的元素的表示形式为: 第0行元素的表示为(*p)[j]; 第1行元素的表示为(*(p+1))[j];…… 第i 行元素的表示为(*(p+ I))[j]; 例 : #include int a[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};for(p=a;p for(j=0;j<4;j++) if(j==3)printf(“%4dn”,(*p)[j]); else printf(“%4d” ,(*p)[j]); } 改写为: #include int a[4][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}}; p=a; for(i=0;i<4;i++) for(j=0;j<4;j++) printf(j==3?“%4dn”: “%4d” , *(*(p+i)+j)); } 3、多维数组的指针作函数参数 一维数组的地址可以作为函数参数传递,多维数组的地址也可作函数参数传递。在用指针变量作形参以接受实参数组名传递来的地址时,有两种方法: 1、用指向变量的指针变量; 2、用指向一维数组的指针变量。 例;有一个班,3个学生,各学4门课,计算总平均分数,以及第n个学生的成绩。main(){ void average(float *p ,int n); void search(float(*p)[4], int n); float score[3][4]={{65,67,70,60},{80,87,90,81}, {90,99,100,98}}; average(*score, 12); /*求12个分数的平均分*/ search(score , 2); /*求第2个学生成绩*/ } void average(float *p , int n){float *p_end; float sum= 0,aver; p_end = p+n-1; for(;p<=p_end;p++)sum =sum+(*p);aver = sum/n;printf(“average=%5.2fn”,aver);} void search(float(*p)[4], int n){ int i;printf(“the score of No %d are:n”,n);for(i=0;i<4;i++)printf(“%5.2f”, *(*(p+n)+i));} 例10.15 在上题基础上,查找一门以上课程不及格的学生,打印出他们的全部课程的成绩。main(){ void search(float(*p)[4], int n);float score[3][4]={{65,57,70,60},{58,87,90,81),{90,99,100,98}};search(score, 3);} void search(float(*p)[4], int n){int i, j, flag;for(j=0;j §10.4字符串的指针和指向字符串的指针变量 一、字符串的表示形式 1、用字符数组存放一个字符串。如:main() { char string[ ]=“I love China!”; printf(“%sn”, string);} 2、用字符指针指向一个字符串。 如:main() { char *string=“I love China!”; printf(“%sn”, string);} 例10.18 将字符串a复制为字符串b。main(){ char a[]=“I am a boy.” , b[20]; int i; for(i=0;*(a+i)!=„‟;i++)*(b+i)= *(a+i); *(b+i)= „‟; printf(“string a is : %sn”, a); printf(“string b is :”); for(i=0;b[i]!=„‟;i++) printf(“%c”, b[i]); printf(“n”);} 例10.19 用指针变量来处理上例。main(){ char a[ ]=“I am a boy.” , b[20], *p1, *p2; int i; p1= a;p2= b; for(;*p1!=„‟;p1++,p2++)*p2 = *p1; *p2 = „‟; printf(“string a is : %sn”, a); printf(“string b is :”); for(i=0;b[i]!=„‟;i++) printf(“%c”, b[i]); printf(“n”);} 二、字符串指针作函数参数 例10.20:用函数调用实现字符串的复制。——(1)用字符数组作参数。 void copy_string(char from[],char to[]){ int i=0; while(from[i]!=„‟) { to[i] = from[i];i++;} to[i]=„‟; } main(){ char a[]=“I am a teach.”; char b[]=“you are a student.”; printf(“string a= %snstring b=%sn”,a,b); copy_string(a,b); printf(“nstring a=%snstring b=%sn”,a,b);} ——(2)形参用字符指针变量 void copy_string(char *from,char *to){ for(;* from!=„‟;from++, to++) *to = *from; *to=„‟; } ——(3)对copy_string函数还可以简化。① void copy_string(char *from, char *to) { while((*to =* from)!=„‟) { to ++;from++;} } ② void copy_string(char *from, char *to) { while((*to ++ =* from++)!=„‟);} ③void copy_string(char *from, char *to) { while(* from!=„‟) *to++ = *from ++; *to = „‟; } ④void copy_string(char *from, char *to) { while(*to++ = *from ++);} ⑤void copy_string(char *from, char *to) { for(;*to++ = *from ++;);} ⑥void copy_string(char from[], char to[]) { char *p1,*p2; p1=from;p2=to; while((*p2++ = *p1++)!=„‟); } 三、字符指针变量和字符数组的讨论 1、字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址,决不是将字符串放到字符指针变量中。 2、赋值方式。对字符数组只能对各个元素赋值,不能用以下办法对字符数组赋值; char str[14]; str=“I love China.”;对字符指针变量,可以采用下面方法赋值: char *a; a= “I love China.”; /*赋给a的是串的首地址*/ 3、对字符指针变量赋初值: char *a=“I love China.”; 等价于 char *a; a=“I love China.”; 而对数组的初始化: char str[14]={“I love China.”};不等价于 char str[14]; str[]=“I love China.”; 即数组可以在变量定义时整体赋初值,但不能在赋值语句中整体赋值。 4、如果定义了一个字符数组,在编译时为它分配内存单元,它有确定的地址。而定义一个字符指针变量时,给指针变量分配内存单元,在其中可以放一个地址值,也就是说,该指针变量可以指向一个字符型数据,但如果未对它赋一个地址值,则它并未具体指向一个确定的字符数据。这很危险。 如: char str[10]; scanf(“%s”,str);是可以的 char *a; scanf(“%s”,a); 能运行,但危险,不提倡,在a单元中是一个不可预料的值。 应当 char *a,str[10];a=str;scanf(“%s”,a); 5、指针变量的值是可以改变的,数组名虽然代表地址,但它的值是不能改变的。可以下标形式引用所指的字符串中的字符。 如:main() {char *a=“I love China.”; a=a+7; printf(“%s”,a);} 又如:char str[]={“I love China.”};str=str+7;printf(“%s”,str);是错的 6、用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。也可以用字符数组实现,但由于不能采用赋值语句对数组整体赋值。 如:char *format;format=“a=%d,b=%fn”;printf(format,a,b); 等价于:printf(“a=%d,b=%fn”,a,b); 也可以:char format[ ]=“a=%d,b=%fn”;printf(format,a,b); 步骤三 课堂小结 本课介绍了指针与二维数组、指针与字符串,指向二维数组的指针有指向元素的指针和行指针,使用时应注意它们的区别。我们既要掌握用数组处理字符串,也要掌握用指针变量处理字符串。要区分这两种方法的不同之处。 步骤四 布置作业 课后作业:第十章课后练习10.61 10.7 课题: 第十章 指针 §5-§7 教学目的: 了解指针与函数的概念 教学重点: 教学难点: 指针数组,二级指针 掌握指针数组,二级指针等知识 掌握指针数组,二级指针等知识 步骤一 复习引导 前面介绍了指针与维数组、指针与字符串,我们可以用指针变量指向整型变量、字符串、数组,也可以指向一个函数。 步骤二 讲授新课 §10.5函数的指针和指向函数的指针变量 函数的地址:函数存储区域的首地址就是该函数的入口点,其函数名表示了入口地址。 一、函数指针变量的定义: 存储类型 数据类型 (*函数指针名)(); 例:static int(*p)();例10.23 求a和b中的大者。 main() { int max(int, int); int a,b,c; scanf(“%d,%d”,&a,&b); c=max(a,b); printf(“a=%d,b=%d,max=%d”,a,b,c); } max(int x, int y){ int z; if(x>y)z=x; else z=y; return(z);} 法2:main() { int max(int, int); int(*p)(); int a,b,c; p=max; /*将地址送入p */ scanf(“%d,%d”,&a,&b); c=(*p)(a,b); /*与max(a,b)等价*/ printf(“a=%d,b=%d,max=%d”,a,b,c); } 注:int(*p)()定义p是一个指向函数的指针变量,此函数带回整型的返回值。 说明: 1、函数的调用可以通过函数名调用,也可以通过函数指针调用。 2、(*p)()表示定义一个指向函数的指针变量,它不是固定指向哪一个函数的,而只是表示定义了这样一个类型的变量,它是专门用来存放函数的入口地址的。 3、在给函数指针变量赋值时,只需给出函数名而不必给出参数,如:p=max。 4、用函数指针变量调用函数时,只需将(*p)代替函数名即可(p为指针变量名),在(*p)之后的括号中根据需要写上实参。如:c=(*p)(a,b); 5、对指向函数的指针变量,像p+n、p++、p--等运算是无意义的。 二、用指向函数的指针作函数参数 函数的参数可以是变量、指向变量的指针变量、数组名、指向数组的指针变量等。现介绍指向函数的指针也可以作为参数,以便实现函数地址的传递,也就是将函数名传给形参。 它的原理可以简述如下:有一个函数(假设函数为sub),它有两个形参(x1和x2),定义x1和x2为指向函数的指针变量。在调用函数sub时,实参用两个函数名f1和f2给形参传递函数地址。这样在函数sub中就可以调用f1和f2函数了。 有人会问,既然在sub函数中要调用f1和f2函数,为什么不直接调用f1和f2而用函数指针变量呢?的确,如果只是用到f1和f2,完全可以直接在sub函数中直接f1和f2,而不必设指针变量x1、x2。但是,如果在每次调用sub函数时,要调用的函数是不固定的,这次调用f1和f2,而下次要调用f3和f4,第三次要调用的名作为实参即可,sub函数不必作任何修改。这种方法是符合结构化程序设计方法原则的,是程序设计中常使用的。 例10.24 设一个函数process,在调用它的时候,每次实现不同的功能。 main(){ int max(int ,int); int min(int , int); int add(int , int); int a, b; printf(“enter a and b:”); scanf(“%d,%d”, &a, &b); printf(“max=”);process(a,b,max); printf(“min=”);process(a,b, min); printf(“sum=”);process(a,b, add);} max(int x, int y) { int z; if(x>y)z = x;else z = y; return(z); } min(int x, int y) { int z; if(x else z = y; return(z);} add(int x, int y){ int z; z = x+y; return(z);} process(int x, int y, int(*fun)(int ,int)){int result; result =(*fun)(x,y); printf(“%dn” , result);} 在函数process定义中,int(*fun)(int,int)表示fun是指向函数的指针,该函数是一个整型函数,有两个整型形参。 在三次调用中,分别将函数名max、min、add作为实参将其入口地址送给process函数中的形参fun(fun是指向函数的指针变量)。例:process函数中的(*fun)(x,y)相当于max(x,y)。 注:在使用时,应将函数声明,这样编译系统将它按函数名处理(把函数入口地址作实参值),而不是作为变量名,不致出错。 Process函数无固定功能。如果max、min、add换成其它函数,此process函数不需改变,只要修改每函数的函数体。 §10.6 返回指针值的函数 一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址。其概念与以前类似,只是带回的值的类型是指针类型而已。格式: 类型名 *函数名(参数表);例: int *a(int x, int y); a是函数名,调用它以后能得到一个指向整型数据的指针(地址)。 例10.25 有若干个学生的成绩(每个学生有4门课程),要求在用户输入学生序号以后,能输出该学生的全部成绩。用指针函数来实现。float *search(float(*pointer)[4], int n) {float *pt; pt = *(pointer +n); return(pt); } main(){ float score[][4]={{60,70,80,90},{56,89,67,88),{34,78,90,66}}; float *p; int i, m; printf(“enter the number of student:”); scanf(“%d”,&m); printf(“The score of No.%d are:n”, m); p=search(score, m); for(i=0;i<4;i++) printf(“%5.2t”, *(p + i)); } 例10.26 对上例中的学生,找出其中有不及格课程的学生及其学生号。float *search(float(*pointer)[4]){ int i; float *pt; pt = *(pointer+1); for(i=0;i<4;i++) if(*(*pointer+i)<60)pt = *pointer; return(pt);} main(){ score[][4]={{60,70,80,90},{56,89,67,88),{34,78,90,66}}; float *search(float(*pointer)[4], int n); float *p; int i, m; for(i=0;i<3;i++){ p=search(score+i); if(p==*(score + i)) { printf(“ No.%d score:”, i); for(j=0;j<4;j++) printf(“%5.2t”, *(p + i)); printf(“n”);} } } 关于函数的返回值是指针的情况,程序设计时应注意: 1、因数组名是地址常量,用于接受这种返值的对象不能是数组名,这与把数组名作为实在参数传递给形式参数的情况不同(作为形式参数的数组名总被视为指针)。 2、不应将局部于被调用函数的指针作为返值返回给调用者,理由是局部于被调用函数的数据对象执行返回语句离开被调用函数后,原来分配的被调用函数的所有局部对象的存储空间立即被收回(释放),虽然调用者已经获得了正确的地址值,但此时它指向的存储区域的内容可能已经发生了变化,或许已经分配给其他函数了。如果调用函数中仍然使用这个指针去存取那个区域中的数据,得到的可能并非原先的数据。对于这种情况的正确做法是应该把所处理的对象定义成全局对象或static型对象。 §10.7 指针数组和指向指针的指针 一、指针数组的概念 一个数组中的元素均为指针类型,称为指针数组。 形式: 存储类型 类型名 *数组名[数组长度] 例如: static int *p[4] 定义指针数组时也可以进行初始化,如: static char ch[][20]={“Beijing”,“Nanjing”,“Shanghai”,“Guangzhou”}; char *p[ ]={ch[0],ch[1],ch[2],ch[3]};该例也可以等价定义为: char *p[ ]={“Beijing”,“Nanjing”,“Shanghai”,“Guangzhou”}; 例如: main(){ int i, min, j; char *temp, *p[ ]={“Beging”,“Nanjing”,“Shanghai”, “Guangzhou”}; for(i=0;i<3;i++) { min=i; for(j=i+1;j<4;j++) if(strcmp(p[j], p[min])<0)min=j; temp=p[i];p[i]=p[min];p[min]=temp; } for(i=0;i<4;i++) printf(“%sn”, p[i]);} 注意:不能把一个二维数组与一个指针数组混淆; 如:int a[10][10];与 int *b[10];的异同点 访问形式相同;如a[5][5],b[5][5]; 占用的存储空间数不同; 每一个b[i]必须置初值者能使用; 使用b优越 不需进行复杂的下标计算; b[i]指向的数组并非一定要10个元素,但a中,每一行上的元素个数必须相同;因指针指向的是一个地址,故对b而言,各个b[i]指向的存储区域之间不必连续;而对a而言,必须存储100个连续的存储int型数据对象的区域。 例10.27 将若干字符串按字母顺序(由小到大)输出。main(){ void sort(char *name[], int n); void print(char *name[], int n); char *name[]={“Follow me”, “Basic”, “Great Wall”, “Fortran”, “Computer”}; int n=5; sort(name, n); print(name, n); } void sort(char *name[], int n){ char *temp; int i, j, k; for(i=0;i { k=i; for(j=i+1;j if(strcmp(name[k], name[j])>0)k=j;if(k!=i) {temp=name[i]; name[i]=name[k]; name[k]=temp;} } } void print(char *name[], int n);{ int i; for(i=0;i } 二、指向指针的指针 在本章开头已提到“间接访问”变量的方式。利用指针变量访问另一个变量就是“间接访问”。 如果在一个指针变量中存放一个目标变量的地址,这就是“单级间址”。指向指针的指针用的是“二级间址”方法。从理论上讲,间址方法可以延伸到更多的级。但实际上在程序中很少有超过二级间址的。级数愈多,愈难理解,容易产生混乱,出错机会也多。 二级指针的定义: char **p; 含义:表示指针变量p是指向一个字符指针变量(即指向字符型数据的指针变量)的。main(){ int i, min, j; char *temp, *p[ ]={“Beging”,“Nanjing”,“Shanghai”, “Guangzhou”}; char **pp; pp=p; for(i=0;i<3;i++) { min=i; for(j=i+1;j<4;j++) if(strcmp(*(pp+j),*(pp+min))<0)min=j; temp=*(pp+i); *(pp+i)=*(pp+min); *(pp+min)=temp; } for(i=0;i<4;i++)printf(“%sn”,*pp++);} 例10.28 使用指向指针的指针。main(){ char *name[]={“Follow me”, “Basic”, “Great Wall”, “Fortran”, “Computer”}; char **p; int i; for(i=0;i<5;i++) { p=name+i; printf(“%sn”, *p); } } 例 main(){ static int a[5]={1,3,5,7,9}; int *num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]}; int **p, i; p= num; for(i=0;i<5;i++) { printf(“%dt”, **p); p++; } } 运行结果: 步骤三 课堂小结 本课介绍了指针数组、二级指针、指针与函数。要搞清它们的定义及应用; 注意区分: char a[5]; 与 char(*a)[5]; int *p(int x); 与 int(*p)(); 步骤四 布置作业 《C语言习题集》同步练习课题: 第十章 指针 §7-§8 教学目的: 了解指针数组作main函数的形参 教学重点: 教学难点: 指针的应用 掌握指针的应用 掌握指针的应用 步骤一 复习引导 上节课介绍了二级指针、指针数组,而指针数组的一个重要应用是作为main函数的形参。main()函数是我们C语言程序必不可少的,以往使用时main()是不带参数的。实际上是可带参数的,如:main(argc, argv)。 步骤二 讲授新课 三、指针数组作main函数的形参 带参数的main原型: main(int argc, char *argv[ ]) { …… } 说明: 第1个参数是指命令行中参数的个数,含文件名本身。 第2个参数是一个指向字符串的指针数组。 main函数是由系统调用的。当处于操作命令状态下,输入main所在的文件名(经过编译、连接后得到的可执行文件名),系统就调用main函数。参数应和命令一起给出。命令形式: 命令名 参数1 参数2 ……参数n 例如:有一个目标文件名file1,今想将两个字符串“China”, “Beijing”作为传送给main函数的参数。可写成: file1 China Beijing 例:编写一程序echo.c,实现将命令行上除程序名之外的所有给出的其他参数都回显到显示器上。 main(int argc, int *argv[ ]){ while(argc>1){ ++argv; printf(“%s”, *argv); --argc;} } 若将该程序编译、连接、装配成echo.exe,则在命令行上输入: echo hello, world! §10.8有关指针的数据类型和指针运算的小结 一、有关指针的数据类型的小结 见书中的表 二、指针运算小结 1、指针变量加(减)一个整数 例:p++、p--、p+i、p-=I等 2、指针变量赋值 将一个变量地址赋给一个指针变量。p=&a;p1=p2; 3、指针变量可以有空值,即该指针变量不指向任何变量。如 : p=NULL; 4、两个指向同一数组元素的指针变量可以相减 5、两个指向同一数组的指针变量可作关系运算 习题举例: 习题10.4 有n个整数,使其前面各数顺序向右移m个位置,最后m个数变成最前面m个数。写一函数实现以上功能,在主函数中输入n个整数,并输出调整后的n个数。 main(){ int number[20],n,m,I; printf(“How many number?”); scanf(“%d”,&n); printf(“Input %d number:n”,n); for(i=0;i scanf(“%d”,&number[i]); printf(“How many place you want to move?”); scanf(“%d”,&m); move(number, n, m); printf(“Now,they are:n”); for(i=0;i printf(“%d”, number[i]);} move(int array[20], int n, int m){ int *p,array_end; array_end = *(array+n-1); for(p= array+n-1;p>array;p--) *p= *(p-1); *array=array_end; m--; if(m>0)move(array, n, m);} 习题10.5 有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。程序: main(){ int i, k, m, n, num[50], *p; printf(“Input number of person:n=”); scanf(“%d”,&n); p=num; for(i=0;i *(p+i)= i+1; i=0;k=0;m=0; while(m { if(*(p+i)!=0)k++; if(k==3) { *(p+i)=0;k=0;m++;} i++; if(i= =n)i=0; } while(*p==0)p++; printf(“The last one is NO.%dn”,*p); } 习题10.6 写出一个函数,求一个字符串的长度。在main函数中输入字符串,并输出其长度。main(){ int len; char *str[20]; printf(“Input string:”); scanf(“%s”, str); len=length(str); printf(“The length of string is %d.”,len);} length(char *p){ int n; n=0; while(*p!=„‟) { n++; p++; } return(n);} 习题10.7 有一字符串,包含n个字符。写一个函数,将此字符串中从第m个字符开始的全部字符复制成为另一个字符串。main(){ int m; char *str1[20],*str2[20]; printf(“Input string:”); gets(str1); printf(“Which character that begin to copy?”); scanf(“%d”,&m); if(strlen(str1) printf(“Input error!”); else { copystr(str1,str2,m); printf(“result:%s”,str2); } } copystr(char *p1, char *p2, int m){ int n; n=0; while(n {n++; p1++; } while(*p1!=„‟) { *p2 = *p1; p1++;p2++; } *p2=„‟;} 习题10.9 写一个函数,将3×3的矩阵转置。main(){ int a[3][3],*p, i; printf(“Input matrix:n”); for(i=0;i<3;i++)scanf(“%d %d %d”, &a[i][0], &a[i][1] , &a[i][2]); p=&a[0][0]; move(p); printf(“Now,matrix:n”); for(i=0;i<3;i++) printf(“%d %d %d”,&a[i][0], &a[i][1], &a[i][2]); } move(int *pointer){ int i, j, t; for(i=0;i<3;i++) for(j=i;j<3;j++) { t= *(pointer+ 3*i + j); *(pointer+ 3*i +j)= *(pointer+ 3*j + i); *(pointer+3*j + i)=t; } }习题10.16 输入一个字符串,内有数字和非数字字符,如: a123x456 17960?302tab5876 将其中连续的数字作为一个整数,依次存放到一数组a中。例如123放在a[0]中,456放在a[1]中……统计共有多少个整数,并输出这些数。#include int i, j, k, m, e10, digit, ndigit, a[10], *pa; printf(“Input a string:n”); gets(str); printf(“n”); pstr=&str[0]; pa=&a[0]; ndigit = 0;i = 0;j=0; while(*(pstr+i)!=„‟) { if((*(pstr+i)>=„0‟)&&(*(pstr+i)<=„9‟))j++; else { if(j>0) { digit = *(pstr+i-1)-48; k=1; while(k { e10=1; for(m=1;m<=k;m++)e10 =e10*10; digit =digit+(*(pstr+i-k)-48)*e10; k++; } *pa=digit;ndigit++; pa++; j=0; } } i++; } printf(“There are %d numbers in this line.They are:n”,ndigit); j=0; pa=&a[0]; for(j=0;j printf(“%d”, *(pa+j)); printf(“n”);} 步骤三 课堂小结 本课主要讲了一些习题,希望通过这些例子加深对指针的了解,看到指针在程序设计中的重要应用。同学们课后需要多看、多想、多练,逐步去体会指针这一重要的概念。步骤四 布置作业 【c语言函数指针数组】推荐阅读: C 语言inline函数小结08-17 c语言指针学习笔记11-17 c语言实验数组的应用08-07 C语言与语言混合编程DSP设计08-23 c语言个人总结08-19 c语言要点总汇09-14 c语言模拟迷宫程序07-07 学生成绩系统c语言07-25 c语言课程设计题目09-25 C语言的读书心得10-269.c语言函数指针数组 篇九
10.史上最全C语言指针总结 篇十
11.C语言程序设计教案 第十章指针 篇十一