指针数组

        http://www.bc-cn.net/Article/kfyy/cyy/jc/Index.html

前面介绍了指向不同类型变量的指针的定义和使用,我们可以让指针指向某类变量,并替代该变量在程序中使用;我们也可以让指针指向一维、二维数组或字符数组,来替代这些数组在程序中使用,给我们在编程时带来许多方便。
    下面我们定义一种特殊的数组,这类数组存放的全部是指针,分别用于指向某类的变量,以替代这些变量在程序中的使用,增加灵活性。指针数组定义形式:
        类型标识*数组名[数组长度]
例如: char *str[4];
    由于[ ] 比*优先权高,所以首先是数组形式str[4 ],然后才是与“*”的结合。这样一来指针数组包含4个指针s t r [ 0 ]、s t r [ 1 ]、s t r [ 2 ]、s t r [ 3 ],各自指向字符类型的变量。例如: int *
p t r [ 5 ] ;
      该指针数组包含5个指针p t r [ 0 ]、p t r [ 1 ]、p t r [ 2 ]、p t r [ 3 ]、p t r [ 4 ],各自指向整型类型的变量。
[例6-22] 针对指针数组的应用,我们分别用指针数组的各指针指向字符串数组、指向一维整型数组、指向二维整型数组。
#include <stdlib.h>
#include <stdio.h>
m a i n ( )
{
     char *ptr1[4]={"china","chengdu","sichuang","chongqin"};
    /* 指针数组p t r 1 的4个指针分别依此指向4个字符串* /
    int i,*ptr2[3],a[3]={1,2,3},b[3][2]={1,2,3,4,5,6};
    for(i=0;i<4;i++)
        printf("/n%s",ptr1[i]);/依*此输出ptr1数组4个指针指向的4个字符串*/
    printf("/n");
    for(i=0;i<3;i++)
        ptr2[i]=&a[i];/*将整型一维数组a的3个元素的地址传递给指针数组ptr2*/
    for(i=0;i<3;i++)/*依此输出ptr2所指向的3个整型变量的值*/
        printf("%4d",*ptr2[i]);
    printf("/n");
    for(i=0;i<3;i++)
        ptr2[i]=b[i];/*传递二维数组b的每行首地址给指针数组的4个指针*/
    for(i=0;i<3;i++)/*按行输出*/
        printf("%4d%4d/n",*ptr2[i],*ptr2[i]+1);
}
程序中指针数组与所指对象的关系如图6-12所示。

        ptr1指针数组中的4个指针分别指向4个字符串,如图6-11的a)所示,程序中依此输出;ptr2指针数组共有3个指针,若将整型一维数组a中各元素地址分别传递给指针数组的各指针,则ptr2[0]就指向a[0];ptr2[1]就指向a[1];ptr2[2]就指向a[2]。若将二维数组各行的首地址分别传递给指针数组的各指针,如图6-11b)所示,这样一来,ptr2[0]就指向了b数组的第0行,该行有两个元素,其地址为ptr2[0]与ptr2[0]+1;相应指针数组第i个元素ptr2[i]指向的b数组的第i行两个元素地址分别为ptr2[i]与ptr[i]+1。

        在处理二维字符数组时,我们可以把二维字符数组看成是由多个一维字符数组构成,也就是说看成是多个字符串构成的二维字符数组,或称为字符串数组。
指针数组对于解决这类问题(当然也可以解决其它问题)提供了更加灵活方便的操作。
有一点需要说明,若定义一个指针数组后,指针数组各元素的取值(即地址)要注意安全性。
如定义指针数组:
        char*ptr[3];
        我们说该数组包含三个指针,但指针的指向是不确定的,指针现在可能指向内存的任一地址。假定现在作语句:scanf("%s",ptr[i]),则输入的字符串在内存的存放其地址由ptr[i]决定。除非给指针数组元素赋值安全的地址。
