C

8. C语言教程-结构

8. struct

Posted by xuepro on October 30, 2017

“教小白精通编程”系列之“C语言教程” (版权所有,不得转载,擅自抄袭转载将承担法律责任)

结构 struct

C语言的内在类型有

   1) 基础类型
   2) 指针类型
   3) 数组类型

这些类型只能表示一些低层的概念,而实际问题或应用中概念是千变万化的,比如员工管理中的员工、游戏中的坦克等都是一些应用中涉及到的比较高层的概念。如何表示这些概念?C语言提供了用户自定义类型的手段,如struct(结构类)型、enum(枚举)类型等。

数组是一组同类型元素的顺序集合,而结构struct则是表示一个对象的多个不同属性的集合,比如编写一个学生成绩单程序,一个学生有:姓名、分数等属性,一个图书管理程序中一本图书有: 书名、作者、出版社、出版日期、书号等属性。C语言可以让程序员用关键字struct定义各种用户自定义的结构(struct)数据类型,这些结构类型(如同int类型表示整数一样)用于抽象表示实际问题中遇到的各种概念或对象的各种属性。定义好某种结构类型如“struct student”后,就可以从这种结构类型“struct student”的各种具体变量。

1. 定义一个结构类型的格式如下:

   struct name{
         members;  /*成员变量*/
   };

例如:

 struct student {
       char student_name[20];   /*学生的姓名*/
       float score;   /*成绩的分数*/  
};

如同内在类型的变量一样,我们也可以定义结构类型的变量,如:

struct student stu1,stu2;  /*定义了struct student类型的2个变量stu1 和 stu2 */

2. 可以通过成员访问运算符’ . ‘ 访问结构类型变量的成员:

    tu1.score = 80.5;
    strcpy(stu1.name,"Li Ping");

如下是一个简短完整的程序:

#include <stdio.h>

struct student {
       char student_name[20];   /*学生的姓名*/
       float score;   /*成绩的分数*/  
};
void main(){
       struct student stu;  
       strcpy(stu.name,"Li Ping");   stu.score = 80.5;
       printf("the score of student  %s  is: %8.4f\n", stu.name,stu.score);
       printf("请输入修改的学生姓名:\n");
       scanf("%s" , stu.name);
       printf("the score of student  %s  is: %8.4f\n", stu.name,stu.score);
}

3. 结构变量的指针、结构变量的指针变量(简称为 结构指针变量)

struct student stu;  
struct student * p ;    /*  p是一个存储struct student类型变量地址(指针)的指针变量,其类型是struct student *   */
p  = &stu;                      /* struct student* 类型的指针变量p存储的是stu的指针  */
strcpy(p->name, "Wang Hao");   /*   p->name: 通过间接访问运算符->访问结构指针变量p指向的student类型变量stu的成员name */ 
p->score = 50.5;
(*p).score = 70.7;      /*  这里的*p :  通过取内容运算符号*作用指针变量p即*p获得p指向的那个变量stu  */

注: 我们学习了新的间接访问运算符->, 也复习了取内容运算符 *

4. 结构变量、结构变量指针 作为函数参数

 可以将一个结构变量或结构变量的指针作为函数参数传给一个函数。这个函数的形式参数类型必须也是结构变量或结构变量指针。

  struct student{
     char name[10];
     double score;
  }
  
  void Print(struct student stu){
     printf("%s,%lf",stu.name,stu.score);     
  }
  void main(){
     struct student s;
     scanf("%s %lf",&(s.name),&(s.score)); /* 因数组名name就是数组的其实地址,也可以:scanf("%s %lf",s.name,&(s.score));*/ 
     Print(s); /*将实际参数s的值拷贝给形式参数stu,进入Print函数执行*/
  }

 下面代码存在什么问题?

  struct student{
     char name[10];
     double score;
  }
  
  void Print(struct student stu){
     printf("%s,%lf",stu.name,stu.score);     
  }
  void Scanf(struct student stu){
     scanf("%s %lf",&(stu.name),&(stu.score));    
  }
  void main(){
     struct student s;
     Scanf(s);   /*将实际参数s的值拷贝给形式参数stu,进入Scanf函数执行*/
     Print(s);   /*将实际参数s的值拷贝给形式参数stu,进入Print函数执行*/
  }

Scanf函数中的形式参数stu确实可以得到键盘的输入,但它是和main中的实际参数s互不相干的,当Scanf执行完后,其中的stu就销毁了,而main中的s没有任何变化。

 那么,如何修改Scanf? 答案: 将main的变量s的指针作为参数传给被调用函数,被调用函数通过这个指向变量s的指针就可以访问修改变量s了。

  struct student{
     char name[10];
     double score;
  }
  
  void Print(struct student stu){
     printf("%s,%lf",stu.name,stu.score);     
  }
  void Scanf(struct student *stu){
     scanf("%s %lf",&(stu->name),&(stu->score));    
  }
  void main(){
     struct student s;
     Scanf(&s);   /*将s的指针作为实际参数值拷贝给形式参数stu,进入Scanf函数执行*/
     Print(s);   /*将实际参数s的值拷贝给形式参数stu,进入Print函数执行*/
  }

5. 结构数组作为函数参数

编写一个学生成绩表的输入输出程序,从键盘输入学生成绩,然后输出这些学生成绩。提示:所有学生成绩可以保存在一个“struct student”类型的数组中。

 struct student{
     char name[10];
     double score;
  }
  
  void Print(struct student stu){
     printf("%s,%lf\n",stu.name,stu.score);     
  }
  void Scanf(struct student *stu){
     scanf("%s %lf",&(stu->name),&(stu->score));    
  }

void main(){
  sturct student students[100]; /*最多能放100个学生成绩*/
  int n=0; /*实际学生人数*/  
  do{
     Scanf(&students[n]);
     if(s.score<0)       break;   /*推出循环*/
     n++; //新输入一个学生信息,人数增加1 
  }while(1);
  
  for(int i = 0 ; i<n ;i++)
     Print(students[i])
}

我们可以将上面程序的输入输出分别变成2个函数,代码如下:

 struct student{
     char name[10];
     double score;
  }
  
  void Print(struct student stu){
     printf("%s,%lf\n",stu.name,stu.score);     
  }
  void Scanf(struct student *stu){
     scanf("%s %lf",&(stu->name),&(stu->score));    
  }
  
 int Scanf_all(struct student students[]){
     int n=0; /*实际学生人数*/  
     do{
        Scanf(&students[n]);
        if(s.score<0)       break;   /*推出循环*/
        n++; //新输入一个学生信息,人数增加1 
     }while(1);
     return n;
}

void Print_all(struct student students[],int n ){
    for(int i = 0 ; i<n ;i++)
      Print(students[i])
}
void main(){
  sturct student students[100]; /*最多能放100个学生成绩*/
  int n = Scanf_all(students);  
  Print_all(students);
}

练习

关注“教小白精通编程”博客微博“教小白精通编程”  


支付宝打赏 微信打赏

您的打赏是对我最大的鼓励!