zoukankan      html  css  js  c++  java
  • 12天学好C语言——记录我的C语言学习之路(Day 12)

    12天学好C语言——记录我的C语言学习之路

    Day 12:

    进入最后一天的学习,用这样一个程序来综合考量指针和字符串的关系,写完这个程序,你对字符串和指针的理解应该就不错了。

    //输入一个字符串,内有数字和非数字字符,如:A123x456 17234?532tab32622,然后将,123,456,17234,532,32622这些被非数字字符分割开的数字找出来,输出这些数。
    //此程序的关键点在于遇到需要输出的字符就记录下来,然后判断他的下一个字符是不是有效字符,有效则不做判定继续执行有效字符的记录工作,如果遇到无效字符,那么这时候就要输出 从记录的第一个字符开始到这个无效字符的前一个字符 之间的所有字符。我们记录的正是这一段有效字符的个数(用k记录),也正是这段字符的首、尾地址的差,然后用指针变量指向首地址,依次输出地址里面的值。
    //当然,我输出的形式还是char,如果题目要求读者将分割开来的数用int型输出,那么不妨将每一个字符都做一个这样的处理,比方说第一个分割出来的数是123,这时的123是字符'1'字符'2'和字符'3',另外我们知道这时的 k=3 ,我们可以用
    //   ('1'-'0')*pow(10,k-1)+('2'-'0')*pow(10,k-2)+('3'-'0')*pow(10,k-3) 来表示,这里的重点在于字符型数字如何转化成整型的数字,用到的是 这个数字字符 和 数字字符'0' 之间的距离正好就是 这个数字字符 的 值。另外,这里的k-1,k-2,k-3可以用k-i来表示,i的范围是1~k

    /*//program 12.1
    #include<stdio.h>
    #include<string.h>
    int main()
    {
        char a[]="A123x456 17234?532tab32622";
        void search(char *);
        search(a);
        return 0;
    }
    void search(char *a)
    {
        char *p1=a;
        long length=strlen(a);
        int i=0,k=0,sum=0;
        for (;i<length; i++) {
            p1=a+i;
            if (*p1>48&&*p1<57) {
                k++;
                if (*(p1+1)<48||*(p1+1)>57) {
                    for (int j=0; j<k; j++) {//这个和下面的程序就略有不同了,这里每次分割完一个数字,就将k初始化为0,而且每次用到j的时候也都是从0开始使用的。所以结果也是正确的
                        printf("%c",*(p1-k+1+j));
                    }
                    k=0;
                    printf(" ");
                    sum++;
                }
            }
        }
        printf(" 共有%d个数字被分割",sum);
    }
    */


    如果你上面的程序会了,那么你试着做一做下面这个题。

    //55234152349555098958788955584  分割这样一串数字,要求是用5分割,如将左边的一串数字分割成
    //55 2341 5 2349 555 0989 5 87889 555 84  然后最后得到的结果为2341 2349 0989 87889 84

    /*//program 12.2
    #include <stdio.h>
    #include <string.h>
    int main()
    {
        char a[]="55234152349555098958788955584";
        void search(char *);
        search(a);
        return 0;
    }

    void search(char *p){
        long length=strlen(p);
        int i=0,k=0,j=0,sum=0;
        for (; i<length; i++) {
            if (*(p+i)!='5') {
                k++;
                if (*(p+i+1)=='5'||*(p+i+1)=='') {//这里必须加上空值,因为上面不是5结尾的
                    for (; j<k; j++) {
                        printf("%c",*(p+i-k+1+j));//这个地方是一个比较逗B的巧合,因为我们在输出第一个分割出来的数字时,k和j都没有归0,那么如上面的一串数字,在输出第二个数字的时候,k是从5开始的(因为第一个分割出来的数字有4位,也就是k=4),那么等第二个数字遍历完毕时,k应该变成了8(同理,第二个分割出来的数字也是有4位的)。再看j,第一次分割结束的时候跳出for循环的时候j做了一次j++,那么j的值就和k当时的值是一样的,所以j在进入第二个分割数的for循环的时候j应该是4,而不是0,那么第二次分割出来的数字的首字符应该是*(p+10-8+1+4),也就是*(p+7),正好就是数字2349中2的地址。这个地方可以说是误打误撞,读者可能在看这个地方的时候看不懂是怎么得到的正确结果。
                    }
                    sum++;
                    printf(" ");
                }
            }
        }
        printf(" 共有%d个数字被分割",sum);
    }
    */

    好了指针部分也差不多结束了,敲了不少程序,希望大家能够准确理解指针~

    接下来转入结构体,也是最后一个环节的学习。

    //结构体类型事实上和int,char,float类型都大同小异,只不过结构体类型是我们自己定义的类型。结构体类型和结构体变量不是一回事,我们知道只能对变量赋值,存取或者运算,而不能对类型如此,类型是不需要分配空间的,只能对变量分配空间。
    //定义结构体类型的格式:      struct 结构体名{ 成员表列 };     注意在声明结构体类型的时候要最后加上分号。
    //当然在声明结构体类型的同时可以定义变量:      struct 结构体名{ 成员表列 } 变量名表列;
    //另外要注意的是结构体类型中的成员名和程序中的变量名如果相同,但二者不代表同一对象的,是两回事,互不干扰

    //定义Student结构体类型,然后将一个同学信息(学号,姓名,性别,住址)放在一个结构体变量中,然后输出该学生的成绩。

    /*//program 12.3
    #include "stdio.h"
    int main()
    {
        struct Student
        {
            int number;
            char name[20];
            char sex[20];//注意,如果在结构体类型中有成员是字符串形式的,那么这里要将成员定义成字符数组的形式
            char addr[30];
        };
        struct Student a={123456,"wangzhongyao","man","shandongshengjinanshi"};//这里是先声明结构体类型,然后再定义结构体变量a,分开进行。下面给出在结构体类型声明的同时定义变量的情况。
        printf("No.%d name:%s sex:%s address:%s ",a.number,a.name,a.sex,a.addr);//这里输出的并不是a,而是a的各个属性,我们输出的是a的详细信息,所以要用  a.变量名  来输出。这里很重要。
        return 0;
    }
    */

    //还是上面的程序,在结构体类型声明的同时定义结构体变量。

    /*//program 12.4
    #include<stdio.h>
    int main()
    {
        struct Student
        {
            int number;
            char name[20];
            char sex[10];
            char addr[30];
        }
        a={123,"maxingze","man","jiningshilaozhaizhen"},b={1234,"yuetianhao","man","jiningshijiaxiangxian"};
        //这里注意,在结构体类型声明的同时定义结构体变量的话,要把结构体变量定义在结构体类型声明时最后一个分号的前面!!!!!这里一定要注意哦!!!
        printf("No.%d name:%s sex:%s addr:%s ",a.number,a.name,a.sex,a.addr);
        printf("No.%d name:%s sex:%s addr:%s ",b.number,b.name,b.sex,b.addr);
        return 0;
    }
    */

    /*//program 12.5
     //对结构体类型中某一成员进行初始化(不完全初始化成员),其余未被初始化的成员是什么情况?下面给出解答。
    #include<stdio.h>
    int main()
    {
        struct Student
        {
            int card;
            char name[10];
            char sex[10];
            char bumen[20];
        }
        a={.name="man"};//允许对结构体中的某一成员初始化,其他 未被初始化的 数值型成员 被初始化为0,未被初始化的 字符型成员 被初始化为'',未被初始化的 指针型成员 被初始化为NULL。这里必须要牢记!!!!!!!
        printf("Card:%d name:%s sex:%s bumen:%s ",a.card,a.name,a.sex,a.bumen);
        return 0;
    }
    */

    /*//program 12.6
    //结构体变量之间可以互相赋值
    #include <stdio.h>
    int main()
    {
        struct Student
        {
            int card;
            char name[10];
            char sex[10];
        }
        a={123,"a","man"},b={321,"b","woman"};//在结构体类型声明的时候定义变量,要注意定义多个变量的时候中间用','隔开,在最后的一个变量定义结束时加一个';'即可,当然最后加很多';'也没有错误(验证得到)。
        a=b;//同类型结构体变量之间可以相互赋值(如:   a=b;),同样同类型结构体变量中相同成员也可以互相赋值(如:   a.card=b.card;)
        printf("card:%d name:%s sex:%s ",a.card,a.name,a.sex);
        return 0;
    }
    */

    //注意不能用以下语句整体读入结构体变量
    //scanf("%d,%s,%s ",&a);   因为结构体变量的地址主要用作函数参数,传递结构体变量的地址。(这句话需要读者好好理解!!!)
    //那应该怎么读入结构体变量呢? 显然要将结构体变量中每一个成员 分别 读入,如下:
    //scanf("%d,%s,%s ",&a.card,&a.name,&a.sex);

    //输入两个学生的学号、姓名和成绩,输出成绩较高的学生的学号、姓名和成绩
    //下面的题目中没有写两个学生成绩相等的情况,读者可以自行加上

    /*//program 12.7
    #include "stdio.h"
    int main()
    {
        struct Student
        {
            int number;
            char name[20];
            int grade;//成绩是一个整数,这里不要错误的声明为数组类型
        }
        a,b;
        printf("请输入两个学生的学号、姓名、成绩: No.1: ");
        scanf("%d%s%d",&a.number,a.name,&a.grade);
        //scanf(格式控制,地址表列);  这里的地址表列可以是变量的地址,也可以是字符串的首地址。(这句话很重要,在上面一句输入语句中,只有a.name没有加'&'号,这是因为name为数组名,代表了字符串数组的首地址,所以说a.name就是一个地址,所以不用再加'&'了)
        printf("No.2: ");
        scanf("%d%s%d",&b.number,b.name,&b.grade);
        if (a.grade>b.grade) {
            printf("number:%d name:%s grade:%d ",a.number,a.name,a.grade);
        }
        else
        {
            printf("number:%d name:%s grade:%d ",b.number,b.name,b.grade);
        }
        return 0;
    }
    */

    /*//program 12.8
    //有3个候选人,编一个统计选票的程序,先后输入备选人的名字,然后输出个人选票结果
    #include <stdio.h>
    struct Person
    {
        char name[20];
        int count;
    }lead[3]={"ma",0,"wang",0,"zheng",0};
    int main()
    {
        char lead_name[20];//声明一个字符数组,用来存放下面10次投票时 每一次 投票的人选姓名
        printf("请投票10次: ");
        for (int i=0; i<10; i++) {
            scanf("%s",lead_name);//这里的lead_name就是数组名,表示的就是这个字符串的首地址。i=10,所以这里要输入10个字符串,分10次输入,下面调用strcmp函数就是将 每一次 投票的任选姓名和候选名单中的三个姓名比较,如果一样,那么结构体变量中的count成员就+1 。
            for (int j=0; j<3; j++) {
                if (strcmp(lead_name,lead[j].name)==0)//这里为什么能用lead_name呢?这个不是地址么,这里应该是比较两个字符串的值把? 记住就好了,字符数组,用数组名来比较即可
                {
                    lead[j].count++;
                }
            }
        }
        for (int i=0; i<3; i++) {
            printf("%s:%d ",lead[i].name,lead[i].count);
        }
        return 0;
    }
    */

    //定义结构体数组的一般形式是
    // struct 结构体名 { 成员表列 } 数组名[数组长度] ;
    //或者是先声明一个结构体类型,然后再定义结构体数组,在已经声明好结构体类型的情况下我们可以这样定义:
    //结构体类型 数组名[数组长度]={初值表列};  (如:  struct Person a[3]={"ma",0,"wang",0,"zheng",0};  )

    //有n个学生的信息(学号、姓名、成绩),要求按照成绩的高低顺序输出各学生的信息
    /*//program 12.9
    #include "stdio.h"
    struct Student
    {
        int number;
        char name[20];
        int grade;
    };
    void change(struct Student *a,int n)
    {
        struct Student temp;//这里的temp和上面数组中的成员是一样的类型,用来在下面排序时作交换的。
        int i,j,k;
        for (i=0; i<n-1; i++) {
            k=i;
            for (j=i+1; j<n; j++) {
                if (a[k].grade<a[j].grade) {
                    k=j;
                }
            }
            temp=a[k];
            a[k]=a[i];
            a[i]=temp;
        }
        for (i=0; i<n; i++) {
            printf("number:%d name:%s grade:%d ",a[i].number,a[i].name,a[i].grade);
        }
    }
    int main()
    {
        struct Student ss[]={1001,"wang",98,1002,"ma",99,1003,"zheng",87,1004,"yue",89,1005,"zhang",100};
        void change(struct Student *a,int n);
        change(ss,5);
        return 0;
    }
    */

    //结构体指针。通过 指向 结构体变量 的指针 来访问 结构体变量 中的 成员。
    //首先我们要知道,这个结构体指针是指向结构体变量的,然后再通过指针去访问结构体变量的成员。
    //结构体指针其实和普通指针差不多,就是指向的结构体变量,而且多了一种形式(p->number)。

    /*//program 12.10
    #include "stdio.h"
    #include "string.h"
    struct Student
    {
        int number;
        char name[30];
        char sex[10];
        int grade;
    };
    int main()
    {
        struct Student a;
        a.number=1001;
        strcpy(a.name,"Xingze Ma");//这里需要注意一下,如果不是直接对整个结构体变量初始化,而是对其中一个一个成员分别初始化,那么在初始化字符数组成员的时候(也就是需要初始化一个字符串),需要用到strcpy函数,这个函数是复制字符串的。对于字符串的赋值,不能说char a[10];  a=“123”; 这样错误。 对于字符串赋值,要么在声明的初始化(char a[10]=“123”;),要么用scanf函数给字符串输入值,要么就要用strcpy函数复制字符串,而也是本题中用的方法,也最为常用
        strcpy(a.sex,"gay");
        a.grade=59;
        struct Student *p;
        p=&a;
        printf("number:%d name:%s sex:%s grade:%d ",(*p).number,(*p).name,(*p).sex,(*p).grade);
        //'.'运算符优先于'*'运算符,所以这里必须加括号(*p)
        printf("number:%d name:%s sex:%s grade:%d ",p->number,p->name,p->sex,p->grade);
        //为了方便,允许把 (*p).number 用 p->number 来代替,含义是p所指向的 结构体变量 中的 number成员
        //所以以下3种情况是等价的
        //struct Student a;    struct Student *p=&a;
        //①a.number ②(*p).number ③p->number
        return 0;
    }
    */

    //指向结构体数组的指针
    //和指向一般数组的指针也别无二致,就是指向结构体数组的首地址即可

    /*//program 12.11
    #include "stdio.h"
    struct Student
    {
        int card;
        char name[20];
        char sex[20];
    }
    a[]={{1001,"wang","man"},{1002,"ma","woman"},{1003,"zheng","gay"}};
    int main()
    {
        struct Student *p=a;
        for (; p<a+3; p++) {//这里无论是什么情况下在for循环中用指针,这是p<a+3,而不是p<p+3 , 牢记!!!!
            printf("card:%d name:%s sex:%s ",p->card,(*p).name,p->sex);
        }
        return 0;
    }
    */


    //用 结构体变量 和 结构体变量的指针 作函数参数
    //有n个结构体变量,内含学生学号、姓名和3门课程的成绩。要求输出平均成绩最高的学生的信息。

    /*//program 12.12
    #include "stdio.h"
    #define N 3
    struct Student
    {
        int num;
        char name[20];
        float score[3];
        float aver;
    };

    void scanf1(struct Student ss[])
    {
        printf("请输入各学生信息: ");
        for (int i=0; i<N; i++) {
            scanf("%d%s%f%f%f",&ss[i].num,&ss[i].name,&ss[i].score[0],&ss[i].score[1],&ss[i].score[2]);
            ss[i].aver=(ss[i].score[0]+ss[i].score[1]+ss[i].score[2])/3;
        }
    }

    struct Student max(struct Student ss[])
    {
        float max=ss[0].aver;
        int k=0;
        for(int i=1;i<N;i++)
        {
            if(max<ss[i].aver)
            {
                max=ss[i].aver;
                k=i;
            }
        }
        return ss[k];
    }

    void print(struct Student s)
    {
        printf("成绩最好的学生是: %d %s %5.2f %5.2f %5.2f",s.num,s.name,s.score[0],s.score[1],s.score[2]);
    }

    int main()
    {
        void scanf1(struct Student ss[]);//这里要传入结构体数组中数组元素,因为我们比较好几个学生的平均成绩,自然要准备一个数组存放它们
        struct Student max(struct Student ss[]);
        void print(struct Student s);
        struct Student s[N];
        scanf1(s);//这里传进去的是数组s[N]的首地址,所以这里我们也可以用指针操作,可以定义一个结构体指针指向s[N],然后调用函数的时候用p来调用,其作用是一样的
        print(max(s));
        //struct Student q;
        //q=max(p);
        //print(q);
        return 0;
    }

    */

    program 12.12 将我们学过的知识基本上汇合了一下,我们的学习也就到此结束了,短短12天,学到的东西很多,我只把C语言部分介绍到结构体,剩下还有一些结构体和链表、共用体类型、文件读写等等部分我就不一一介绍了。时间有限,由读者自行学习。希望读者能学习到一些知识,那么我写的这几篇连载博客也就有价值了。希望大家学习愉快!


                                   

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    BZOJ1027 [HNOI2004]打鼹鼠 【dp】
    面试的绝招(V1.0)
    面试的绝招(V1.0)
    Google是如何做测试的?
    Google是如何做测试的?
    Google是如何做测试的?
    六年测试之精华分享:产品质量应从哪些方面提高
    六年测试之精华分享:产品质量应从哪些方面提高
    六年测试之精华分享:产品质量应从哪些方面提高
    拒绝混乱,回归有序
  • 原文地址:https://www.cnblogs.com/wzy294250051/p/4787903.html
Copyright © 2011-2022 走看看