zoukankan      html  css  js  c++  java
  • C:指针

    知识点

    指针运算

    1、取地址运算&和去内容运算*

    2、指针与整数的加减运算

    3、指针相减运算

    4、指针关系运算

    指针与结构数组

    //定义结构体类型
    struct info
    {
        short num;
        char name[5];
    };
    
    //定义指向info结构体的指针
    struct info *p_info;
    
    //定义结构体变量
    struct info myinfo;
    
    //初始化指针
    p_info = &myinfo;
    

    字符串指针

    1、指向字符数组的指针

     

    2、指向字符串常量的指针

     

    指针数组

     

    指向指针的指针

    又叫做“指针型指针”

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int *q,**p;
        int x = 1;
        q = &x;
        p = &q;
        printf("q = %x
    ",q);
        printf("*q = %d
    ",*q);
        printf("p = %x
    ",p);
        printf("*p = %x
    ",*p);
        printf("**p = %d",**p);
        return 0;
    }

     用指针型指针输出数组元素:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int a[5] = {1,2,3,4,5};
        int *num[5] = {&a[0],&a[1],&a[2],&a[3],&a[4]};
        int **p,i;
        p =num;
        for(i = 0;i < 5;i++)
        {
            printf("%d	",**p);  //输出:1       2       3       4       5
            p++;
        }
        return 0;
    }

    习题

    1、 请指出以下程序段中的错误。

    程序中的错误有:
    (1)p=i:类型不匹配。
    (2)q=*p:q 是指针,*p 是指针 p 指向变量的值。
    (3)t='b':t 是指针类型。

    解释:指针变量是一种存放地址的特殊变量,其特殊性表现在类型和值上。指针变量的
    类型是指针变量所指向的变量的类型,而不是自身的类型。指针变量赋值应该是地址值

    正确程序应为:

    main ()
    {
      int i,j,*p,*q;
      char ch1,ch2,*t,*s;
      i=3;
      p=&i;
      j=*p/2+10;
      q=p;
      ch1='a';
      s=&ch1;l
      *s='c';
      *t='b';
      ch2=*t;
    }

    2、以下程序的输出结果是什么?

    main()
    {
      char *point[]={"one","two","three","four"};
      while(*point[2]!='')
      printf("%c",*point[2]++);
    }

    答:输出结果是 three。
    结果分析:指针数组是指数组的每一个元素都是一个指针变量的数组, 定义了指针数组 pd,它由 pd[0]~pd[3]4 个数组元素组成。 

    main()
    {
      char *point[]={"one","two","three","four"};
      point[2]=point[0];
      printf("%s",point[2]++);
    }

    答:输出结果是 one。

    3、请对以下程序进行修改,用指针完成对数组元素的访问:

    main()
    {
      int data[12]={12,34,56,12,34,56,3,54,6,7,89,12};
      int i,sum;
      sum=0;
      for(i=0;i<12;i++)
      sum+=data[i];
      printf("The sum is %d
    ",sum);
    }

    算法分析:本题需要抓住数组和指针的联系,讨论数组时,对数组元素的访问是采用的
    下标法,即是以数组的下标来确定数组元素的。在引入指针变量后,我们可以利用一个指向
    数组的指针来完成对数组元素的存取操作及其他运算,这种方法称为指针法
    修改后的程序为:

    #include<stdio.h>
    
    main ()
    
    {
      int data[12]={12,34,56,12,34,56,3,54,6,7,89,12};
      int i,sum;
      int *p;  //定义指针
      sum=0;
      p=data;   //指针赋值
      for (i=0;i<12;i++)
      {
        sum+=*p;
        p++;
      }
      printf("The sum is %d
    ",sum);
    }

    4、指出并更正以下程序的错误。

    main ()
    {
      char data[]="There are some mistakes in the program";
      char *point;
      char array[30];
      int i,length;
      length=0;
      while(data[1ength]!='')
        length++;
      for(i=0;i<length;i++,point++)
        *point=data[i];
        array=point;
      printf("%s
    ",array);
    }

    经过分析,我们可以看出程序的目的是将这个字符串输出,原程序中的主要错误是在
    针运算前没有赋初始地址,于是进行以下修改:

    #include<stdio.h>
    main()
    {
    
      char data[]="there are some mistakes in the program";
      char *point;
      char array[100];//定义一个数组
      int i,length;
      length=0;
      while(data[length]!='')//求字符串的长度
        length++;
      point=array;//给指针赋首地址,主要修改部分
      for(i=0;i<=length;i++,point++)//输出字符串
        *point=data[i];
      printf("%s
    ",array);
    }

    5、编写一个程序输入两个字符串 string1 和 string2,检查在 string1 中是否包含有 string2。如果有,则输出 string2 在 string1 中的起始位置;如果没有,则显示“NO”;如果 string2在 string1 中多次出现,则输出在 string1 中出现的次数以及每次出现的起始位置,

    例如:stringl="the day the month the year"; 

       string2="the"

    输出结果应为:出现三次,起始位置分别是:0,8,18
    又如:
      stringl="aaabacad"
      string2="a"
    输出结果应为:出现五次,起始位置分别是 0,1,2,4,6

    算法分析:

    (1)本题需要对两个字符串进行循环,但与普通循环不同的是,这两个循环并不
    是同时进行的。string1 开始循环后,string2 并不一定开始循环,而是需要判断 string2 的首
    字母是否和 string1 中循环到的字母相同,如果相同,则两个字符串开始同时循环,并记录
    下开始的位置,然后判断 string2 中后面的字母是否和 string1 中的相同,相同则继续,不同
    则停止,直到 string2 循环完成。此时用当前的位置减去 string2 的长度就是 string2 的起始位
    置。

    (2)在本题中,还需要注意的是,由于 string2 可能多次出现,所以需要一个数组来保存多
    次出现的位置。

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    void main()
    {
        char string1[100],string2[10];  // 定义数组存储两个字符串,暂定第一个在 100 内,第二个在 10 内
        char *p,*q;   //定义指针遍历字符串
        int locat[10];  //定义数组保存出现的位置
        int j,len2 = 0,i = 0,posit = 0;  //len2 表示第二个字符串的长度
    
        printf("请输入字符串1:
    ");
        gets(string1);
        printf("请输入字符串2:
    ");
        gets(string2);
    
        q = string2;
        // 求第二个字符串的长度
        for(j = 0;*q != '';j++,q++)
        {
            len2 = j + 1;
        }
        p = string1;  //指针赋首地址
        q = string2;
        //循环进行判断
        do
        {
            // 字符不相同的情况
            if(*p != *q)
            {
                p++;
                posit++;
            }
            // 第一个字符相同,继续对后面字符进行判断
            else
            {
                while((*q != '') && (*q == *p))
                {
                    q++;
                    p++;
                    posit++;
                }
                // 第二个字符串循环结束
                if(*q == '')
                {
                    locat[i] = posit - len2;
                    i++;
                }
            }
            q = string2;
        }while(*p != '');
    
        printf("字符串1:%s
    字符串2:%s
    ",string1,string2);
        printf("出现%d次,起始位置分别是:",i);
    
        //输出位置
        for(j = 0;j < i;j++)
        {
            printf("%d	",locat[j]);
        }
    }

    程序分析:q=string2 这句的作用是什么呢?是保证 q 循环后能再次初始化,这样才能
    进行多次判断,并且防止错误。例如:q 和 p 的第 1 个、第 2 个字符相同,但第 3 个不同,
    此时 q 指针已经指向了第 3 个字符,如果不再次初始化,下一步比较就将从 q 的第 3 个字符
    开始,出现错误。

    6、给定一个整数数组:num[]={23,45,345,23};请定义一个指针变量 point,并令它指向数组的第一个元素,然后回答以下问题:

    (1) num[2]的值等于什么?
    (2) *(point+2)的值等于什么?
    (3) *++point 的值等于什么?

    答: 

    int *p = num; 

    (1)345,即是数组的第 3 个元素。
    (2)345,指针指向了数组的第 3 个元素。
    (3)45,指针指向了数组的第 2 个元素。

    7、【不太懂】编制一个程序显示内存中一片存储区域的内容

    #include <stdio.h>
    #include <stdlib.h>
    
    void main()
    {
        char *point;
        long int b_addr,e_addr,i,j;
    
        printf("请输入起始地址和结束地址:
    ");
        scanf("%lx%lx",&b_addr,&e_addr);
        for(i = b_addr;i < e_addr;i+=16)
        {
            printf("%05lx:",i);
            point = (char*)i;
            for(j = 0;j < 16;j++)
            {
                if(j == 8)
                {
                    printf(" ");
                }
                printf("%02x",*point);
                point++;
            }
            printf("
    ");
        }
    }

    现令其按 ASCII 码的方式显示内存单元的内容:

    #include <stdio.h>
    #include <stdlib.h>
    
    void main()
    {
        char *point;
        long int b_addr,e_addr,i,j;
        printf("please enter the beginning and the end addr in hex
    ");
        scanf("%lx%lx",&b_addr,&e_addr);
        for(i=b_addr; i<e_addr; i+=16)
        {
            printf("%05lx: ",i);  // 宽度为5,的长十六进制的数输出  ???
            point=(char*)i;
            for(j=0; j<16; j++)
            {
                if(j==8)
                    printf(" ");
                printf("%3d ",*point);
                point++;
            }
            printf("
    ");
        }
    }

    8、编写程序输入一个字符串,分别统计输出该字符串中的字母个数和数字个数。

    算法分析:

      判断字母和数字的核心方法是依靠 ASCII 码进行,所以对字符串中的每个
    字符逐个判断即可得到结果。实现方法依然是依靠指针。

    代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    void main()
    {
        char str[100];  //定义一个数组存储字符串
        char *p;
        int n_count=0,c_count=0;
        p=str;
        printf("请输入一个字符串:
    ");
        gets(str); //输入字符串
        do
        {
            if((*p>='0')&&(*p<='9'))//判断数字
                n_count++;
            if((*p>='a')&&(*p<='z'))//判断小写字母
                c_count++;
            if((*p>='A')&&(*p<='Z'))//判断大写字母
                c_count++;
            p++;
        }while(*p!='');
        printf("字符串%s 中的字母个数是:%d,数字个数是%d",str,c_count,n_count);
    }

    程序分析:本题需要注意的有两点:

      1.char 类型的变量,初学者往往理解为是不能直接比较大小的,【自动转换】实际上直接比较大
    小时,是将类型转换为了 int 后比较的 ASCII 码值。这样的方法相对与手动转换为 ASCII
    码比较而言更加高效和方便。
      2.字母包含大小写,这点容易遗漏,在程序设计时应该考虑更全面。

    另外,这道题还可以扩展为求数字、字母和其他字符的数量:

    #include <stdio.h>
    #include <stdlib.h>
    
    void main()
    {
        char str[100];//定义一个数组存储字符串
        char *p;
        int n_count=0,c_count=0,o_count = 0;
        p=str;
        printf("请输入一个字符串:
    ");
        gets(str);//输入字符串
        do
        {
            if((*p>='0')&&(*p<='9'))//判断数字
                n_count++;
            else if(((*p>='a')&&(*p<='z')) || (*p>='A')&&(*p<='Z')) //判断字母
                c_count++;
            else         //判断其他字符
                o_count++;
            p++;
        }while(*p!='');
        printf("字符串%s 中的字母个数是:%d,数字个数是%d, 其他字符个数是: %d",str,c_count,n_count,o_count);
    }

    9、以下程序的输出结果是什么?

    main()
    {
      char *point[]=
      {
        "111111111",
        "222222222",
        "333333333",
        "444444444",
        "555555555"
      };
      int i,j;
      for(i=1;i<3;i++)
      {
        for(j=1;j<5;j++)
          printf("%c",*(point[j]+i));
        printf("
    ");
      }
    }

    答:

    输出结果为:2 3 4 5
          2 3 4 5

    10、编写一个程序,输入两个字符串,比较它们是否相等。

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        char str1[100],str2[100];
        char *p,*q;
    
        printf("请输入第一个字符串:
    ");
        gets(str1);
        printf("请输入第二个字符串:
    ");
        gets(str2);
    
        p=str1;
        q=str2;
    
        if(*p!=*q)
            printf("两个字符串不相等。");
        else
        {
            while((*p==*q)&&(*p!='')&&(*q!=''))//循环判断是否每个字符相等
            {
                p++;
                q++;
            }
            if((*p=='')&&(*q==''))
                printf("两个字符串相等:");
            else
                printf("两个字符串不相等:");
        }
    } 
  • 相关阅读:
    pdf文件预览实现
    RPC failed; curl 56 OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 10054 问题解决
    Git、GitHub、GitLab三者之间的联系及区别(转)
    html中:befoer和:after用法(转)
    html中box-shadow用法(转)
    js/vue实现滑块验证(方法3)
    vue实现滑块验证(使用awsc实现)(方法1)
    js/vue实现滑块验证(组件形式,可重复调用)(方法2)
    js实现图片上传
    【英语】IT English (随时更新...)
  • 原文地址:https://www.cnblogs.com/pam-sh/p/12381255.html
Copyright © 2011-2022 走看看