⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 6_指针.txt

📁 一些c的经典案例
💻 TXT
📖 第 1 页 / 共 3 页
字号:
                        "Wednesday",
                        "Thursday",
                        "Friday",
                        "Saturday",
                        "Sunday"};
  return((n<1||n>7) ? name[0] : name[n]);
}
本程序是通过指针函数,输入一个1~7之间的整数, 输出对应的星期名。指针数组的说明与使用
    一个数组的元素值为指针则是指针数组。 指针数组是一组有序
的指针的集合。 指针数组的所有元素都必须是具有相同存储类型和
指向相同数据类型的指针变量。
指针数组说明的一般形式为:    类型说明符*数组名[数组长度]  
其中类型说明符为指针值所指向的变量的类型。例如:    int *pa[3]    表示pa是一个指针数组,它有三个数组元素, 每个元素值都是
一个指针,指向整型变量。
    通常可用一个指针数组来指向一个二维数组。 指针数组中的每
个元素被赋予二维数组每一行的首地址, 因此也可理解为指向一个
一维数组。图6—6表示了这种关系。
int a[3][3]={1,2,3,4,5,6,7,8,9};
int *pa[3]={a[0],a[1],a[2]};
int *p=a[0];
main(){
  int i;
  for(i=0;i<3;i++)
      printf("%d,%d,%d\n",a[i][2-i],*a[i],*(*(a+i)+i));
  for(i=0;i<3;i++)
      printf("%d,%d,%d\n",*pa[i],p[i],*(p+i));
}    本例程序中,pa是一个指针数组,三个元素分别指向二维数组a
的各行。然后用循环语句输出指定的数组元素。其中*a[i]表示i行0
列元素值;*(*(a+i)+i)表示i行i列的元素值;*pa[i]表示i行0列元
素值;由于p与a[0]相同,故p[i]表示0行i列的值;*(p+i)表示0行i
列的值。读者可仔细领会元素值的各种不同的表示方法。 应该注意
指针数组和二维数组指针变量的区别。 这两者虽然都可用来表示二
维数组,但是其表示方法和意义是不同的。
    二维数组指针变量是单个的变量,其一般形式中"(*指针变量名)
"两边的括号不可少。而指针数组类型表示的是多个指针( 一组有序
指针)在一般形式中"*指针数组名"两边不能有括号。例如:    int (*p)[3];
    表示一个指向二维数组的指针变量。该二维数组的列数为3或分
解为一维数组的长度为3。    int *p[3]    表示p是一个指针数组,有三个下标变量p[0],p[1],p[2]均为
指针变量。
    指针数组也常用来表示一组字符串, 这时指针数组的每个元素
被赋予一个字符串的首地址。 指向字符串的指针数组的初始化更为
简单。例如在例6.20中即采用指针数组来表示一组字符串。 其初始
化赋值为:    char *name[]={"Illagal day",
                  "Monday",
                  "Tuesday",
                  "Wednesday",
                  "Thursday",
                  "Friday",
                  "Saturday",
                  "Sunday"};
    完成这个初始化赋值之后,name[0]即指向字符串"Illegal day"
,name[1]指向"Monday"......。
指针数组也可以用作函数参数。
    在本例主函数中,定义了一个指针数组name,并对name 作了初
始化赋值。其每个元素都指向一个字符串。然后又以name 作为实参
调用指针型函数day  name,在调用时把数组名 name 赋予形参变量
name,输入的整数i作为第二个实参赋予形参n。在day  name函数中
定义了两个指针变量pp1和pp2,pp1被赋予name[0]的值(即*name),
pp2被赋予name[n]的值即*(name+ n)。由条件表达式决定返回pp1或
pp2指针给主函数中的指针变量ps。最后输出i和ps的值。
指针数组作指针型函数的参数。
main(){
  static char *name[]={ "Illegal day",
                        "Monday",
                        "Tuesday",
                        "Wednesday",
                        "Thursday",
                        "Friday",
                        "Saturday",
                        "Sunday"};
  char *ps;
  int i;
  char *day  name(char *name[],int n);
  printf("input Day No:\n");
  scanf("%d",&i);
  if(i<0) exit(1);
  ps=day  name(name,i);
  printf("Day No:%2d-->%s\n",i,ps);
}
char *day name(char *name[],int n)
{
  char *pp1,*pp2;
  pp1=*name;
  pp2=*(name+n);
  return((n<1||n>7)? pp1:pp2);
}    下例要求输入5个国名并按字母顺序排列后输出。在以前的例子
中采用了普通的排序方法, 逐个比较之后交换字符串的位置。交换
字符串的物理位置是通过字符串复制函数完成的。 反复的交换将使
程序执行的速度很慢,同时由于各字符串(国名) 的长度不同,又增
加了存储管理的负担。 用指针数组能很好地解决这些问题。把所有
的字符串存放在一个数组中, 把这些字符数组的首地址放在一个指
针数组中,当需要交换两个字符串时, 只须交换指针数组相应两元
素的内容(地址)即可,而不必交换字符串本身。
    程序中定义了两个函数,一个名为sort完成排序, 其形参为指
