C语言学习与总结---第八章:指针[03]

指针[03]

  • 8.6 指针与字符串
    • 8.6.1 字符串的表示
    • 8.6.2 字符数组作函数参数
    • 8.6.3 区别:字符指针变量和字符数组
  • 8.7 指向函数的指针
    • 8.7.1 函数的指针
    • 8.7.2 用函数指针变量调用函数
    • 8.7.3 用指向函数的指针作函数参数
  • 8.8 返回指针值的函数
  • 8.9 指针数组和多重指针
    • 8.9.1 指针数组
    • 8.9.2指向指针数据的指针

8.6 指针与字符串

8.6.1 字符串的表示

(1)用字符数组存放一个字符串

#include  
int main()  
{  
    char string[] = "I Love China!";  
    printf("%s\n", string);  
    return 0;  
}  

(2)用字符指针指向一个字符串

#include  
int main()  
{  
    char* string = "I Love China!";  
    printf("%s\n", string);  
    return 0;  
}

注意

char* string = "I Love China!"; 

等价于

char* string; string = "I Love China!"; 

而不是

char* string; *string = "I Love China!"; 

例,字符串的复制:将字符数组a里面的字符串复制到字符数组b.

#include  
int main()  
{  
    char a[] = "I am a boy.", b[20];  
    int i;  
    for (i = 0; *(a + i) != '\0'; i++)  
        *(b + i) = *(a + i);  
    *(b + i) = '\0';  //当循环结束时,指针位置跳到i+1,正好是结束符的位置;
    printf("string a is : %s\n", a);  
    printf("string b is : ");  
    for (i = 0; b[i] != '\0'; i++)  
        printf("%c", b[i]);  
    printf("\n");  
    return 0;  
}

用指向字符数组的指针实现:

#include   
int main()  
{  
    char a[] = "I am a boy.", b[20], * p1, * p2;  
    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);  
    return 0;  
}  

8.6.2 字符数组作函数参数

(1)实参形参都为字符数组

#include   
void copy_string(char from[], char to[]);  
int main()  
{  
    char a[] = "I am a teacher.";  
    char b[] = "you are a student.";  
    printf("string a = %s\nstring b = %s\n", a, b);  
    printf("copy string a to string b: \n");  
    copy_string(a, b);  
    printf("\nstring a = %s\nstring b = %s\n", a, b);  
    return 0;  
}  
void copy_string(char from[], char to[])  
{  
    int i = 0;  
    while (from[i] != '\0')  
    {  
        to[i] = from[i];  
        i++;  
    }  
    to[i] = '\0';  
}  

(2)实参为指针变量

#include   
void copy_string(char from[], char to[]);  
int main()  
{  
    char a[] = "I am a teacher.";  
    char b[] = "you are a student.";  
    char* from = a, * to = b;  
    printf("string a = %s\nstring b = %s\n", a, b);  
    printf("copy string a to string b: \n");  
    copy_string(from, to);  
    printf("\nstring a = %s\nstring b = %s\n", a, b);  
    return 0;  
} 

(3)形参为指针变量

void copy_string(char* from, char* to)  
{
   for (; *from != '\0'; from++, to++)  
     *to = *from;  
*to = '\0'; 
}

或者

void copy_string(char* from, char* to)  
{  
    while ((*to = *from) != '\0')  
    {  
        to++;  
        from++;  
    }
}  

8.6.3 区别:字符指针变量和字符数组

(1)字符指针变量

char *a=″I love China!″;

等价于

char*a;a=″I love China!″;

而字符数组

char  str[14] =″I love  China!″;

不能等价于

char str[14];str[] =″I love China!″;

(2)字符数组的输入:

char str[10];scanf(″%s″,str);

但是字符指针变量

char *a;scanf(″%s″,a);

却是错误的,正确输入为:

char *a, str[10];a = str;scanf(″%s″,a);

8.7 指向函数的指针

