C的实用笔记41——结构体指针引用结构体(变量/数组)

1.结构体指针的概念

1、知识点:

  1. 与变量的两种访问方式一样,结构体变量也有两种访问方式:通过结构体变量名访问,通过结构体变量地址访问。这里结构体变量地址就是结构体指针。
  2. 普通指针可以引用变量,同时普通指针也可以引用一维数组,因为数组的名字就是指针类型的地址常量,也是它第首个元素的地址。类似的,结构体指针可以引用结构体变量,当然结构体指针也可以引用结构体数组,因为结构体数组的名字就是结构体指针类型的地址常量,也是它首个结构体的地址。

2.通过结构体指针间接访问结构体变量

1、标准写法:

  1. 使用剑号运算符"->"。 结构体指针->成员变量。
    #include 
    struct Test
    {
        int idata;
        char cdata;
    };
    int main(int argc, char const *argv[])
    {
        struct Test t1 = {10, 'c'};
        struct Test *ps = &t1;
        printf("t1的idata=%d\n", ps->idata);		//使用剑号运算符"->"读取结构体变量的值
        printf("t1的cdata=%c\n", ps->cdata);
        ps->cdata = '2'; 						//使用剑号运算符"->"修改结构体变量的值
        printf("t1的cdata=%c\n", ps->cdata);
        return 0;
    }

2、啰唆的写法:

  1. 指针取星花,再用点运算符".":不推荐,缺少了对剑号运算符的使用。
        printf("t1的cdata=%c\n", (*ps).cdata);

3.通过结构体指针间接访问结构体数组

1、标准写法:

  1. 结构体指针偏移后用剑号运算符"->"。
    #include 
    struct Student
    {
        int num;
        char name[32];
    };
    int main(int argc, char const *argv[])
    {
        struct Student arr[3] = {
            {1, "张三"},
            {2, "李四"},
            {3, "王五"}
        };
        struct Student *parr = arr;
        int len = sizeof(arr) / sizeof(arr[0]);
        for(int i=0; inum, (parr+i)->name);	 //结构体指针偏移
        }
        return 0;
    }

2、见怪不怪的写法:

  1. 结构体指针下标法,然后用点运算符".",这种方法比较直观,可以在给函数传递结构体数组后使用
        for(int i=0; i

  2. 结构体指针自加,使用的比较多,也比较直观,但是存在缺点(因为对p进行了修改,下次再用容易造成数组越界)。需要每次都让p回到数组头部。
        int i;
    	parr = arr;												      //使用前让指针复位
        for(i=0; inum, parr->name);		//结构体指针自加
            parr++;
        }

  3. 结构体指针偏移后取星花,再使用点运算符"."。不推荐,因为要注意优先级的问题,需要加多个括号,同时缺少了剑号运算符的使用。
        for(int i=0; i

  4. 结构体数组名当做指针来使用。也不推荐用,因为我们终归是使用定义出来的指针,而不是地址常量
        for(int i=0; inum, (arr+i)->name);		
        }

4.习题(函数形参接收结构体数组)

代码心得:

  1. 程序写一部分就编译试一下,不要等到全部写完才编译,否则错误很多看不完,而且有些地方虽然没语法错,但是通过提前测试,可以补充一些细节。
  2. 小技巧,可以根据指针函数返回一个指针类型的数据,从而把函数返回值赋值给指针本身,修改指针自身的值,而不需要通过给函数传递二级指针的方式进行修改。
  3. 可以通过给指针函数传递结构体数组,获取结构体数组中的的某个结构体的的地址。(结构体数组有点像二维数组,但并不是)