针数组name,即为待排序的各字符串数组的指针。形参n为字符串的
个数。另一个函数名为print,用于排序后字符串的输出,其形参与
sort的形参相同。主函数main中,定义了指针数组name 并作了初始
化赋值。然后分别调用sort函数和print函数完成排序和输出。值得
说明的是在sort函数中,对两个字符串比较,采用了strcmp 函数,
strcmp函数允许参与比较的串以指针方式出现。name[k]和name[ j]
均为指针,因此是合法的。字符串比较后需要交换时, 只交换指针
数组元素的值,而不交换具体的字符串, 这样将大大减少时间的开
销,提高了运行效率。现编程如下:
#include"string.h"
main(){
  void sort(char *name[],int n);
  void print(char *name[],int n);
  static char *name[]={ "CHINA","AMERICA","AUSTRALIA",
                        "FRANCE","GERMAN"};
  int n=5;
  sort(name,n);
  print(name,n);
}
void sort(char *name[],int n){
  char *pt;
  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){
          pt=name[i];
          name[i]=name[k];
          name[k]=pt;
      }
  }
}
void print(char *name[],int n){
  int i;
  for (i=0;i<n;i++) printf("%s\n",name[i]);
}main函数的参数
    前面介绍的main函数都是不带参数的。因此main 后的括号都是
空括号。实际上,main函数可以带参数,这个参数可以认为是 main
函数的形式参数。C语言规定main函数的参数只能有两个, 习惯上
这两个参数写为argc和argv。因此,main函数的函数头可写为:    main (argc,argv)
    C语言还规定argc(第一个形参)必须是整型变量,argv( 第二个
形参)必须是指向字符串的指针数组。加上形参说明后,main函数的
函数头应写为:    main (argc,argv)
         int argv;
         char *argv[];或写成:
    main (int argc,char *argv[])
    由于main函数不能被其它函数调用, 因此不可能在程序内部取
得实际值。那么,在何处把实参值赋予main函数的形参呢? 实际上
,main函数的参数值是从操作系统命令行上获得的。当我们要运行一
个可执行文件时,在DOS提示符下键入文件名,再输入实际参数即可
把这些实参传送到main的形参中去。
DOS提示符下命令行的一般形式为:    C:\>可执行文件名  参数  参数……;  
    但是应该特别注意的是,main 的两个形参和命令行中的参数在
位置上不是一一对应的。因为,main的形参只有二个,而命令行中的
参数个数原则上未加限制。argc参数表示了命令行中参数的个数(注
意:文件名本身也算一个参数),argc的值是在输入命令行时由系统
按实际参数的个数自动赋予的。例如有命令行为:    C:\>E6  24  BASIC  dbase  FORTRAN      由于文件名E6  24本身也算一个参数,所以共有4个参数,因此
argc取得的值为4。argv参数是字符串指针数组,其各元素值为命令
行中各字符串(参数均按字符串处理)的首地址。 指针数组的长度即
为参数个数。数组元素初值由系统自动赋予。其表示如图6.8所示:
main(int argc,char *argv){
  while(argc-->1)
      printf("%s\n",*++argv);
}
本例是显示命令行中输入的参数
    如果上例的可执行文件名为e24.exe,存放在A驱动器的盘内。
因此输入的命令行为:    C:\>a:e24 BASIC dBASE FORTRAN  则运行结果为:BASIC
dBASE
FORTRAN
    该行共有4个参数,执行main时,argc的初值即为4。argv的4个
元素分为4个字符串的首地址。执行while语句,每循环一次 argv值
减1,当argv等于1时停止循环,共循环三次, 因此共可输出三个参
数。在printf函数中,由于打印项*++argv是先加1再打印, 故第一
次打印的是argv[1]所指的字符串BASIC。第二、 三次循环分别打印
后二个字符串。而参数e24是文件名,不必输出。
    下例的命令行中有两个参数,第二个参数20即为输入的n值。在
程序中*++argv的值为字符串“20”,然后用函数"atoi"把它换为整
型作为while语句中的循环控制变量,输出20个偶数。
#include"stdlib.h"
main(int argc,char*argv[]){
  int a=0,n;
  n=atoi(*++argv);
  while(n--) printf("%d  ",a++*2);
}
本程序是从0开始输出n个偶数。指向指针的指针变量
    如果一个指针变量存放的又是另一个指针变量的地址, 则称这