[例6-23]定义字符指针数组,包含5个数组元素。同时再定义一个二维字符数组其数组大小为5*10,即5行10列,可存放5个字符串。若将各字符串的首地址传递给指针数组各元素,那么指针数组就成为名副其实的字符串数组。下面对各字符串进行按字典排序。
        在字符串的处理函数中,strcmp(str1,str2)函数就可以对两个字符串进行比较,函数的返回值>0、=0、<0分别表示串str1大于str2、str1等于str2、str1小于str2。再利用strcpy()函数实现两个串的复制。下面选用冒泡排序法。
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
main()
{
        char*ptr1[4],str[4][20],temp[20];
        /*定义指针数组、二维字符数组、用于交换的一维字符数组*/
        inti,j;
        for(i=0;i<4;i++)
            gets(str[i]);/*输入4个字符串*/
        printf("/n");
        for(i=0;i<4;i++)
            ptr1[i]=str[i];/*将二维字符数组各行的首地址传递给指针数组的各指针*/
        printf("original string:/n");
        for(i=0;i<4;i++)/*按行输出原始各字符串*/
            printf("%s/n",ptr1[i]);
        printf("ordinal string:/n");
        for(i=0;i<3;i++)/*冒泡排序*/
        for(j=0;j<4-i-1;j++)
        if(strcmp(ptr1[j],ptr1[j+1])>0)
            {strcpy(temp,ptr1[j]);
        strcpy(ptr1[j],ptr1[j+1]);
        strcpy(ptr1[j+1],temp);
}
for(i=0;i<4;i++)/*输出排序后的字符串*/
        printf("%s/n",ptr1[i]);
}

        程序中一定要注意指针的正确使用。一旦将二维字符数组的各行首地址传递给指针数组
的各指针,则相当于给指针分配了安全可操作的地址,地址空间大小由二维字符数组来决定。
当然也可由编译系统为指针分配地址用于字符串的存放。
[例6-24]利用malloc()函数指针分配存储空间,实现字符串的排序。
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
main()
{
        char *ptr1[4],*temp;
        inti,j;
        for(i=0;i<4;i++)
        {
            ptr1[i]=malloc(20);/*为指针数组各指针分配20字节的存储空间*/
            gets(ptr1[i]);
        }
        printf("/n");
        printf("original string:/n");
        for(i=0;i<4;i++)
            printf("%s/n",ptr1[i]);
        printf("ordinal string:/n");
        for(i=0;i<3;i++)
                for(j=0;j<4-i-1;j++)
        if(strcmp(ptr1[j],ptr1[j+1])>0)
        {
            temp=ptr1[j];/*利用指向字符串的指针,进行指针地址的交换*/
            ptr1[j]=ptr1[j+1];
            ptr1[j+1]=temp;
        }
        for(i=0;i<4;i++)/*字符串输出*/
              printf("%s/n",ptr1[i]);
}
运行程序,其结果与上述例6-23完全相同。

          [例6-25]对已排好序的字符 指针数组进行指定字符串的查找。字符串按字典顺序排列,查找算法采用二分法,或称为折半查找。
