项目六 用指针优化学生成绩排名 项目要求 项目分析 项目六 用指针优化学生成绩排名 项目要求 一个班有40位学生参加了期终考试(考了三门课),请用指针优化学生成绩排名。即用指针实现数组的输入输出以及数组的排序(在函数中进行)。 项目分析 要用指针优化学生成绩排名,第一必须要了解指针的概念、引用; 第二必须会用指针实现数组的输入输出; 第三在函数中用指针实现数组的排序,然后调用此函数。 为了在介绍的时候条理清晰,所以分解成5个任务。
任务1 了解指针 一、问题情景 知识点: 1、指针的概念; 2、指针的引用; 任务1 了解指针 一、问题情景 一个班进行了一次考试,现要将几个学生的成绩输入,用指针的方式输出。 知识点: 1、指针的概念; 2、指针的引用;
三、相关知识 (一)地址的概念与取地址运算 地址——内存单元的编号(在计算机中,把内存区划 分为一个一个的存储单元,每个单元为一个字节,它 们都有一个编号,这个编号就是内存地址) 取地址运算——& 如:int a = 3 ; &a 就是变量在内存中的地址。 可以用printf(“%x \n” , &a); 看出其地址。 #include <stdio.h> main() { int a=3; printf("%d\n",a); printf("%x\n",&a); } 注意: 这个地址并不是始终不变的,这是由机器和操作系统来安排的,我们无法预先知道。 但&不能施加在常量或表达式前。
三、相关知识 (二)指针的概念 ——一个变量在内存中存储时的地址, 它并不占内存中的存储空间。 简单地说,指针就是地址。二者是同一个概念的两种说法。只不过指针更形象一些,就像一个针一样,可以指向某个地方。
三、相关知识 (三)指针变量 概念 既然存储在内存中的各种变量都有一个地址,我们能否这样设想:定义某种变量,让这个变量的值始终等于某个变量的地址,如同某个房间号、门牌号一样?回答是肯定的。我们把这种存放某种变量地址的变量称为指针变量。 …. 35 10 a b 240ff52 240ff56 p q 因此,在C语言中,将地址形象化地称为指针
三、相关知识 指针变量的定义和赋值 [存储类型 ] 数据类型 * 指针变量名 1、定义 [存储类型 ] 数据类型 * 指针变量名 如: int *p, a=3; int *q, b=5; 说明 a. * 是定义指针变量的标志,不可丢掉 b. 数据类型是指针变量所指向的变量的类型 c. 指针变量定义后,其值是不确定的
三、相关知识 2、赋值:可以进行初始化,也可以使用赋值语句 (1)初始化: int a, *s=&a; (2)赋值语句 int a, *s; (3)注意:只能用同类型变量的地址进行赋值! 如定义:int *s; float f; 则 s=&f;是非法的。
三、相关知识 指针变量的引用 1、 &——取地址运算 如: int *p , i=3, j=5; p=&i; /*让p其指向变量i*/ 2、 *——指针运算,则代表取指针所指向的单元的内容。 区分:*运算符在不同场合的作用, 编译器能够根据上下文环境判别*的作用。int a,b,c; int *p; (*表示定义指针) p = &a; *p = 100; (*表示指针运算符) c = a * b; (*表示乘法运算符)
【例6-1】指针与地址的应用 #include <stdio.h> void main() { int a,b,*pointer_1,*pointer_2; a=100,b=200; pointer_1=&a; pointer_2=&b; printf("%d,%d\n",a,*pointer_1); printf("%d,%d\n",b,*pointer_2); }
printf(“%d , %d \n” , *p1, *p2); } 指针赋值, 若输入“3 4”,则输出为什么? 定义指针变量 main( ) { int *p1, *p2, a1, a2; scanf(“%d %d” , &a1, &a2 ); p1 =&a1; p2=&a2; printf(“%d , %d \n” , *p1, *p2); p2 = p1; printf(“%d , %d \n” , *p1, *p2); } 指针赋值, 把a1的地址给p1 直接赋值, 把p1指针的地址给p2, 即p2也指向a1 指针运算, p1指针所指向的变量a1的内容
任务1的具体实现 #include <stdio.h> void main() { int *p1,*p2,a,b; printf("输入:"); scanf("%d,%d",&a,&b); p1=&a;p2=&b; printf("输出:"); printf("a=%d,b=%d\n",a,b); printf("*p1=%d,*p2=%d\n",*p1,*p2); }
【例6-2】输入两个学生的成绩,按从小到大的顺序输出。 #include <stdio.h> void main() { int *p1,*p2,*p,a,b; printf("输入:"); scanf("%d,%d",&a,&b); p1=&a; p2=&b; if(a>b) {p=p1;p1=p2;p2=p;} printf("输出:"); printf("a=%d,b=%d\n",a,b); printf("min=%d,max=%d\n",*p1,*p2); }
? 形参不能传递给实参! 此方法不能实现两个数的调换! 如何用函数调用的方式实现两个数的调换? swap(int x,int y) {int temp; temp= x ; x= y ; y=temp ; } main( ) { int a, b; scanf(“%d,%d”,&a,&b); if(a<b) swap(a, b); printf(“%d, %d \n ” , a, b); } 形参不能传递给实参! 此方法不能实现两个数的调换! ?
指针变量作为函数参数 注意: 指针变量作为函数的参数,从实参向形参的数据传递仍然遵循“单向值传递”的原则,只不过此时传递的是地址. 函数可以通过return返回一个值,如果要函数返回多个值怎么办? 指针传递的方式来改变 【例6-3】用指针变量作为函数参数,实现数据的交换。 #include <stdio.h> void swap(int *p1,int *p2) { int temp; temp=*p1; *p1=*p2; *p2=temp; } void main() { int a,b,*pointer_1,*pointer_2; printf("输入a,b的值:"); scanf("%d,%d",&a,&b); pointer_1=&a,pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("调用函数后输出a,b的值为:"); printf("%d,%d\n",a,b); }
【例6-12】如果上例中的交换函数交换的是指针, 则结果如何? 【例6-12】如果上例中的交换函数交换的是指针, 则结果如何? void main() { int a,b,*pointer_1,*pointer_2; printf("输入a,b的值:"); scanf("%d,%d",&a,&b); pointer_1=&a,pointer_2=&b; swap(pointer_1,pointer_2); printf("调用函数后输出a,b的值为:"); printf("%d,%d\n",a,b); printf(“调用函数后输出 *pointer_1,*pointer_2的值为:"); printf("%d,%d\n",*pointer_1,*pointer_2); } #include <stdio.h> void swap(int *p1,int *p2) { int *temp; temp=p1; p1=p2; p2=temp; }
举一反三 【例6-11】输入a、b、c 3个整数,按从大到小顺序输出。 void main() { int a,b,c,*p1,*p2,*p3; printf("请输入3个数,以逗号隔开:"); scanf("%d,%d,%d",&a,&b,&c); p1=&a; p2=&b;p3=&c; if(a<b) swap(p1,p2); if(a<c) swap(p1,p3); if(b<c) swap(p2,p3); printf("从大到小的顺序为:"); printf("%d,%d,%d\n",a,b,c); } #include <stdio.h> void swap(int *a,int *b) { int t; t=*a; *a=*b; *b=t; }
任务2 用指针优化全班同学一门课成绩的输入输出 一、问题情景 一个班有40个同学进行了一次考试,现要用指针实现全班同学成绩的输入输出。 二、具体实现(以十个学生为例) 方法一:下标法(常用,很直观) #include <stdio.h> main() {int score[10],i; printf("请输入10个学生的成绩\n"); for(i=0;i<10;i++) scanf("%d",&score [i]); printf("输出的10个学生的成绩为\n"); printf("%3d", score [i]); printf("\n"); }
三、相关知识 (一)指向一维数组的指针 复习:一维数组在内存中的存放方法? int a[5]; a[0] a[1] 数组元素的地址:&a[i] 数组首地址:&a[0]或a
三、相关知识 指向数组 1、指针与一维数组的对应关系 int a[10],*p=a; memory 使p指向a数组的第一个元素a[0] 各元素的指针按存储单元递增 a[0] a[2] a[4] a[3] a[6] a[7] a[1] a[5] a[8] a[9] memory p p+1 p+2 p+9 2、用指针访问数组的一般形式 对下标为i的元素访问: a[i],*(a+i),*(p+i) 对a[i]的地址表示: &a[i],a+i,p+i 访问数组的两种方式:下标方式,指针方式
三、相关知识 (1)下标法(常用,很直观) #include <stdio.h> main() {int score[10],i; printf("请输入10个学生的成绩\n"); for(i=0;i<10;i++) scanf("%d",&score [i]); printf("输出的10个学生的成绩为\n"); printf("%3d", score [i]); printf("\n"); }
三、相关知识 (2)用数组名计算数组元素的地址。 (效率与下标法相同,不常用) #include <stdio.h> main() {int score[10],i; printf("请输入10个学生的成绩\n"); for(i=0;i<10;i++) scanf("%d",& score [i]); printf("输出的10个学生的成绩为\n"); printf("%3d", *(score+i)); printf("\n"); }
三、相关知识 (3)用指针访问各元素。(常用,效率高) #include <stdio.h> main() {int score[10],*p,i; printf("请输入10个学生的成绩\n"); for(i=0;i<10;i++) scanf("%d",& score [i]); printf("输出的10个学生的成绩为\n"); for(p=score;p<score+10;p++) printf("%3d", *p); printf("\n"); }
#include <stdio.h> void main() { int a[10],*p,i; p=a; 【例6-5】下面的程序在输入1 2 3 4 5 6 7 8 9 0后的输出结果还是1 2 3 4 5 6 7 8 9 0吗? #include <stdio.h> void main() { int a[10],*p,i; p=a; for(i=0;i<10;i++) scanf("%d",p++); printf("\n"); for(i=0;i<10;i++,p++) printf("%d ",*p); } #include <stdio.h> void main() { int a[10],*p,i; p=a; for(i=0;i<10;i++) scanf("%d",p++); /*特别要注意输入时指针的变化*/ printf("\n"); /*使p指针重新指向了数组的首地址*/ for(i=0;i<10;i++,p++) printf("%d ",*p); } 输入:1 2 3 4 5 6 7 8 9 0 输出: 怎样解决? 小结: (1) 指针变量可以实现自身值的改变。如:pa++; 而数组名所代表的地址则不能改变,a++是错误的用法。 (2)应注意指针变量的当前值。如上例。 (3)指针变量可以指向数组中各个内存单元。
注意 指针使用的几个细节 设指针p指向数组a(p=a),则: ①*p++,相当于*(p++) ② *(p++):先取*p,再使p加1
实训报告11
指向二维数组的指针 1、二维数组结构的分析 设有数组定义为:int a[3][4]; 则有: a表示数组在内存中的首地址。 a+i=a[i]=&a[i][0] 代表第i行的首地址
指向二维数组的指针 a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] 二维数组的逻辑结构图如下: a+0 a[0] a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a+1 a[1] a[2][0] a[2][1] a[2][2] a[2][3] a+2 a[2]
2、指向二维数组中一行的指针变量 我们可以定义一种指向行向量的指针,让它指向二维数组的第一行,该指针加1,就指向二维数组的下一行,这样的指针就叫做行指针。 (1)格式:类型名 (*指针变量名)[每一行的元素个数]; (2)例如:int (*p)[4]; (3)含义:p是指针变量,它指向一个数组,数组 每一行含有4个元素,每个元素的类型是int。
若定义:int a[3][4], (*pa)[4]=a; 则关系图为: (*pa)[0] (*pa)[1] (*pa)[2] (*pa)[3] a pa pa a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3] pa++ 如果执行pa++, 则变为如图所示 那么(*pa)[0]、(*pa)[1]、(*pa)[2]、(*pa)[3] 也变了
设p为指向二维数组的指针变量, 若p=b[0],可定义为int(*p)[4],p=b, 则p+i指向一维数组b[i],而*(*(p+i)+j)则是i行j列元素的值。 *(*(b+i)+j)式子是根据二维数组名计算i行j列元素的值; 还有一种直接采用首元素地址计算i行j列元素的方法。 其格式如下: *(首元素地址+行号*列数+列号)
【例6-6】 用几种方法输出二维数组各元素的值。 #include <stdio.h> void main() { int s[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int i,j,(*p)[4]; int row,col; p=s; printf("用二维数组的指针变量计算i行j列元素的方法\n"); for(i=0;i<3;i++) { for(j=0;j<4;j++) printf("%8d",*(*(p+i)+j)); printf("\n"); } printf("用二维数组的数组名计算i行j列元素的方法\n"); for(i=0;i<3;i++) { for(j=0;j<4;j++) printf("%8d",*(*(s+i)+j)); printf("\n"); } printf("用直接采用首元素地址计算i行j列元素的方法\n"); row=3;col=4; for(i=0;i<row;i++) { for(j=0;j<col;j++) printf("%8d",*(&s[0][0]+i*col+j)); printf("\n"); }}
有3个学生,各学4门课, 计算某一位学生的平均成绩 例 有3个学生,各学4门课, 计算某一位学生的平均成绩 #include <stdio.h> void average(float (*p)[4]) { int j; float sum=0; for(j=0;j<4;j++) sum+= (*p)[j]; printf ("这位学生的平均分为%5.2f\n ",sum/4); } main() { float score[3][4]={{66,67,70,60},{80,87,90,81},{90,99,100,98}}; average(score[2]); }
任务4 用指针优化学生姓名的排序 一、问题情景 分析: 要将3个候选人以姓氏的英文顺序排队, 要求用C中的字符指针解决此问题, 所以,在本任务中将要解决什么是字符指针,字符指针如何引用。
三、相关知识 一、字符串的表现形式 C语言中,有两种方式可以实现字符串:字符数组、字符指针。 (一)字符串的表示形式 1. 用字符数组实现 #include <stdio.h> main() { char string[ ]="I love China! "; printf("%s\n",string); } 2. 用字符指针实现 #include <stdio.h> main() { char *string="I love China! "; printf("%s\n",string); }
【例6-9】将字符串a复制到字符串b。 #include <stdio.h> void main() { 方法一 #include <stdio.h> void main() { char a[]="I am a boy.",b[20],*p1,*p2; int i; p1=a; p2=b; for(;*p1!='\0';p1++,p2++) *p2=*p1; *p2='\0'; printf("string a is:%s\n",a); printf("string b is:%s\n",b); printf("\n"); } 方法二 #include <stdio.h> void main() { char *a="I am a boy.",*b; b=a; printf("string a is:%s\n",a); printf("string b is:%s\n",b); printf("\n"); } 注意:若a,b都是字符指针,则可以用b=a,即将a的地址赋给b, 但是若a,b是字符数组,则不能用b=a,应用strcpy(b,a)
用指针实现: 输入一个字符串,把其中大写字母变成小写字母 。 #include <stdio.h> main() { char str[80],*pt; gets(str); for(pt=str;*pt!='\0';pt++) if(*pt>='A'&&*pt<='Z') *pt+=32; printf("string is:\n%s\n",str); }
用指针实现:输入一个字符串,求出字符串长度的函数。 并在主函数中实现调用。 #include <stdio.h> int str_len(char *str) { char *pt; int count=0; for(pt=str;*pt!='\0';pt++) count++; return count; } main() char str[80]; printf("请输入一个字符串\n"); gets(str); printf("该字符串的长度为%d\n",str_len(str));
任务5的具体实现 #include <stdio.h> #include "string.h" main( ) { char *name1="张小明",*name2="李大刚",*name3="周建华",*tt; if( strcmp(name1,name2)<0) {tt=name1;name1=name2;name2=tt;} if( strcmp(name1,name3)<0) {tt=name1;name1=name3;name3=tt;} if( strcmp(name2,name3)<0) {tt=name2;name2=name3;name3=tt;} printf("输出的姓名为:\n"); printf("%s\n",name1); printf("%s\n",name2); printf("%s\n",name3); }
字符数组与字符串指针变量的区别 字符数组 字符串指针变量 存放的是首地址 每个元素放一个字符 可以整体赋值 不能整体赋值 char *p; p=“abcde”; char s[6]; s=“abcde”; /* 不对*/ char s[6]; 使用s不能加/减 p可以加/减
指针数组 指针数组中每一个元素都是一个指针变量, 并且它们具有相同的数据类型。 指针数组的引用 char *p[4]; 格式: 类型标识 *数组名[数组长度] 功能: 指向一维数组的指针变量。 说明: 适合于指向若干个字符串, 使字符串处理更加方便灵活。 char *p[4];
字符指针数组的初始化。 #include <stdio.h> main() { char *week[]={"Sunday","Monday","Tuesday", "Wednesday","Thursday","Friday","Saturday"}; int i; while(1) printf("Enter week No:"); scanf("%d",&i); if(i<0||i>6) break; printf("Week No.%d--%s\n",i,week[i]); }
将4个字符串:dog,cat,pig和all animal 用指针数组输出。 #include <stdio.h> main() { char *s[4]; int i; s[0]="dog"; s[1]="cat"; s[2]="pig"; s[3]="all animal"; for(i=0;i<4;i++) printf("%s\n",*(s+i)); }