个指针变量为指向指针的指针变量。
    在前面已经介绍过,通过指针访问变量称为间接访问, 简称间
访。由于指针变量直接指向变量,所以称为单级间访。 而如果通过
指向指针的指针变量来访问变量则构成了二级或多级间访。 
    在C语言程序中,对间访的级数并未明确限制, 但是间访级数
太多时不容易理解解,也容易出错,因此,一般很少超过二级间访。
指向指针的指针变量说明的一般形式为:    类型说明符** 指针变量名;  
例如:    int ** pp;    表示pp是一个指针变量,它指向另一个指针变量, 而这个指针
变量指向一个整型量。下面举一个例子来说明这种关系。
main(){
  int x,*p,**pp;
  x=10;
  p=&x;
  pp=&p;
  printf("x=%d\n",**pp);
}    上例程序中p 是一个指针变量,指向整型量x;pp也是一个指针
变量, 它指向指针变量p。通过pp变量访问x的写法是**pp。程序最
后输出x的值为10。通过上例,读者可以学习指向指针的指针变量的
说明和使用方法。
    下述程序中首先定义说明了指针数组ps并作了初始化赋值。 又
说明了pps是一个指向指针的指针变量。在5次循环中, pps 分别取
得了ps[0],ps[1],ps[2],ps[3],ps[4]的地址值(如图6.10所示)
。再通过这些地址即可找到该字符串。
main(){
  static char *ps[]={ "BASIC","DBASE","C","FORTRAN",
                      "PASCAL"};
  char **pps;
  int i;
  for(i=0;i<5;i++){
      pps=ps+i;
      printf("%s\n",*pps);
  }
}
本程序是用指向指针的指针变量编程,输出多个字符串。本章小结
1. 指针是C语言中一个重要的组成部分,使用指针编程有以下优点:
(1)提高程序的编译效率和执行速度。
(2)通过指针可使用主调函数和被调函数之间共享变量或数据结构,
   便于实现双向数据通讯。
(3)可以实现动态的存储分配。
(4)便于表示各种数据结构,编写高质量的程序。
2. 指针的运算
(1)取地址运算符&:求变量的地址
(2)取内容运算符*:表示指针所指的变量
(3)赋值运算
  ·把变量地址赋予指针变量
  ·同类型指针变量相互赋值
  ·把数组,字符串的首地址赋予指针变量
  ·把函数入口地址赋予指针变量(4)加减运算
    对指向数组,字符串的指针变量可以进行加减运算,如p+n,p-n,
p++,p--等。对指向同一数组的两个指针变量可以相减。对指向其它
类型的指针变量作加减运算是无意义的。
(5)关系运算
    指向同一数组的两个指针变量之间可以进行大于、小于、 等于
比较运算。指针可与0比较,p==0表示p为空指针。3. 与指针有关的各种说明和意义见下表。
int *p;       p为指向整型量的指针变量
int *p[n];    p为指针数组,由n个指向整型量的指针元素组成。
int (*p)[n];  p为指向整型二维数组的指针变量,二维数组的列数
              为n
int *p()      p为返回指针值的函数,该指针指向整型量
int (*p)()    p为指向函数的指针,该函数返回整型量
int **p       p为一个指向另一指针的指针变量,该指针指向一个
              整型量。
4. 有关指针的说明很多是由指针,数组,函数说明组合而成的。
    但并不是可以任意组合,例如数组不能由函数组成,即数组元素
不能是一个函数;函数也不能返回一个数组或返回另一个函数。例如
int a[5]();就是错误的。5. 关于括号
    在解释组合说明符时, 标识符右边的方括号和圆括号优先于标
识符左边的“*”号,而方括号和圆括号以相同的优先级从左到右结
合。但可以用圆括号改变约定的结合顺序。
6. 阅读组合说明符的规则是“从里向外”。
    从标识符开始,先看它右边有无方括号或园括号,如有则先作出
解释,再看左边有无*号。 如果在任何时候遇到了闭括号,则在继续
之前必须用相同的规则处理括号内的内容。例如:    int*(*(*a)())[10]
       ↑ ↑↑↑↑↑↑
        7  6 4 2 1 3 5
上面给出了由内向外的阅读顺序,下面来解释它:
(1)标识符a被说明为;
(2)一个指针变量,它指向;
(3)一个函数,它返回;
(4)一个指针,该指针指向;
(5)一个有10个元素的数组,其类型为;
(6)指针型,它指向;
(7)int型数据。
    因此a是一个函数指针变量,该函数返回的一个指针值又指向一
个指针数组,该指针数组的元素指向整型量。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -