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("\n共有%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)=='\0') {//这里必须加上空值,因为上面不是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("\n共有%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\nname:%s\nsex:%s\naddress:%s\n",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\nname:%s\nsex:%s\naddr:%s\n\n",a.number,a.name,a.sex,a.addr);
    printf("No.%d\nname:%s\nsex:%s\naddr:%s\n\n",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,未被初始化的 字符型成员 被初始化为'\0',未被初始化的 指针型成员 被初始化为NULL。这里必须要牢记!!!!!!!
    printf("Card:%d\nname:%s\nsex:%s\nbumen:%s\n",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\nname:%s\nsex:%s\n",a.card,a.name,a.sex);
    return 0;
}
*/

//注意不能用以下语句整体读入结构体变量
//scanf("%d,%s,%s\n",&a);   因为结构体变量的地址主要用作函数参数,传递结构体变量的地址。(这句话需要读者好好理解!!!)
//那应该怎么读入结构体变量呢? 显然要将结构体变量中每一个成员 分别 读入,如下:
//scanf("%d,%s,%s\n",&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("请输入两个学生的学号、姓名、成绩:\nNo.1:\n");
    scanf("%d%s%d",&a.number,a.name,&a.grade);
    //scanf(格式控制,地址表列);  这里的地址表列可以是变量的地址,也可以是字符串的首地址。(这句话很重要,在上面一句输入语句中,只有a.name没有加'&'号,这是因为name为数组名,代表了字符串数组的首地址,所以说a.name就是一个地址,所以不用再加'&'了)
    printf("No.2:\n");
    scanf("%d%s%d",&b.number,b.name,&b.grade);
    if (a.grade>b.grade) {
        printf("number:%d\nname:%s\ngrade:%d\n",a.number,a.name,a.grade);
    }
    else
    {
        printf("number:%d\nname:%s\ngrade:%d\n",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次:\n");
    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\n",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\n",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\nname:%s\nsex:%s\ngrade:%d\n\n",(*p).number,(*p).name,(*p).sex,(*p).grade);
    //'.'运算符优先于'*'运算符,所以这里必须加括号(*p)
    printf("number:%d\nname:%s\nsex:%s\ngrade:%d\n",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\nname:%s\nsex:%s\n\n",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("请输入各学生信息:\n");
    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("成绩最好的学生是:\n%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语言部分介绍到结构体,剩下还有一些结构体和链表、共用体类型、文件读写等等部分我就不一一介绍了。时间有限,由读者自行学习。希望读者能学习到一些知识,那么我写的这几篇连载博客也就有价值了。希望大家学习愉快!


                               
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值