C语言谭浩强第三版第十章例题及课后题:指针
eg10.3输入a和b两个整数,按先大后小的顺序输出a和b
#include<stdio.h> void swap(int *a, int *b); void swap(int *a, int *b){ void main(void){ swap(&m, &n); //等价于swap(p1,p2);
|
#include<stdio.h> void swap(int *a, int *b); void swap(int *a, int *b){ //等价于swap(p1,p2);
|
#include<stdio.h> void swap(int **a, int **b); void swap(int **a, int **b){ //swap(&(&m), &(&n)); //[Error]lvalue required as unary '&' operand //unary a.一元的 |
交换的是两个变量的值 |
交换的是两个指针的值 |
//eg10.3输入a和b两个整数,按先大后小的顺序输出a和b
/*
#include<stdio.h>
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);
printf("交换后的两个整数为:%d,%d\n", m, n);
printf("交换后两个指针指向的整数为:%d,%d\n", *p1, *p2);
}
*/
/*
#include<stdio.h>
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);
printf("交换后的两个整数为:%d,%d\n", m, n);
printf("交换后两个指针指向的整数为:%d,%d\n", *p1, *p2);
}
*/
#include<stdio.h>
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)); //[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
swap(&p1, &p2);
printf("交换后的两个整数为:%d,%d\n", m, n);
printf("交换后两个指针指向的整数为:%d,%d\n", *p1, *p2);
}
eg10.5输出数组中的全部元素
用for循环输出
#include<stdio.h> void main(void){ |
#include<stdio.h> void main(void){ |
#include<stdio.h> void main(void){ |
#include<stdio.h> void main(void){ p++; |
这个和下一个执行效率是相同的。C编译系统是将a[i]转换为*(a+i)处理的,即先计算地址元素。 | 比前两种方法快,用指针变量直接指向元素,不必每次都重新计算地址,像p++这样的自加操作是比较快的。 |
用while循环输出
p = a; //*p++ <=> *p(++) 先得到p所指向的变量的值(即*p),然后再使p+1=>p |
p = a; while(p<a+10){ printf("%d ", *p); p++; } |
//1 2 3 4 5 6 7 8 9 0
/*
#include<stdio.h>
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<stdio.h>
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<stdio.h>
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");
}
eg10.7将数组a中n个整数按相反顺序存放
void inv(int *a, int n){ |
void inv(int *a, int n){ |
两种方法得到的结果相同,都可以实现题目要求功能 |
有一个实参数组,要想在函数中改变此数组中的元素的值,实参与形参的对应关系有以下4种情况:
void inv(int *a, int n){ ... }
void main(void){ ... |
void inv(int a[], int n){ ... }
void main(void){ ... |
void inv(int *a, int n){ ... }
void main(void){ int *p = a; ...
|
void inv(int a[], int n){ ... }
void main(void){ int *p = a; ...
|
用数组名作函数的参数 fun(int arr[], int n) <=> fun(int *arr, int n) 实参数组名代表该数组首元素的地址,而形参是用来接收从实参传递过来的数组首元素地址的。因此,形参应该是一个指针变量(只有指针变量才能存放地址)。实际上,C编译都是将形参数组名作为指针变量来处理的。 在该函数被调用时,系统会建立一个指针变量arr,用来存放从主调函数传递过来的实参数组首元素的地址。 |
/*
#include<stdio.h>
void show(int a[], int n);
void inv(int *a, int 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 show(int a[], int n){
int i;
for(i = 0; i < n; i++){
printf("%d ", a[i]);
}
}
void main(void){
int a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};
printf("原数组中的元素为:");
show(a, 10);
printf("\n");
inv(a, 10);
printf("交换后数组中的元素为:");
show(a, 10);
}
*/
#include<stdio.h>
void show(int a[], int n);
void inv(int *a, int 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");
}
void show(int a[], int n){
int i;
for(i = 0; i < n; i++){
printf("%d ", a[i]);
}
}
void main(void){
int a[10] = {3, 7, 9, 11, 0, 6, 7, 5, 4, 2};
printf("原数组中的元素为:");
show(a, 10);
printf("\n");
inv(a, 10);
printf("交换后数组中的元素为:");
show(a, 10);
}
eg10.11用指针变量输出二维数组元素的值
#include<stdio.h> void main(void){
|
#include<stdio.h> void main(void){
|
#include<stdio.h> void main(void){
|
eg10.12输出二维数组任一行任一列元素的值
#include<stdio.h> void main(void){ |
#include<stdio.h> void main(void){ |
p是指向整型数据的,p+1所指向的元素是p所指向的元素的下一元素。 | p是指向一个包含m个元素的一维数组,p的增值以一维数组的长度为单位。 |
/*
#include<stdio.h>
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));
}
*/
#include<stdio.h>
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));
}
eg10.13有3个学生各学4门课,计算总平均分数以及第n个学生的成绩
多维数组名做函数参数
1.用指向变量的指针变量 |
2.用指向一维数组的指针变量 |
float average(float *s, int n){ void main(void){ av = average(*score, 12); //*score, 即score[0],即&score[0][0] |
void search(float (*s)[4], int n){
void main(void){ |
#include<stdio.h>
float average(float *s, int n);
void search(float (*s)[4], int n, float s1[]);
void search(float (*s)[4], int n, float s1[]){
int i;
float (*p)[4];
for(i = 0, p = s+n; i < 4; i++){
//printf("%.2f ", *(*p+i));
s1[i] = *(*p+i);
//printf("%.2f ", s1[i]);
}
}
float average(float *s, int n){
float *p;
float sum = 0;
for(p = s; p < s+n; p++){
//for(p = s; p < s+n-1; p++){
sum += *p;
}
return sum*1.0/n;
}
void main(void){
float score[3][4] = {{65, 67, 70, 60}, {80, 87, 90, 81}, {90, 99, 100, 98}};
float av;
float se[4];
int m;
int i;
av = average(*score, 12);
printf("总的平均分为:%.2f\n", av);
printf("请输入要查找的学生的序号(不超过2):");
scanf("%d", &m);
search(score, m, se);
printf("\n第%d个学生的成绩为:", m+1);
for(i = 0; i < 4; i++){
printf("%.2f ", se[i]);
}
}
eg10.14在上题基础上,查找有一门以上课程不及格的学生,输出他们的全部课程的成绩
#include<stdio.h>
void searchNotQualified(float (*a)[4], int n);
void searchNotQualified(float (*a)[4], int n){
int i, j;
int flag;
for(i = 0; i < n; i++){
flag = 0;
for(j = 0; j < 4; j++){
if(*(*(a+i)+j) < 60){
flag=1;
}
}
if(flag == 1){
printf("序号为%d的学生成绩不及格,各科分数为:", i);
for(j = 0; j < 4; j++){
printf("%.2f ", *(*(a+i)+j));
}
printf("\n");
}
}
}
void main(void){
float score[3][4] = {{65, 57, 70, 60}, {80, 87, 90, 81}, {90, 99, 100, 98}};
searchNotQualified(score, 3);
}
eg10.15定义一个字符数组,对它初始化,然后输出该字符串
eg10.16定义字符指针
C语言中,可以用两种方法访问一个字符串
(1)用字符数组存放一个字符串 | (2)用字符指针指向一个字符串 |
#include<stdio.h> void main(void){ |
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'为止。 |
#include<stdio.h>
void main(void){
char string[] = "I love China!";
printf("%s\n", string);
}
#include<stdio.h>
void main(void){
char *string = "I love China!";
printf("%s\n", string);
}
eg10.17将字符串a复制为字符串b
eg10.18用指针变量处理eg10.17问题
对字符串中字符的存取,可以用下标方法,也可以用指针方法。
7.15字符串拷贝 | 下标法 | 和2等价 | 指针方法 |
#include<stdio.h> #include<string.h> 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<stdio.h> #include<string.h> 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<stdio.h> #include<string.h> 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<stdio.h> #include<string.h> 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); } |
/*
//7.15字符串拷贝,不要用strcpy函数
#include<stdio.h>
#include<string.h>
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<stdio.h>
#include<string.h>
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]; //str1[i] = '\0'; 这样写也可以 //把最后的那个'\0'复制过去
printf("拷贝后的第一串字符为:");
puts(str1);
}
*/
//课本
#include<stdio.h>
#include<string.h>
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'; //str1[i] = '\0'; 这样写也可以 //把最后的那个'\0'复制过去
printf("拷贝后的第一串字符为:");
puts(str1);
}
#include<stdio.h>
#include<string.h>
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用函数调用实现字符串的复制
将一个字符串从一个函数传递到另一个函数,可以用地址传递的方法(即用字符数组名作参数),也可以用指向字符的指针变量作参数。在被调用的函数中可以改变字符串的内容,在主调函数中可以得到改变了的字符串。 |
||||||||
归纳起来,作为函数参数,有以下几种情况:
|
//字符串2复制到字符串1
/*
#include<stdio.h>
#include<string.h>
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<stdio.h>
#include<string.h>
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<stdio.h>
#include<string.h>
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<stdio.h>
#include<string.h>
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.1(20)输入3个整数,按由小到大的顺序输出
// 6:55 - 7:15
#include<stdio.h>
void sort(int *a, int *b, int *c);
void swap(int *a, int *b);
void swap(int *a, int *b){
int tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
void sort(int *a, int *b, int *c){ //按 a<b<c 排
if(*a > *b){
swap(a, b); //使a成为a b中较小的一个
}
if(*a > *c){
swap(a, c); //使a成为a c中较小的一个
} //所以,a是三者中最小的一个
if(*b > *c){
swap(b, c); //使b成为b c中较小的一个
}
}
void main(void){
int a, b, c;
int a1, b1, c1;
printf("请输入3个整数:");
scanf("%d%d%d", &a, &b, &c);
printf("\n这3个整数为:%d %d %d\n", a, b, c);
a1 = a;
b1 = b;
c1 = c;
sort(&a1, &b1, &c1);
printf("\n按由小到大的顺序排序为:%d %d %d\n", a1, b1, c1);
}
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); } |
这样只能交换每个字符串的第一个字符 | 这样子交换的是指针的值,但是指针的值并不会通过函数传递出来,我们的目的是通过指针的指向改变内存中字符串的值。 | 这才是正解 |
// 7:20 - 8:05
/*
I study very hard.
C language is very interesting.
He is a professor.
*/
#include<stdio.h>
#include<string.h>
#define ARRAY_SIZE 80
void swap(char *a, char *b);
/*
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;
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);
}
void main(void){
char s1[ARRAY_SIZE];
char s2[ARRAY_SIZE];
char s3[ARRAY_SIZE];
char *p1 = s1;
char *p2 = s2;
char *p3 = s3;
printf("请输入3个字符串:\n");
gets(p1);
gets(p2);
gets(p3);
if(strcmp(p1, p2) > 0){
swap(p1, p2);
}
printf("\n按由小到大的顺序排序为:\n%s\n%s\n%s\n", p1, p2, p3);
if(strcmp(p1, p3) > 0){
swap(p1, p3);
}
printf("\n按由小到大的顺序排序为:\n%s\n%s\n%s\n", p1, p2, p3);
if(strcmp(p2, p3) > 0){
swap(p2, p3);
}
printf("\n按由小到大的顺序排序为:\n%s\n%s\n%s\n", p1, p2, p3);
}
10.3(30)输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换
忘记用指针了
/*
10.3输入10个整数,将其中最小的数与第一个数对换,把最大的数与最后一个数对换
写3个函数:
1)输入10个数
2)进行处理
3)输出10个数
*/
// 8:30 - 9:00
//32 24 56 78 1 98 36 44 29 6
#include<stdio.h>
void initial(int num[], int n);
void show(int num[], int n);
void fun(int num[], int n);
void fun(int num[], int n){
int min = num[0];
int max = num[0];
int minIndex = 0;
int maxIndex = 0;
int i;
for(i = 0; i < n; i++){
if(num[i] < min){
min = num[i];
minIndex = i;
}
if(num[i] > max){
max = num[i];
maxIndex = i;
}
}
printf("min=%d, minIndex=%d, max=%d, maxIndex=%d\n", min, minIndex, max, maxIndex);
num[minIndex] = num[0];
num[0] = min;
num[maxIndex] = num[n-1];
num[n-1] = max;
}
void show(int num[], int n){
int i;
for(i = 0; i < n; i++){
printf("%d ", num[i]);
}
printf("\n");
}
void initial(int num[], int n){
int i;
for(i = 0; i < n; i++){
scanf("%d", &num[i]);
}
}
#include<stdio.h>
void main(void){
int num[10];
printf("请输入10个整数:");
initial(num, 10);
printf("这10个整数为:");
show(num, 10);
fun(num, 10);
printf("经过变换之后的10个整数为;");
show(num, 10);
}