为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

c语言9

2011-09-24 50页 ppt 335KB 38阅读

用户头像

is_811064

暂无简介

举报
c语言9null10、指针10、指针10.1 指针概念 10.2 指针变量的定义和使用 10.3 指针与一维数组 10.4 指针与函数 10.5 指针数组、多级指针与指向一维数组 的指针 10.6 指针与字符串 10.1 指针概念10.1 指针概念 所谓指针,某种程度上就相当于地址,但要比地 址的含义更加丰富 • 变量的指针 变量的指针指的就是该变量的首地址 • 指针变量 指针变量是以指针(地址)为值的一种变量 • 指针指向变量 如有普通...
c语言9
null10、指针10、指针10.1 指针概念 10.2 指针变量的定义和使用 10.3 指针与一维数组 10.4 指针与函数 10.5 指针数组、多级指针与指向一维数组 的指针 10.6 指针与字符串 10.1 指针概念10.1 指针概念 所谓指针,某种程度上就相当于地址,但要比地 址的含义更加丰富 • 变量的指针 变量的指针指的就是该变量的首地址 • 指针变量 指针变量是以指针(地址)为值的一种变量 • 指针指向变量 如有普通变量x及指针变量p,且p=&x; ,则称: 指针p指向变量x null • 指针变量的类型 指针变量按其所指向变量类型的不同,也分成相 应的多种不同类型,指针变量只允许指向相应类 型的变量。例如: 有定义: int a, *p; float b, *q; 则允许:p=&a; q=&b; 不允许:p=&b; q=&a; p=q; q=p; • 空指针 指向地址为0的指针称为空指针,空指针用于 示指向空,记为NULL,NULL是一个指针常量, 对应0地址,在头文件stdio.h中定义。 10.2 指针变量的定义和使用10.2 指针变量的定义和使用 • 指针变量的定义 一般形式: 数据类型 *指针变量名; 如:int n, *p; float x, *p1, *p2; • 取址运算符& int n, *p; p = &n; • 取值运算符* int m, n, *p; p = &n; *p=5; m = *p;null • 指针使用举例 【例7.1】输入一个整数,通过指针方式赋值给另 一个变量后输出。 #include main() { int n, m, *p; scanf( "%d", &n ); p = &n; m = *p; printf( "%d\n", m ); }地址 内存 变量null • 指针变量的初始化 int i, *p = &i; char *q = "abcde"; 把字符串首地址赋给 q int *p = NULL; 0地址赋给 p (指向空) • 指针必须先赋值再使用 int n, *p; 定义指针变量p *p = 5; 可怕的错误 p=&n; *p=5; 先赋值再使用 10.3 指针与一维数组 10.3.1 一维数组的内存安排 10.3 指针与一维数组 10.3.1 一维数组的内存安排 int a[]={10,11,12,13,14}; int p=a;10.3.2 指向数组的指针运算 10.3.2 指向数组的指针运算 1. 指向数组的指针 • 指针可以指向数组中的某个元素 int c[5], *p, *q; p = &c[0]; /* 与 p = c; 等价 */ q = &c[1]; • 指向整型数组的指针与指向单个整型变量的指针 在指针类型上是一样的,都是指向整型量的指针 int n, c[5], *p, *q = c; p=&n; 2. 指针的加减整数运算2. 指针的加减整数运算 指针加减一个整数,该整数表示的是该指针所指 向数据类型的数据的个数,指针实际的增加量或 减少量是该整数乘以指针所指向数据类型的长度 (字节数)。 例如:p为指针变量,则p=p+1后指向了原指向的数据的后面一个数据的首地址。 如果p为字符型指针变量,则其增量为1字节; 如果p为整型指针变量,则其增量为2字节; 如果p为实型指针变量,则其增量为4字节。 null3. 指针和所指向值的自增自减运算 • 指针可以进行自增自减运算 设p为指针,则有: p++; ++p; p--; --p; • 对指针所指向的值也可以进行自增自减运算,如: (*p)++; 或 ++(*p); 相当于 *p = *p + 1; (*p)--; 或 --(*p); 相当于 *p = *p - 1; • 指针与++、--和* 运算符 ++、--和 * 运算都是单目运算符,具有同等的优 先级,C语言规定单目运算符是右结合的 null 设有:int n, a[5] = { 0, 1, 2, 3, 4 }, p = &a[2]; 则: 表达式 作用和意义 *++p 先++p使p指向a[3],再取*p即a[3]值 ++*p p指向的元素值增1,即++a[2] (*p)++ 先取*p即a[2]值,再使a[2]值增1,即a[2]++ *(p++) 先取*p即a[2]值, 再使p增1指向a[3] 注: *p++等价于*(p++) null【例7.2】以下程序的运行结果。 #include main() { int a[] = {10, 11, 12, 13, 14}, *p, n, i; p = &a[0]; n = *(p++); n += *(++p); n += (*(p+=2))++; n -= (*(--p))--; n -= *(--p-1); printf( "%d\n", n ); for(i=1;i<5;i++) printf("%d ",a[i]); }/* n=a[0]=10 p→a[1] *//* p→a[2] n=n+a[2]=22 *//* p→a[4] n=n+a[4]=36 a[4]=15 *//* p→a[3] n=n-a[3]=23 a[3]=12 *//* p→a[2] n=n-a[1]=12 *//* p→a[0] *//* 12 *//* 10 11 12 12 15 */null4. 指针的比较运算 • 任意两个指针可以进行相等比较,以确定它们是 否指向同一个变量 • 两个指针指向同一数组时,可进行比较运算(含 <、<=、 >、 >=、 !=、 = =)。以确定它们在数 组中的前后位置值。 例:指针关系运算举例。 #include "stdlib.h" #include "time.h"nullmain() { int a[20] ,*p, *q, n1, n2; randomize(); /* 初始化随机数发生器 */ n1=random(20); n2=random(20); p=a+n1; /* p指向a[n1] */ q=a+n2; /* q指向a[n2] */ if(p==q) printf( "\np and q points same element." ); else if(p a[j+1]) swap(&a[j],&a[j+1]); }main() { int x[10], i; for(i=0; i < 10; i++) scanf("%d",&x[i]); sort(x, 10); for(i = 0; i < 10; i++) printf("%d ",x[i]); printf( "\n" ); } 10.4.2 指针做为函数返回类型 10.4.2 指针做为函数返回类型 【例7.6】编写函数,在一个已从小到大排序的数 组中查找一个指定的数,如果找到,返回指向数组 中该数的指针,否则返回空指针。nullint *find(int *a, int n, int data) /* 数组a长度n待查数data */ { int *p=a, *q=a+n, *r; while ( p < q ) /* 待查找区不为空时 */ { r = p + (q-p)/2; /* 待查找区的中点位置 */ if ( *r==data ) return r; /* 如找到,返回该指针 */ else if ( *r < data ) p = r + 1; /* 比中点大,在后半区 */ else q = r; /* 比中点小,在前半区 */ } return NULL; /* 没找到,返回空指针 */ }nullmain() { int x[]={11,22,33,44,55,66,77,88,99,100}, d, *p; scanf( "%d", &d ); /* 输入要查找的数 */ p = find( x, 10, d ); /* 调用查找,结果赋值给p */ if ( p != NULL ) /* 判断是否找到数 */ printf( "Found at %d\n", p-x ); /* 找到,输出下标 */ else printf( "Not Found.\n" ); /* 没找到 */ }10.4.3 动态内存分配与释放函数 10.4.3 动态内存分配与释放函数 在处理实际问题时,常会遇到数组的大小要在程 序执行中才能确定的情况,合理的方法是在程序中 再决定数组的大小。 C语言提供了动态存储分配函数,可在程序运行 过程中,动态分配内存区供数据存储,可根据需要 指定大小,以及不需时予以释放。 下面介绍动态存储分配函数中的malloc()和free(), 在stdlib.h和alloc.h头文件中均含有它们的原型。null• 内存分配函数malloc() 原型:void * malloc(unsigned size); 功能:内存中分配一块连续的size个字节的未初始 化的存储区。返回一指向该区首址的void * 类型(称通用型或无类型)指针,须按实际需 要的数据类型进行强制转换,才能赋值给 相应的指针变量。如无法分配,则返回空指针。 • 内存释放函数free() 原型:void * free(void *buffer); 功能:释放buffer所指向的由malloc()等内存分配函数所分配的内存块。null【例7.7】输入n和n个整数,输出其中不重复出现 的整数,要求:只要内存容量许可,不对n的上限 做明显的限定。 #include main() { int *p, n, i, j, ct; scanf( "%d", &n ); p = (int *)malloc( n*sizeof(int) ); if ( p == NULL ) { printf( "There is not enough memory.\n" ); return -1; }null for ( i = 0; i < n; i++ ) scanf( "%d", &p[i] ); for ( i = 0; i < n; i++ ) { for (ct = 0, j = 0; j < n; j++ ) if ( p[i] == p[j] ) ct++; if ( ct == 1 ) printf( "%d\t", p[i] ); } free( p ); printf( "\n" ); }运行结果: 输出:33 44 100输入:8 11 33 5 11 5 5 44 10010.4.4 函数指针 10.4.4 函数指针 1. 函数指针的定义和使用 • 函数指针的概念 函数名具有类似数组名的地址特性: 数组名 — 该数组的首地址 函数名 — 该函数的入口地址 一个函数作为一段程序,在内存中占据一片连续 的存储单元,其中第一条执行指令所在的位置称 为函数的入口地址,取值为函数入口地址的指针 变量,称为指向函数的指针变量,简称函数指针。 通过该指针可以调用并执行函数。null • 函数指针的定义 函数值类型 ( *函数指针变量名 ) ( 参数说明表 ) ;  参数说明表中可只说明形参类型,而无形参本身。  如省略参数说明表,系统不检查参数传递正确性; 例如: 有函数说明:int max(int, int), abs( int ) ; 如要定义一个用来指向max函数的指针变量,则可 定义如下: int (*p) ( int, int ); 或 int (*p) ( ); null • 函数指针的使用  给函数指针变量赋值时,只需给出函数名而不必 (也不能)给出参数。如: int a, b, c, max(int, int), (*p)( ); p=max; /* p为函数指针变量,max为函数名*/  函数可通过函数名调用,也可通过函数指针调用, 如上例后,只需用(*p)代替函数名max即可。如: c=max(a, b); /* 通过函数名调用 */ c=(*p)(a, b); /* 通过函数指针调用 */  对函数指针变量,象p+i、p++、p--等运算无意义。null2. 函数指针做函数的参数 【例7.8】求三角函数sin(),cos()和tan()在10度, 20度,30度,40度和50度时的数值。 #include void printvalue( double (*fun)(double), int n ) { int i; for( i=1; i<=n; i++ ) printf( "%d\t%lf\n", i*10, (*fun)(3.14159*i/18) ); } main() { printvalue( sin, 5 ); printvalue( cos, 5 ); printvalue( tan, 5 ); }null3. 函数指针数组 函数指针可以组成指针数组,称为函数指针数组, 该数组的元素都是函数指针。 定义格式: 数据类型 (*函数指针数组名[常量表达式] ) ( ) 其中常量表达式的值表示函数指针数组的长度。 例:用循环语句for,while,do-while和if-goto编 制计算 的函数,并验证其正确性。要求 用函数指针数组nulllong sum1(int n) { int i; long sum=0; for(i=1; i<=n; i++) sum+=i; return sum; } long sum2(int n) { int i=0; long sum=0; while(++i<=n) sum+=i; return sum; }long sum3(int n) { int i=0; long sum=0; do sum+=i; while(i++<=n); return sum; } long sum4(int n) { int i=0; long sum=0; ss: sum+=i; if(i++<=n) goto ss; return sum; }nullmain() { long (*f[4])( ), k; int i, n; printf("\ninput a number:"); scanf("%d", &n); f[0]=sum1; f[1]=sum2; f[2]=sum3; f[3]=sum4; k=(*f[0])(n); for(i=1; i<4; i++) if(k!= (*f[i])(n)) { k=-1; break; } if(k==-1) printf("Error!"); else printf("Right. sum=%ld", k); }10.5 指针数组、多级指针与 指向一维数组的指针10.5 指针数组、多级指针与 指向一维数组的指针10.5.1 指针数组与多级指针10.5.1 指针数组与多级指针1. 指针的数组 • 一个数组的元素都为指针类型数据,称为指针 数组 • 定义格式: 数据类型 *指针数组名[常量表达式] 其中常量表达式的值表示数组的元素个数。 例:int *b[3]; 指针数组b的每个元素相当于可以指向一般整型变量,也可以指向整型数组元素的指针变量。null2. 多级指针 • 指针变量中可以保存另一个指针的地址,变成 “指向指针的指针”,称为多级指针。例如: 有指针数组name,其元素是指向一般数据的指针。 令指针变量p=name, p指向指针数组name。 则称指针变量p为二级指针。 如有指针变量pp再指向p,则称pp为三级指针。 • 多级指针的定义 二级指针的定义形式:数据类型 **指针名 三级指针的定义形式:数据类型 ***指针名 从上可知,n级指针定义时,指针名前应加n个*。null3. 数据的访问 如有:int x[3], y, z[2], *pa[3], **p2; pa[0]=x; pa[1]=&y; pa[2]=z; p2=pa; 则层次关系为: 则有(每行等价): *(*(p2+0)+j) p2[0][j] *(pa[0]+j) pa[0][j] x[j] *(*(p2+1)) p2[1][0] *pa[1] pa[1][0] y *(*(p2+2)+j) p2[2][j] *(pa[2]+j) pa[2][j] z[j]null例:将8个字符串按词典顺序排列。 ⑴ 用二维数组 #include "string.h" #define SIZE 8 main() { char name[SIZE][10]={"constant","pointer","function", "variable","address","structue","union","array"}; int i, j, k; char temp[10];null for(i=0; i0) k=j; if(k!=i) { strcpy(temp, name[k]); strcpy(name[k], name[i]); strcpy(name[i], temp); } } for(i=0; i0) k=j; if(k!=i) { temp=name[k]; name[k]=name[i]; name[i]=temp; } } for(i=0; i0) k=j; if(k!=i) /*原name[k], name[j] */ { temp= *(p+k); /*原name[k]*/ *(p+k) = *(p+i) ; /*原name[k]=name[i]*/ *(p+i) =temp; /*原name [i] */ } } for(i=0; i年级
所 有学生的成绩(只考虑一门课程,成绩使用int类型 表示),设年级共有4个班,一班50人,二班30人, 三班60人,四班40人。 1. 使用二维数组和指向一维数组的指针 /* 二维数组, 最多4个班, 每班最多60个学生 */ int stu[4][60]; /* 指向一维数组的指针, 每行60个整型数, 指向二维数组 */ int (*p1stu)[60]= stu; null 2. 在二维数组基础上的指针数组与二级指针 /* 二维数组, 最多4个班, 每班最多60个学生 */ int stu[4][60]; /* 指针数组指向二维数组的4个不同的行 */ int *pastu[4] = { stu[0], stu[1], stu[2], stu[3] }; /* 再在指针数组的基础上构造二级指针 */ int **p2stu = pastu; 3. 在多个一维数组基础上的指针数组与二级指针 /* 定义多个一维数组, 一班有50个学生, 二班有30个学生 , 三班有60个学生, 四班有40个学生 */ int stu1[50], stu2[30], stu3[60], stu4[40] ; null /* 在这4个一维数组的基础上构造指针数组 */ int *pastu[4] = { stu1, stu2, stu3, stu4 }; /* 再构造一个二级指针变量将所有有信息归结到一个单 一变量 */ int **p2stu = pastu; 4. 访问学生成绩 访问第i个班第j个学生(i和j从0开始取值)的成 绩,可以使用以下表达式: stu[i][j] /* 二维数组,下标+下标表示法 */ (*(p1stu+i))[j] /* 指向一维数组的指针, 指针+下标*/ *(pastu[i]+j) /* 指针数组,下标+指针表示法 */ *(*(p2stu+i)+j) /* 二级指针,指针+指针表示法 */null 为了简化格式,避免书写的错误,可以统一使用 二重下标法,如下所示: stu[i][j] /* 二维数组 */ p1stu[i][j] /* 指向一维数组的指针 */ pastu[i][j] /* 指针数组 */ p2stu[i][j] /* 二级指针 */10.6 指针与字符串10.6 指针与字符串10.6.1 字符串的内存安排10.6.1 字符串的内存安排1. 字符数组的初始化 2. 字符数组的输入 char a[10]="Hello!" char a[10]; gets(a);null3. 字符串常量和字符指针的初始化 char *p="Hello!"; 10.6.2 字符串处理程序举例 10.6.2 字符串处理程序举例 【例7.10】 编程,输入一行字符,将其中以一个或 多个空格分开的子串称为单词,将奇数位置的单词 转换为大写,偶数位置的单词保持不变,所有单词 重新组织后输出,输出时单词之间使用 "---" 连接, 行首以"[B]"开始,行尾以"[E]"结束。 例如,输入(符号表示空格):   how   are you?     *#@-aBc-123-$$$     则输出: [B]HOW---are---YOU?---*#@-aBc-123-$$$[E]null#include #include /* 字符串转换为大写函数 */ char *toucase( char *str ) { char *p; for(p=str; *p != '\0'; p++) if ( *p>= 'a' && *p<= 'z' ) *p=*p - 'a' + 'A'; return str; }null/* 从字符串中取出下一个单词 */ char *getnextword( char *str, char *word ) { char *p; for ( p = str; *p == ' '; p++ ) ; /* 过滤前导的空格 */ /* 循环至单词结束 */ for( ; *p!= ' ' && *p!='\0'; p++,word++ ) *word = *p; /* 复制单词 */ *word = '\0'; /* 单词结束 */ for ( ; *p==' '; p++ ) ; /* 过滤单词尾部空格 */ return p; /* 返回下一个非空格的位置 */ }nullmain() { char stra[81], strb[81], word[81], *p=stra; int n=0; gets( stra ); strcpy( strb, "[B]" ); /* 产生行首子串*/ while ( *p != '\0' ) { p = getnextword( p, word ); /* 取出下一个单词 */ if ( n != 0 ) strcat( strb, "---" ); /* 加连接子串 */ if ( n % 2 != 0 ) strcat( strb, word ); /* 直接拼接 */ else strcat( strb, toucase(word) ); /* 先大写再拼接 */ n++; /* 单词个数统计 */ } strcat( strb, "[E]" ); /* 拼接行尾子串 */ puts( strb ); }null例:下面程序的输出结果是 __________ 。 char b[ ]="ABCD"; main( ) { char *chp; for(chp=b; *chp; chp+=2) printf("%s", chp); printf("\n"); } ABCDCD10.6.3 多字符串的表示与处理 10.6.3 多字符串的表示与处理 多字符串实际上就是二维的字符数据,可以采用 二维的字符数组,也可以采用字符的指针数组形式 表示,或者二者结合。 【例7.11】编程,输入一行字符,将其中的单词按 逆顺序输出,例如, 输入(符号表示空格): howareyou?*#@-aBc-123-$$$ 则输出: *#@-aBc-123-$$$ you? are how null#define MAXN 40 int getallwords( char *str, char *pp[ ], int maxn ) { char *p; int n; p = str; n = 0; while ( *p != '\0' ) { p = getnextword( p, pp[n] ); /* 分离出第n个单词 */ if ( pp[n][0] != '\0' ) n++; if ( n >= maxn ) break; } return n; }nullmain() { char stra[81], words[MAXN][81], *pa[MAXN]; int i, n; gets( stra ); for ( i = 0; i < MAXN; i++ ) pa[i] = words[i]; n = getallwords( stra, pa, MAXN ); for ( i = n-1; i >= 0; i-- ) printf( "%s\t", words [i] ); printf( "\n" ); }10.6.4 程序举例 10.6.4 程序举例 例1:编写函数,把字符串 t 接在字符串s之后, 返回 新字符串首地址。 char *strjion (char *s, char *t) { char *p; p=s; /*保存s*/ while (*s) s++; /* 找字符串s末尾*/ while (*s++=*t++); /*连接*/ return p; /*返回指向连接后新字符串的指针*/ }null例2:从键盘输入两个字符串, 不使用库函数strcmp( ) 来比较它们的大小,若相等,则输出:“Both equal.”,否则输出其中较大者。 main() { char a[80], b[80], *p, *q ; gets(a); gets(b); for(p=a, q=b; *p &&*q ; p++, q++); if(*p>*q) puts(a); else if (*p<*q) puts(b); else if (*p=='\0'&&*q=='\0') puts("Both equal."); } null例3:编一个程序,输入一个字符串,内容依次是学 号(位数不定)和姓名的汉语拼音码。经处理后,输出一个字符串,内容依次为,姓名,两个*号和学号。nullmain() /* (1)不使用库函数 */ { char a[40], b[40], *p=a, *q=b, *r; gets(a); /* 定位姓名的首字符位置 */ while(*p>='0'&&*p<='9') p++; r=p; /* 记存姓名的首字符位置 */ while(*q++=*p++) ; /* 将姓名放入数组b */ *(q-1)='*'; /* 数组b中尾随姓名的'\0' 改为'*' */ *q++='*'; /* 数组b中再加一 '*' */ *r='\0'; /* 使a数组的学号尾随'\0' */ p=a; while(*q++=*p++); /* 将学号放入数组b的'*' 之后 */ p
/
本文档为【c语言9】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索