eg10.3输入a和b两个整数,按先大后小的顺序输出a和b
#include void swap(int *a, int *b); void swap(int *a, int *b){ int tmp; tmp = *a; *a = *b; *b = tmp; } void main(void){ int m, n; int *p1 = &m, *p2 = &n; printf("请输入两个整数:"); scanf("%d%d", &m, &n); printf("这两个整数为:%d,%d\n\n", m, n); swap(&m, &n); //等价于swap(p1,p2); printf("交换后的两个整数为:%d,%d\n", m, n); printf("交换后两个指针指向的整数为:%d,%d\n", *p1, *p2); }  |
#include void swap(int *a, int *b); void swap(int *a, int *b){ int *tmp; tmp = a; a = b; b = tmp; } void main(void){ int m, n; int *p1 = &m, *p2 = &n; printf("请输入两个整数:"); scanf("%d%d", &m, &n); printf("这两个整数为:%d,%d\n\n", m, n); swap(&m, &n); //等价于swap(p1,p2); printf("交换后的两个整数为:%d,%d\n", m, n); printf("交换后两个指针指向的整数为:%d,%d\n", *p1, *p2); }  |
#include void swap(int **a, int **b); void swap(int **a, int **b){ int *tmp; tmp = *a; *a = *b; *b = tmp; } void main(void){ int m, n; int *p1 = &m, *p2 = &n; printf("请输入两个整数:"); scanf("%d%d", &m, &n); printf("这两个整数为:%d,%d\n\n", m, n); swap(&p1, &p2); //swap(&(&m), &(&n)); //[Error]lvalue required as unary '&' operand //unary a.一元的 //swap(&&m, &&n); //[Error]label 'm' used but not defined [Error]label 'n' used but not defined printf("交换后的两个整数为:%d,%d\n", m, n); printf("交换后两个指针指向的整数为:%d,%d\n", *p1, *p2); }  |
交换的是两个变量的值 |
|
交换的是两个指针的值 |
|
eg10.5输出数组中的全部元素 用for循环输出
#include void main(void){ int a[10]; int i; printf("请输入10个整数:"); for(i = 0; i < 10; i++){ scanf("%d", &a[i]); } printf("数组中的元素为:"); for(i = 0; i < 10; i++){ printf("%d ", a[i]); } printf("\n"); } |
#include void main(void){ int a[10]; int i; printf("请输入10个整数:"); for(i = 0; i < 10; i++){ scanf("%d", &a[i]); } printf("数组中的元素为:"); for(i = 0; i < 10; i++){ printf("%d ", *(a+i)); } printf("\n"); } |
#include void main(void){ int a[10]; int i; int *p; printf("请输入10个整数:"); for(i = 0; i < 10; i++){ scanf("%d", &a[i]); } printf("数组中的元素为:"); for(p = a; p < (a+10); p++){ printf("%d ", *p); } printf("\n"); } |
#include void main(void){ int a[10]; int i; int *p; printf("请输入10个整数:"); for(i = 0; i < 10; i++){ scanf("%d", &a[i]); } printf("数组中的元素为:"); for(p = a,i=0; i<10; i++){ printf("%d ", *p); p++; } printf("\n"); } |
这个和下一个执行效率是相同的。C编译系统是将a[i]转换为*(a+i)处理的,即先计算地址元素。 |
|
比前两种方法快,用指针变量直接指向元素,不必每次都重新计算地址,像p++这样的自加操作是比较快的。 |
|
用while循环输出
|
eg10.7将数组a中n个整数按相反顺序存放
void inv(int *a, int n){ int i; int tmp; for(i = 0; i <= (n-1)/2; i++){ //for(i = 0; i < (n-1)/2; i++){ 不写=的话,最中间的那两个就没有交换 tmp = a[i]; a[i] = a[n-1-i]; a[n-1-i] = tmp; } printf("\n"); } |
void inv(int *a, int n){ int *p,*q; int tmp; for(p = a, q = a+n-1; p <= a+(n-1)/2; p++, q--){ tmp = *p; *p = *q; *q = tmp; } printf("\n"); } |
两种方法得到的结果相同,都可以实现题目要求功能 |
|
有一个实参数组,要想在函数中改变此数组中的元素的值,实参与形参的对应关系有以下4种情况:
void inv(int *a, int n){ ... } void main(void){ int a[5] = {3, 7, 9, 11, 0}; ... inv(a, 5); } |
void inv(int a[], int n){ ... } void main(void){ int a[5] = {3, 7, 9, 11, 0}; ... inv(a, 5); } |
void inv(int *a, int n){ ... } void main(void){ int a[5] = {3, 7, 9, 11, 0}; int *p = a; ... inv(p, 5); } |
void inv(int a[], int n){ ... } void main(void){ int a[5] = {3, 7, 9, 11, 0}; int *p = a; ... inv(p, 5); } |
用数组名作函数的参数 fun(int arr[], int n) <=> fun(int *arr, int n) 实参数组名代表该数组首元素的地址,而形参是用来接收从实参传递过来的数组首元素地址的。因此,形参应该是一个指针变量(只有指针变量才能存放地址)。实际上,C编译都是将形参数组名作为指针变量来处理的。 在该函数被调用时,系统会建立一个指针变量arr,用来存放从主调函数传递过来的实参数组首元素的地址。 |
|
eg10.11用指针变量输出二维数组元素的值
#include void main(void){ int a[3][4] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23}; int *p; for(p=a[0]; p < a[0]+12; p++){ if((p-a[0])%4 == 0){ printf("\n"); } printf("%4d", *p); } printf("\n"); }  |
#include void main(void){ int a[3][4] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23}; int *p; for(p=a[0]; p < a[0]+12; p++){ if((p+1-a[0])%4 == 0){ printf("\n"); } printf("%4d", *p); } printf("\n"); }  |
#include void main(void){ int a[3][4] = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23}; int *p; for(p=a[0]; p < a[0]+12; p++){ printf("%4d", *p); if((p+1-a[0])%4 == 0){ printf("\n"); } } printf("\n"); }  |
|
eg10.12输出二维数组任一行任一列元素的值
#include void main(void){ int a[3][4] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}}; int *p; int i,j; p = a[0]; printf("请输入行号和列号:"); scanf("%d%d", &i, &j); printf("a[%d][%d]=%d\n", i, j, *(p+i*4+j)); } |
#include void main(void){ int a[3][4] = {{1, 3, 5, 7}, {9, 11, 13, 15}, {17, 19, 21, 23}}; int (*p)[4]; int i,j; p = a; printf("请输入行号和列号:"); scanf("%d%d", &i, &j); printf("a[%d][%d]=%d\n", i, j, *(*(p+i)+j)); } |
p是指向整型数据的,p+1所指向的元素是p所指向的元素的下一元素。 |
p是指向一个包含m个元素的一维数组,p的增值以一维数组的长度为单位。 |
|
 |
|
eg10.13有3个学生各学4门课,计算总平均分数以及第n个学生的成绩 多维数组名做函数参数
1.用指向变量的指针变量 |
2.用指向一维数组的指针变量 |
float average(float *s, int n){ ...... } void main(void){ float score[3][4] = {......}; ...... av = average(*score, 12); //*score, 即score[0],即&score[0][0] ...... } |
void search(float (*s)[4], int n){ ...... } void main(void){ float score[3][4] = {......}; ...... search(score, ...); ...... } |
|
eg10.15定义一个字符数组,对它初始化,然后输出该字符串 eg10.16定义字符指针 C语言中,可以用两种方法访问一个字符串
(1)用字符数组存放一个字符串 |
(2)用字符指针指向一个字符串 |
#include void main(void){ char string[] = "I love China!"; printf("%s\n", string); } |
void main(void){ char *string = "I love China!"; printf("%s\n", string); } |
|
char *string = "I love China!"; <=> char *string; string = "I love China!"; |
|
把"I love China!"的第一个字符的地址赋给指针变量string,string只能指向一个字符变量 |
printf(“%s…”, …)与puts(…)只有一点点差别: printf(“%s\n”, s); <=> puts(s); puts()函数输出字符串后,自动换行。 |
%s是输出字符串时所用的格式符,在输出项中给出字符指针变量名string,则系统先输出它所指向的一个字符数据,然后自动使string加1,使之指向下一个字符,然后再输出一个字符……如此直到遇到字符串结束标志'\0'为止。 |
|
eg10.17将字符串a复制为字符串b eg10.18用指针变量处理eg10.17问题 对字符串中字符的存取,可以用下标方法,也可以用指针方法。
7.15字符串拷贝 |
下标法 |
和2等价 |
指针方法 |
#include #include void main(void){ char str1[80] = {0}; char str2[80] = {0}; int index = -1; int i; printf("请输入第二串字符:"); gets(str2); index = strlen(str2); printf("字符串结束标志下标为:%d\n",index); printf("拷贝前的第一串字符为:"); puts(str1); for(i = 0; i < index+1; i++){ str1[i] = str2[i]; } printf("拷贝后的第一串字符为:"); puts(str1); } |
#include #include void main(void){ char str1[80] = {0}; char str2[80] = {0}; int i; printf("请输入第二串字符:"); gets(str2); printf("拷贝前的第一串字符为:"); puts(str1); for(i = 0; str2[i] != '\0'; i++){ str1[i] = str2[i]; } str1[i] = str2[i]; printf("拷贝后的第一串字符为:"); puts(str1); } |
#include #include void main(void){ char str1[80] = {0}; char str2[80] = {0}; int i; printf("请输入第二串字符:"); gets(str2); printf("拷贝前的第一串字符为:"); puts(str1); for(i = 0; *(str2+i) != '\0'; i++){ *(str1+i) = *(str2+i); } *(str1+i) = '\0'; printf("拷贝后的第一串字符为:"); puts(str1); } |
#include #include void main(void){ char str1[80] = {0}; char str2[80] = {0}; char *p1; char *p2; printf("请输入第二串字符:"); gets(str2); printf("拷贝前的第一串字符为:"); puts(str1); for(p1 = str1, p2 = str2; *p2 != '\0'; p1++, p2++){ *p1 = *p2; } *p1 = '\0'; printf("拷贝后的第一串字符为:"); puts(str1); } |
|
eg10.19用函数调用实现字符串的复制
将一个字符串从一个函数传递到另一个函数,可以用地址传递的方法(即用字符数组名作参数),也可以用指向字符的指针变量作参数。在被调用的函数中可以改变字符串的内容,在主调函数中可以得到改变了的字符串。 |
归纳起来,作为函数参数,有以下几种情况:
实参:数组名 形参:数组名 |
实参:字符指针变量 形参:数组名 |
实参:数组名 形参:字符指针变量 |
实参:字符指针变啦 形参:字符指针变啦 |
#include #include void stringCopy(char from[], char to[]); void stringCopy(char from[], char to[]){ int i = 0; while(from[i] != '\0'){ to[i] = from[i]; i++; } to[i] = '\0'; } void main(void){ char str1[80] = {0}; char str2[80] = {0}; printf("请输入第二串字符:"); gets(str2); printf("拷贝前的第一串字符为:"); puts(str1); stringCopy(str2, str1); printf("拷贝后的第一串字符为:"); puts(str1); } |
#include #include void stringCopy(char from[], char to[]); void stringCopy(char from[], char to[]){ int i = 0; while(from[i] != '\0'){ to[i] = from[i]; i++; } to[i] = '\0'; } void main(void){ char str1[80] = {0}; char str2[80] = {0}; char *p1 = str1; char *p2 = str2; printf("请输入第二串字符:"); gets(str2); printf("拷贝前的第一串字符为:"); puts(str1); stringCopy(p2, p1); printf("拷贝后的第一串字符为:"); puts(str1); } |
#include #include void stringCopy(char *from, char *to); void stringCopy(char *from, char *to){ while(*from != '\0'){ *to = *from; from++; to++; } *to = '\0'; } void main(void){ char str1[80] = {0}; char str2[80] = {0}; printf("请输入第二串字符:"); gets(str2); printf("拷贝前的第一串字符为:"); puts(str1); stringCopy(str2, str1); printf("拷贝后的第一串字符为:"); puts(str1); } |
#include #include void stringCopy(char *from, char *to); void stringCopy(char *from, char *to){ while(*from != '\0'){ *to = *from; from++; to++; } *to = '\0'; } void main(void){ char str1[80] = {0}; char str2[80] = {0}; char *p1 = str1; char *p2 = str2; printf("请输入第二串字符:"); gets(str2); printf("拷贝前的第一串字符为:"); puts(str1); stringCopy(p2, p1); printf("拷贝后的第一串字符为:"); puts(str1); } |
|
|
10.2(45)输入3个字符串,按由小到大的顺序输出
void swap(char *a, char *b){ //char *tmp = a; *tmp = *a; *a = *b; *b = *tmp; } |
void swap(char *a, char *b){ char tmp[ARRAY_SIZE]; //char *tmp = a; *tmp = *a; *a = *b; *b = *tmp; } |
 |
 |
这样子的函数其实只能交换每个字符串的第一个字符,但tmp的初值实在是无处安放,要是真的想交换第一个字符,就要先让tmp指向这三个之外的一个字符串,这样才可以达到目的。 |
定义tmp为一个字符数组,而不是指针变量,就可以了 |
void swap(char *a, char *b){ char tmp[ARRAY_SIZE]; //char *tmp; *tmp = *a; *a = *b; *b = *tmp; } |
void swap(char *a, char *b){ char tmp[ARRAY_SIZE]; //char *tmp; tmp = a; a = b; b = tmp; } |
void swap(char *a, char *b){ char tmp[ARRAY_SIZE]; //char *tmp; strcpy(tmp, a); strcpy(a, b); strcpy(b, tmp); } |
 |
 |
 |
这样只能交换每个字符串的第一个字符 |
这样子交换的是指针的值,但是指针的值并不会通过函数传递出来,我们的目的是通过指针的指向改变内存中字符串的值。 |
这才是正解 |
|
10.12用指针数组处理上一题目,字符串不等长 优先级:()>[]>*
用指针数组作为参数 void stringSort(char *a[], int row); void main(void){ int i = 0; char a[10][20]; char *p[10]; for(i = 0; i < 10; i++){ p[i] = a[i]; } ....... stringSort(p, 10); ....... } |
|
eg10.22求a和b中的最大值(指向函数的指针) 函数的调用
可以通过函数名调用 |
也可以通过函数指针调用(即用指向函数的指针变量调用) |
#include int max(int a, int b); int max(int a, int b){ return (a>b) ? a : b; } void main(void){ int a, b, c; printf("请输入两个整数:"); scanf("%d%d", &a, &b); c = max(a, b); printf("%d和%d中的最大值是:%d\n", a, b, c); } |
#include int max(int a, int b); int max(int a, int b){ return (a>b) ? a : b; } void main(void){ int a, b, c; int (*p)(int, int); printf("请输入两个整数:"); scanf("%d%d", &a, &b); p = max; c = (*p)(a, b); printf("%d和%d中的最大值是:%d\n", a, b, c); } |
|
int (*p)(int, int); //定义 用来定义p是一个指向函数的指针变量,它不是固定指向哪一个函数的,而只是表示定义了这样一个类型的变量,它是专门用来存放函数的入口地址的。在程序中把哪一个函数的地址赋给它,它就指向哪一个函数。在一个程序中,一个指针变量可以先后指向同类型的不同函数。 *p两侧的括号不可省略,表示p先与*结合,是指针变量,然后再与后面的()结合,表示此指针变量指向函数。 p = max; //赋值 在给函数指针变量赋值时,只需给出函数名而不必给出参数,因为这是将函数的地址赋给p,不涉及实参与形参的问题。 将函数max的人口地址赋给指针变量p 这时,p是指向函数max的指针变量 调用*p就是调用max函数 (注)p是指向函数的指针变量,它只能指向函数的入口地址而不可能指向函数中的某一条指令处。对指向函数的指针变量,像p+n、p++、p--等运算都是无意义的。 c = (*p)(a, b); //调用 <=>c = max(a, b); 用函数指针变量调用函数时,只需将(*p)代替函数名即可,在(*p)后面的括号中根据需要写上实参。 |
|
eg10.23有一个函数process,在调用它的时候,每次实现不同的功能(用指向函数的指针作函数参数)
int max(int a, int b); int min(int a, int b); int add(int a, int b); void process(int (*p)(int, int), int x, int y); void main(void){ int a, b, c; printf("请输入两个整数:"); scanf("%d%d", &a, &b); printf("%d和%d中的最大值是:", a, b); process(max, a, b); printf("%d和%d中的最小值是:", a, b); process(min, a, b); printf("%d和%d之和是:", a, b); process(add, a, b); } |
|
eg10.25对上例中的学生,找出其中不及格课程的学生及其学生号 //思考;返回的指针只能返回一个不及格的学生,万一有多个学生该怎么办? //课本:在主函数中对各个学生进行循环,分别判断其是否及格 |
10.20用指向指针的指针的方法对5个字符串排序并输出
指针数组的元素指向字符串 (1) char *a[12] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; char **p = a; (2) char *a[ ] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; char **p = a; (3)用户输入字符串 char str[5][20]; char *pstr[5]; char **p; int i; // pstr = str; 这样不对 for(i = 0; i < 5; i++){ pstr[i] = str[i]; } p = pstr; printf("请输入5个字符串:\n"); inputString(pstr,5); |
|
10.21用指向指针的指针的方法对n个整数排序并输出
指针数组的元素指向整型数组 (1) int a[5] = {1, 3, 5, 7, 9}; int *num[5] = {&a[0], &a[1], &a[2], &a[3], &a[4]}; int **p; int i; p = num; for(i = 0; i < 5; i++){ printf("%d ", **p); p++; } printf("\n"); (2) int a[10]; int *pa[10] = {&a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7], &a[8], &a[9]}; int **p = pa; int i; printf("请输入10个整数:"); for(i = 0; i < 10; i++){ scanf("%d", &a[i]); } |
|
|