习题1:用函数改进选票系统,让程序看起来更整洁。练习结构体指针、结构体数组、指针函数等知识点

  1. 思路:显然选民系统中有三个功能,因此我们将这三个功能写成API。通过想象内存空间,我们可以看出这几个函数都是在对堆区开辟的动态内存(可以看成结构体数组)进行操作。C的实用笔记41——结构体指针引用结构体(变量/数组)_第1张图片 
    声明结构体1: struct Candidate { char name[32]; int tickets; };	代表候选人的名字和得票数
    
    f1. 封装初始化选民信息的API: struct Candidate* initXms(struct Candidate *xm, int len);
    	函数形参接收的是:结构体数组、结构体数组长度的地址; 指针函数,返回结构体数组的首地址
        f1.1 调用断言函数assert,断言xm这个指针没被初始化: assert(xm = NULL);
    	f1.2 调用malloc函数,在堆区开辟一个长度为len的结构体数组,数组中一个元素(结构体)的占用
        空间用sizeof运算符计算,将首地址保存在xm中:
    		xm = (struct Candidate*)malloc(len*sizeof(struct Candidate)); 
    		//内在逻辑:不做free,让结构体数组的生命周期一直到程序结束
    	f1.3 for循环,代表结构体数组下标(第i个选民)的循环变量i从0开始,name);
    	f1.4 返回初始化完毕后的堆区结构体数组的首地址xm
        
    f2. 封装打印选民信息的API: void printXms(struct Candidate *xm, int len);
    	函数形参接收的是:结构体数组、结构体数组长度
    	f2.1 for循环,代表结构体数组下标(第i个选民)的循环变量i从0开始,tickets是否小于xm->tickets
        		f4.2.1.1 如果是,
            				那么,认为xm[i]选民的得票数最多,令: max = xm;
    	f4.3 返回得票数最多人的地址,即max
    
    1. 一开始不知道有几个候选人,需要通过开辟动态内存的方式确定结构体数组,故先定义一个结构体指针:
       struct Candidate *xm = NULL; 	//用NULL防止野指针,并表示xm还没有具体指向
    2. 自定参选的人数,保存在变量len中: scanf("%d%*c", &len);//%*c为了跳过回车,因为后面还要输入
    3. 调用API1. 初始化选民信息,在堆区中开辟一个结构体数组,并把地址保存在xm中:
    	xm = initXms(xm, len);	
    	//内在逻辑:通过指针函数的方式修改指针的值,传递xm是为了判断xm是否是NULL,其实不传递xm也行
    4. 调用API2. 打印投票前的选民信息: printXms(xm, len);
    5. 调用API3. 进入唱票环节: 统计得票数和废票数,将返回的废票数保存在变量invalidTickets中:
    	invalidTickets = doVote(xm, len);
    6. 调用API2. 打印投票后的选民信息: printXms(xm, len);
    7. 调用API4. 选出得票最多的人(结构体),将这个人的地址保存在结构体指针变量final中:
    	final = getMax(xm, len);
    8. 打印结果,谁以几票当选

  2. 代码:
    #include 
    #include  
    #include 
    #include 
    struct Candidate
    {
        char name[32];
        int tickets;
    };
    
    struct Candidate* initXms(struct Candidate *xm, int len);   
    void printXms(struct Candidate *xm, int len);
    int doVote(struct Candidate *xm, int len);
    struct Candidate* getMax(struct Candidate *xm, int len);
    
    int main(int argc, char const *argv[])
    {
        struct Candidate *xm = NULL;
        int len = 0;                               //结构体数组长度,即选民人数
        int invalidTickets;
        struct Candidate *final;
        puts("请输入参选的人数");    
        scanf("%d%*c", &len);
        xm = initXms(xm, len);                      //1.初始化环节          
        printXms(xm, len);                          //  1.展示选民(姓名和票数)
        invalidTickets = doVote(xm, len);           //2.唱票环节
        printXms(xm, len);                          //  2.展示选民(姓名和票数)和废票
        printf("废票共计%d张\n", invalidTickets);    //  2.展示废票
        final = getMax(xm, len);
        printf("%s以%d票当选!!!\n", final->name, final->tickets);  //3.公布结果
        return 0;
    }
    
    struct Candidate* initXms(struct Candidate *xm, int len)
    {
        assert(xm == NULL);       
        int i;
        xm = (struct Candidate*)malloc(len*sizeof(struct Candidate));     
        for(i=0; itickets < xm->tickets){
                max = xm;
            }
            xm++;
        }
        return max; 
    }

 

你可能感兴趣的:(c语言)