8.7.1 函数的指针

用指针变量可以指向一个函数;函数在编译时被分配给一个入口地址这个函数的入口地址就称为函数的指针;函数名代表函数的入口地址;

8.7.2 用函数指针变量调用函数

一般定义形式:

数据类型  (*指针变量名)(函数参数表列)

例如这个简单的比较大小的函数

#include   
int 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\n", a, b, c);  
    return 0;  
}  
int max(int x, int y)  
{  
    int z;  
    if (x > y) z = x;  
    else z = y;  
    return z;  
}

主函数里面可以使用函数指针变量:

#include   
int main()  
{  
    int max(int, int);  
    int (*p)(int, int);/*类型要跟被指向函数类型一致, 
                        参数表列类型也要跟被指向函数一致,(*p)的括号不能省略*/  
    int a, b, c;  
    p = max;  
    scanf("%d,%d", &a, &b);  
    c = (*p)(a, b);  
    printf("a=%d,b=%d,max=%d\n", a, b, c);  
    return 0;  
}  

注意
(1)* p两侧的括号不能省略,表示p先于 * 结合,是指针变量,然后再与后面的()结合,表示此指针变量指向函数。

(2)对指向函数的指针变量,像p+n、p++、p–等运算是没有意义的。

8.7.3 用指向函数的指针作函数参数

指向函数的指针作为参数,可以实现函数地址的传递,这样就能够在被调用的函数中使用实参函数。
C语言学习与总结---第八章:指针[03]_第1张图片
例,有两个整数a和b,由用户输入1,2或3。输入1时,输出a和b中大者;输入2时,输出a和b中小者;输入3时,输出a和b之和。

#include   
int main()  
{  
    void fun(int, int, int (*p)(int, int));  
    int max(int, int);  
    int min(int, int);  
    int add(int, int);  
    int a = 34, b = -21, n;  
    scanf("%d",&n);  
    if (n == 1) fun(a, b, max);  
    else if (n == 2) fun(a, b, min);  
    else if (n == 3) fun(a, b, add);  
    return 0;  
}  
void fun(int x,int y,int(*p)(int, int))  
{  
    int  result;  
    result = (*p)(x, y);  
    printf("%d\n", result);  
}  
int max(int x, int y)  
{  
    int z;  
    if (x > y) z = x;  
    else z = y;  
    return z;  
}  
int min(int x, int y)  
{  
    int z;  
    if (x < y) z = x;  
    else z = y;  
    return z;  
}  
int add(int x, int y)  
{  
    int z;  
    z = x + y;  
    return z;  
} 

第4行中,第三个参数是指向函数的指针,发生调用时,根据实参决定形参指针指向哪个函数,例如第11行中,函数调用

fun(a, b, min);

void fun(int, int, int (*p)(int, int))

中的形参(*p)指向函数min;

8.8 返回指针值的函数

一个函数可以带回一个整型值、字符值、实型值等,也可以带回指针型的数据,即地址。
一般定义形式为:

类型名 *函数名(参数表列);

例如:

int *a(int x,int y);

注意

*a两侧没有括号,在a的两侧分别为*运算符和()运算符。
而()优先级高于*,因此a先与()结合,这是函数形式。
前面有一个*,表示此函数是指针型函数,即函数值是指针。

例,有若干个学生的成绩(每个学生有4门 课程),要求在用户输入学生序号以 后,能输出该学生的全部成绩。

#include   
int main()  
{  
    float score[][4] = { {60,70,80,90},{56,89,67,88},{34,78,90,66} };  
    float* search(float(*p)[4], int n);  
    float* p1;  
    int i, k;  
    printf("enter the number of student: ");  
    scanf("%d", &k);  
    printf("The scores of No. %d are: \n", k);  
    p1 = search(score, k);  
    for (i = 0; i < 4; i++)  
        printf("%5.2f\t", *(p1 + i));  
    printf("\n");  
    return 0;  
}  
float* search(float(*p)[4], int n)  
{  
    float* pt;  
    pt = *(p + n);  
    return pt;  
}