折半查找算法描述:
1.设按开序(或降序)输入n个字符串到一个 指针数组。
2.设low指向 指针数组的低端,high指向 指针数组的高端,mid=(low+high)/2
3.测试mid所指的字符串,是否为要找的字符串。
4.若按字典顺序,mid所指的字符串大于要查找的串,表示被查字符串在low和mid之间,
否则,表示被查字符串在mid和high之间。
5.修改low式high的值,重新计算mid,继续寻找。
#include<stdlib.h>
#include<alloc.h>
#include<string.h>
#include<stdio.h>
main()
{
        char*binary();/* 函数声明*/
        char*ptr1[5],*temp;
        inti,j;
        for(i=0;i<5;i++)
        {
                ptr1[i]=malloc(20);/*按字典顺序输入字符串*/
                gets(ptr1[i]);
        }
        printf("/n");
        printf("original string:/n");
        for(i=0;i<5;i++)
            printf("%s/n",ptr1[i]);
        printf("input search string:/n");
        temp=malloc(20);
        gets(temp);/输*入被查找字符串*/
        i=5;
        temp=binary(ptr1,temp,i);/*调用查找 函数*/
        if(temp)
                printf("succesful-----%s/n",temp);
        else
                printf("nosuccesful!/n");
        return;
}
char *binary(char *ptr[],char *str,int定n)义返回字符 指针函数*/
{/*折半查找*/
        inthig,low,mid;
        low=0;
        hig=n-1;
        while(low<=hig)
        {
                mid=(low+hig)/2;
                if(strcmp(str,ptr[mid])<0)
                        hig=mid-1;
                elseif(strcmp(str,ptr[mid])>0)
                        low=mid+1;
                else return(str);/*查帐成功,返回被查字符串*/
        }
        return NULL; / *查找失败,返回空 指针* /
}

[例6-26] 在一个已排好序的字符串数组中,插入一个键盘输入的字符串,使其继续保持有序。
在上述程序查找成功的基础上,我们将该字符串插入到字符数组中。插入的位置可以是数组头、中间或数组尾。查找的算法采用折半算法,找到插入位置后,将字符串插入。
#include <stdlib.h>
#include <alloc.h>
#include <string.h>
#include <stdio.h>
m a i n ( )
{
        int binary(); / *查找 函数声明* /
        void insert(); / *插入 函数声明* /
        char *temp,*ptr1[6];
        int i,j;
        for (i=0;i<5;i++)
        {
                ptr1[i]=malloc(20);/*为 指针分配地址后*/
                gets(ptr1[i]);/*输入字符串*/
        }
        ptr1[5]=malloc(20);
        printf("/n");
        printf("original string:/n");
        for(i=0;i<5;i++)/*输出 指针数组各字符串*/
            printf("%s/n",ptr1[i]);
        printf("input search string:/n");
        temp=malloc(20);
        gets(temp);/*输入被插字符串*/
        i=binary(ptr1,temp,5)/*;寻找插入位置i*/
        printf("i=%d/n",i);
        insert(ptr1,temp,5,i);/*在插入位置i处插入字符串*/
        printf("outputstrings:/n");
        for(i=0;i<6;i++)/*输出 指针数组的全部字符串*/
            printf("%s/n",ptr1[i]);
        return;
}
intbinary(char*ptr[],char*str,intn)
{        /*折半查找插入位置*/
            int hig,low,mid;
          low=0;
          hig=n-1;
        if(strcmp(str,ptr[0])<0)return0;
        /*若插入字符串比字符串数组的第0个小,则插入位置为0*/
         if(strcmp(str,ptr[hig])>0)returnn;
        /*若插入字符串比字符串数组的最后一个大,则应插入字符串数组的尾部*/
        while(low<=hig)
        {
            mid=(low+hig)/2;
            if(strcmp(str,ptr[mid])<0)
                    hig=mid-1;
            else if(strcmp(str,ptr[mid])>0)
                    low=mid+1;
            else return(mid);/*插入字符串与字符串数组的某个字符串相同*/
        }
        returnlow;/*插入的位置在字符串数组中间*/
}
void insert(char*ptr[],char*str,intn,inti)
{
        int j;
        for(j=n;j>i;j--)/*将插入位置之后的字符串后移*/
            strcpy(ptr[j],ptr[j-1]);
        strcpy(ptr[i],str);将被插字符串按字典顺序插入字符串数组*/
}
            在程序中,字符串数组的6个 指针均分配存放20字节的有效地址。语句ptr1[5]=malloc(20)保证插入字符串后,也具有安全的存储空间,字符串的长度以串中最长的为基准向系统申请存储空间,以保证在串的移动中有足够的存储空间。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值