例,对上例中的学生,找出其中有不及格课程的学生及其学生号

#include  
int main()  
{  
    float s[][4] = { {60,70,80,90},{56,89,67,88},{34,78,90,66} };  
    float* search(float(*pr)[4]);  
    float* p;  
    int i, j;  
    for (i = 0; i < 3; i++)  
    {  
        p = search(s + i);  
        if (p == *(s + i))  
        {  
            printf("No. %d scores;", i);  
            for (j = 0; j < 4; j++)  
                printf("%5.2f, ", *(p + j));  
            printf("\n");  
        }  
    }  
    return 0;  
}  
  
float* search(float(*p)[4])  
{  
      int i;  
      float* pt;  
      pt = NULL;  
      for (i = 0; i < 4; i++)  
          if (*(*p + i) < 60) pt = *p;  
      return pt;  
} 

8.9 指针数组和多重指针

8.9.1 指针数组

一个数组,若其元素均为指针类型数据,称为指针数组,即指针数组中的每一个元素都相当于一个指针变量。
一维指针数组的定义形式为: 类型名*数组名[数组长度];
例如:

int *p[4];

注意
由于[]比* 优先级高,因此p先与[4]结合,形成p[4]形式,这是数组形式,它有4个元素。然后再与*结合,表示此数组是指针类型的,每个数组元素都是一个指针变量。
例如,下面这个程序

#include 
#include 
void sort(char* name[], int n);
void print(char* name[], int n);
int main()
{
		char* name[] = { "Follow me", "BASIC",
		   "Great Wall", "FORTRAN", "Computer design" };
	int n = 5;
	sort(name, n);
	print(name, n);
	return 0;
}
void sort(char* name[],int n)
{
	char* temp;
	int i, j, k;
		for (i = 0 ; i < n - 1; i++)
		{
			k = i;
			for (j = i + 1; j < n; 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 < n; i++)
		printf("%s\n", name[i]);
}

C语言学习与总结---第八章:指针[03]_第2张图片
C语言学习与总结---第八章:指针[03]_第3张图片
C语言学习与总结---第八章:指针[03]_第4张图片
运行结果:
C语言学习与总结---第八章:指针[03]_第5张图片

8.9.2指向指针数据的指针

定义一个指向指针数据的指针变量:

char **p;

p的前面有两个* 号。*运算符的结合性是从右到左,因此**p相当于 * ( * p)。
如果没有最前面的 * ,那就是定义了一个指向字符数据的指针变量。
现在它前面又有一个*号,表示指针变量p是指向一个字符指针变量的。
*p就是p所指向的另一个指针变量。
#include  
int main()  
{  
    char* name[] = { "Follow me", "BASIC",  
                    "Great Wall", "FORTRAN", "Computer design" };  
    char** p;  
        for(int i=0;i<5;i++)  
    {  
            p = name + i;  
            printf("%s\n", *p);  
    }  
    return 0;  
}

运行结果
C语言学习与总结---第八章:指针[03]_第6张图片
C语言学习与总结---第八章:指针[03]_第7张图片
再如

1.	#include<stdio.h>  
2.	int main()  
3.	{  
4.	    int a[5] = { 1, 3, 5, 7, 9 };  
5.	    int* num[5] = { &a[0], &a[1], &a[2], &a[3], &a[4] };  
6.	    int** p,i;  
7.	    p = num;  
8.	    for(i=0;i<5;i++)  
9.	    {  
10.	        printf("%d\n", **p);  
11.	        p++;  
12.	    }  
13.	    return 0;  
14.	}

运行结果
C语言学习与总结---第八章:指针[03]_第8张图片
C语言学习与总结---第八章:指针[03]_第9张图片

你可能感兴趣的:(C语言,指针,数组)