C语言总结(第9章 用户自己建立数据类型)

第9章用户自己建立数据类型

目录

第9章用户自己建立数据类型

书上典型例题总结:

示例问题:创建图书目录

建立结构声明

 访问结构成员

指向结构的指针

关键概念

本章小结

第九章目录:

第九章课后题答案:

书上典型例题总结:

如何去定义一个结构体数组:

#include<stdio.h>
#include<string.h>
struct Person
{
    char name[20];
    int count;
}leader[3]={"Li",0,"Zhang",0,"Sun",0};

int main()
{
    int i,j;
    char leader_name[20];
    for (i=1;i<=10;i++)
    {
        scanf("%s",leader_name);
        for(j=0;i<3;i++)
        if(strcmp(leader_name,leader[j].name)==0)leader[j].count++;
    
    }
printf("\nResult:\n");
for(i=0;i<3;i++)
    printf("%5s:%d\n",leader[i].name,leader[i].count);
return 0;
}

指向结构体变量的指针:

#include<stdio.h>
#include<string.h>
int main()
{
    struct Student
    {
        long num;
        char name[20];
        char sex;
        float score;
    };
struct Student_stu_1;
struct Student*p;
p=stu&_1;            //p指向stu_1
stu_1.num=10101;
strcpy(stu_1.name,"Li Lin");
stu_1.sex='M';
stu_1.score=89.5;
printf("No.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n");
        stu_1.num,stu_1.name,stu_1.sex,stu_1.score);
printf("No.:%ld\nname:%s\nsex:%c\nscore:%5.1f\n");
       (*p).num,(*p).name,(*p).sex,(*p).score);    //(*p)表示p指向的结构体变量,(*p).num表示p所指向的结构体变量中的成员num。注意*两侧的括号不可省,因为成员运算符“.”优先于“*”运算符
return 0;
}

如果p指向一个结构体变量stu,以下三种用法等价

(1)stu.成员名(如stu.num);

(2)(*p).成员名(如(*p).num);

(3)p->成员名(如p->num)。

306页例9.7:

学生成绩管理系统

#include<stdio.h>
#include<stdlib.h>
#include<stdlib.h>
#include<string.h>
struct Student{   //每个学生对应一个结构体 
	char ID[20];//学号 
	char Name[10];//姓名 
	float Mark1;//语文成绩 
	float Mark2;//数学成绩 			//四个变量
	float Mark3;//英语成绩 
	float Mark4;//计算机成绩
	float All; //总分 
	float Average;//平均成绩 
}students[1000];

int num=0; //计数器
void Copy(struct Student *arr,int i,int j)
{
	strcpy(arr[i].ID,arr[j].ID);		//strcpy()函数的简介:
									是将一个字符串复制到另一块空间地址中 的函数,‘\0’是停止拷贝的终止条件,
									 也复制到目标空间。下面是库中的strcpy()函数声明:
	strcpy(arr[i].Name,arr[j].Name);
	arr[i].Mark1 = arr[j].Mark1;
	arr[i].Mark2 = arr[j].Mark2;
	arr[i].Mark3 = arr[j].Mark3;
	arr[i].Mark4 = arr[j].Mark4;
	arr[i].All = arr[j].All;
	arr[i].Average = arr[j].Average;
}
int Student_SearchByName(char name[])//通过姓名来检索学生
{
     int i;
     for (i=0;i<num;i++)
     {
         if (strcmp(students[i].Name,name)==0)  //通过strcmp函数来对比学生姓名,找到返回在数组的位置 
         {
              return i;
       }
     }
     return -1;    //未找到返回 -1 
}
int Student_SearchByIndex(char id[])//通过学号来检索学生信息
{
     int i;
     for (i=0;i<num;i++)
     {
         if (strcmp(students[i].ID,id)==0)  //通过strcmp函数来对比学生id,找到返回位置 
         {
              return i;
         }  
     }
     return -1;   //未找到返回 -1 
}
void Student_DisplaySingle(int index)//输出表头
{
     printf("%10s%10s%8s%8s%8s%10s\n","学号","姓名","语文","数学","英语","计算机","总成绩","平均成绩");
     printf("-------------------------------------------------------------\n");
     printf("%10s%10s%8.2f%8.2f%8.2f%8.2f%10.2f%10.2f\n",students[index].ID,students[index].Name,
              students[index].Mark1,students[index].Mark2,students[index].Mark3,students[index].Mark4,students[index].All,students[index].Average);
}
void inputt()//利用循环录入学生信息
{
     while(1)
     {
         printf("请输入学号:");
         scanf("%s",&students[num].ID);
         getchar();
         printf("请输入姓名:");
         scanf("%s",&students[num].Name);
         getchar();
         printf("请输入成绩:");
         scanf("%f",&students[num].Mark1);
         getchar();
         printf("请输入成绩:");
         scanf("%f",&students[num].Mark2);
         getchar();
         printf("请输入成绩:");
         scanf("%f",&students[num].Mark3);
         getchar();
         printf("请输入成绩:");
         scanf("%f",&students[num].Mark4);   //依次输入各项数据 
         getchar();
         students[num].All=students[num].Mark1+students[num].Mark2+students[num].Mark3+students[num].Mark4;    //输完数据后自动计算总成绩与平均成绩 
         students[num].Average=(students[num].Mark1+students[num].Mark2+students[num].Mark3+students[num].Mark4)/4;
         if(Student_SearchByIndex(students[num].ID) == -1)
         {
         	num++;  //移向下一个位置 
		 }
		 else
		 {
		 	printf("学号重复,输入数据无效 !!!\n");
		 }
		 
 		 printf("是否继续?(y/n)");
         if (getchar()=='n')
         {
              break;
         }
     }
}
void modify()//修改成绩
{
	  while(1)
     {
         char id[20];
         int index;
         printf("请输入要修改的学生的学号:");
         scanf("%s",&id);
         getchar();
         index=Student_SearchByIndex(id);  //调用搜查id函数,根据其返回值确定位置 
         if (index==-1)
         {
              printf("学生不存在!\n");
         }
         else
         {
              printf("你要修改的学生信息为:\n");
              Student_DisplaySingle(index);
              printf("-- 请输入新值--\n");
              printf("请输入学号:");
              scanf("%s",&students[index].ID);
              getchar();
              printf("请输入姓名:");
              scanf("%s",&students[index].Name);
              getchar();
              printf("请输入语文成绩:");
              scanf("%f",&students[index].Mark1);
 			  getchar();
              printf("请输入数学成绩:");
              scanf("%f",&students[index].Mark2);
              getchar();
              printf("请输入英语成绩:");
              scanf("%f",&students[index].Mark3);
              getchar();
              printf("请输入计算机成绩:");
              scanf("%f",&students[index].Mark4);  //重新录入一套新的数据替代 
              getchar();
              students[index].All=students[index].Mark1+students[index].Mark2+students[index].Mark3+students[index].Mark4;
        	  students[index].Average=(students[index].Mark1+students[index].Mark2+students[index].Mark3+students[index].Mark4)/4;   
         }
         printf("是否继续?(y/n)");
         if (getchar()=='n')
         {
              break;
         }
     }
}
void deletee()//删除学生信息
{
	  int i;
     while(1)
     {
         char id[20];
         int index;
         printf("请输入要删除的学生的学号:");
         scanf("%s",&id);
         getchar();
         index=Student_SearchByIndex(id);   //调用搜查id函数,根据其返回值确定位置 
         if (index==-1)
         {
              printf("学生不存在!\n");
         }
         else
         {
              printf("你要删除的学生信息为:\n");
              Student_DisplaySingle(index);
              printf("是否真的要删除?(y/n)");
              if (getchar()=='y')
              {
                   for (i=index;i<num-1;i++)
                   {
                   	   Copy(students,i,i+1);
                       //students[i]=students[i+1];    //把后边的对象都向前移动
                   }
                   num--;
              }
             getchar();
         }
         printf("是否继续?(y/n)");
         if (getchar()=='n')
         {
              break;
         }
     }
}
void display()//打印已录入的学生信息
{
	 int a;
     printf("%10s%10s%8s%8s%8s%8s%10s%10s\n","学号","姓名","语文","数学","英语","计算机","总成绩","平均成绩");
     printf("-------------------------------------------------------------\n");
     for (a=0;a<num;a++)
     {
         printf("%10s%10s%8.2f%8.2f%8.2f%8.2f%10.2f%10.2f\n",students[a].ID,students[a].Name,
              students[a].Mark1,students[a].Mark2,students[a].Mark3,students[a].Mark4,students[a].All,students[a].Average);
     }
}
void insert()//指定位置插入学生信息
{
		int a,b,c;
		printf("请输入你要插入的位置");
		scanf("%d",&a);
		if(a>num) {
		printf("输入的位置有误,请重新输入,当前共%d条数据\n",num); 
		scanf("%d",&a);}
 
     	b=num-1;
     	for(;b>=a-1;b--)
     	{
     		//strcpy(students[b+1].ID,students[b].ID);
     		//strcpy(students[b+1].Name,students[b].Name);
     		//students[b+1].Mark1=students[b].Mark1;
     		//students[b+1].Mark2=students[b].Mark2;
     		//students[b+1].Mark3=students[b].Mark3;
     		//students[b+1].Mark4=students[b].Mark4;
     		//students[b+1].All=students[b].All;
     		//students[b+1].Average=students[b].Average;  
			Copy(students,b+1,b); //根据其输入的位置,将其及以后的数据向后移动一个位置 
     		
		 }
		 num++;
         printf("请输入学号:");
         scanf("%s",&students[a-1].ID);
         getchar();
         printf("请输入姓名:");
         scanf("%s",&students[a-1].Name);
         getchar();
         printf("请输入语文成绩:");
         scanf("%f",&students[a-1].Mark1);
         getchar();
         printf("请输入数学成绩:");
         scanf("%f",&students[a-1].Mark2);
         getchar();
         printf("请输入英语成绩:");
         scanf("%f",&students[a-1].Mark3);
         getchar();
         printf("请输入计算机成绩:");
         scanf("%f",&students[a-1].Mark4);  //输入新数据 
         getchar();  
         students[a-1].All=students[a-1].Mark1+students[a-1].Mark2+students[a-1].Mark3+students[a-1].Mark4;
         students[a-1].Average=(students[a-1].Mark1+students[a-1].Mark2+students[a-1].Mark3+students[a-1].Mark4)/4;
 
}
void search()//查询学生信息
{
	 while(1)
     {
         char name[20];
         int index;
         printf("请输入要查询的学生的姓名:");
         scanf("%s",&name);
         getchar();
         index=Student_SearchByName(name);   //调用搜查name函数,根据其返回值确定位置 
         if (index==-1)
         {
              printf("学生不存在!\n");
         }
         else
         {
              printf("你要查询的学生信息为:\n");
              Student_DisplaySingle(index);
         }
         printf("是否继续?(y/n)");
         if (getchar()=='n')
         {
              break;
         }
     }
}
voidsort()//根据平均分排序 
(此时注意按照题目要求应该排序两个)
{
	 int i,j;
	 //struct students tmp;
     for (i=0;i<num;i++)
     {
     	students[i].Average=(students[i].Mark1+students[i].Mark2+students[i].Mark3+students[i].Mark4)/4;
     }
     for (i=0;i<num;i++)
     {
         for (j=1;j<num-i;j++)
         {
              if (students[j-1].Average<students[j].Average)
              {
                  
				   Copy(students,num,j-1);
				   Copy(students,j-1,j);
				   Copy(students,j,num); 
				   //tmp=students[j-1];
                   //students[j-1]=students[j];
                   //students[j]=tmp;      //冒泡排序 
            }  
         }
     }
     int a;
     printf("%10s%10s%8s%8s%8s%10s\n","学号","姓名","语文","数学","英语","计算机","总成绩","平均成绩");
     printf("-------------------------------------------------------------\n");
     for (a=0;a<num;a++)
     {
         printf("%10s%10s%8.2f%8.2f%8.2f%8.2f%10.2f%10.2f\n",students[a].ID,students[a].Name,
              students[a].Mark1,students[a].Mark2,students[a].Mark3,students[a].Mark4,students[a].All,students[a].Average);
     }
} 
 
 
void SearchLow()//搜索不及格的并输出 
{
	int a;
	printf("           语文不及格的有%10s%10s%8s\n","学号","姓名","语文"); 
	for(a=0;a<num;a++)
	{ 
		if(students[a].Mark1<60)
		printf("%10s%10s%8.2f\n",students[a].Name,students[a].ID,students[a].Mark1);    //从头搜索到尾,若小于60就输出 
	 } 
	 
	printf("           数学不及格的有%10s%10s%8s\n","学号","姓名","数学"); 
	for(a=0;a<num;a++)
	{ 
		if(students[a].Mark2<60)
		printf("%10s%10s%8.2f\n",students[a].Name,students[a].ID,students[a].Mark2);
	 } 
	 
	 printf("           英语不及格的有%10s%10s%8s\n","学号","姓名","英语");
	for(a=0;a<num;a++)
	{ 
		if(students[a].Mark3<60)
		printf("%10s%10s%8.2f\n",students[a].Name,students[a].ID,students[a].Mark3);
	 } 
	 
	 printf("           计算机不及格的有%10s%10s%8s\n","学号","姓名","计算机");
	for(a=0;a<num;a++)
	{ 
		if(students[a].Mark4<60)
		printf("%10s%10s%8.2f\n",students[a].Name,students[a].ID,students[a].Mark4);
	 } 
	 system("pause");		//这个好像没作用
}
 
void SearchHigh()//搜索成绩最高者输出 
{
	int a;
	int max ;
	printf("           语文最高分为%10s%10s%8s\n","学号","姓名","语文"); 
	max=students[0].Mark1;
	for(a=1;a<num;a++)
	{ 
		if(students[a].Mark1>max)
		max=students[a].Mark1;
	}
	for(a=0;a<num;a++)
	{ 
		if(max==students[a].Mark1)
		printf("%10s%10s%8.2f\n",students[a].Name,students[a].ID,students[a].Mark1);
	}
	
	printf("           数学最高分为%10s%10s%8s\n","学号","姓名","数学"); 
	max=students[0].Mark2;
	for(a=1;a<num;a++)
	{ 
		if(students[a].Mark2>max)
		max=students[a].Mark2;
	}
	for(a=0;a<num;a++)
	{ 
		if(max==students[a].Mark2)
		printf("%10s%10s%8.2f\n",students[a].Name,students[a].ID,students[a].Mark2);
	}
	
	printf("           英语最高分为%10s%10s%8s\n","学号","姓名","英语"); 
	max=students[0].Mark3;
	for(a=1;a<num;a++)
	{ 
		if(students[a].Mark3>max)
		max=students[a].Mark3;
	}
	for(a=0;a<num;a++)
	{ 
		if(max==students[a].Mark3)
		printf("           %10s%10s%8.2f\n",students[a].Name,students[a].ID,students[a].Mark3);
	}
	
	printf("           计算机最高分为%10s%10s%8s\n","学号","姓名","计算机"); 
	max=students[0].Mark4;
	for(a=1;a<num;a++)
	{ 
		if(students[a].Mark4>max)
		max=students[a].Mark4;
	}
	for(a=0;a<num;a++)
	{ 
		if(max==students[a].Mark4)
		printf("           %10s%10s%8.2f\n",students[a].Name,students[a].ID,students[a].Mark4);
	}
	 system("pause");
}
void Save()
{
	FILE*fp = fopen("temp.txt","w+");
	fprintf(fp,"%d\n",num);
	for(int i = 0 ; i< num ;i++)
	{
		fprintf(fp,"%s %s %f %f %f %f %f %f\n",students[i].ID,students[i].Name,students[i].Mark1,students[i].Mark2,students[i].Mark3,students[i].Mark4,students[i].All,students[i].Average);
	}
	fclose(fp);
}
void Load()
{
	FILE*fp = fopen("temp.txt","r");
	fscanf(fp,"%d",&num);
	for(int i = 0 ; i< num ;i++)
	{
		fscanf(fp,"%s %s %f %f %f %f %f %f\n",students[i].ID,students[i].Name,&students[i].Mark1,&students[i].Mark2,&students[i].Mark3,&students[i].Mark4,&students[i].All,&students[i].Average);
	}
	fclose(fp);
} 
/*主程序*/
int main(){
	int i;
	while(1){
		 Load();
		 printf("\t\t\t\t\t-------- 学生成绩管理系统-------\n\n\n\n");     //菜单 
         printf("\t\t\t\t\t1. 增加学生记录\n\n");
         printf("\t\t\t\t\t2. 修改学生记录\n\n");
         printf("\t\t\t\t\t3. 删除学生记录\n\n");
         printf("\t\t\t\t\t4. 插入学生记录\n\n");
         printf("\t\t\t\t\t5. 显示所有记录\n\n");
         printf("\t\t\t\t\t6. 查询学生记录\n\n");
         printf("\t\t\t\t\t7. 按平均成绩排序\n\n");
         printf("\t\t\t\t\t8. 输出各科目不及格学生\n\n");
         printf("\t\t\t\t\t9. 输出各科目最高分\n\n");
         printf("\t\t\t\t\t0. 退出\n\n\n");
         printf("请选择(0-9):");
 		 scanf("%d",&i);
			switch(i){
		 case 1:inputt();break;
		 case 2:modify();break;
	 	 case 3:deletee();break;
	 	 case 4:insert();break;
	 	 case 5:display();break;
		 case 6:search();break;
		 case 7:sort();break;
		 case 8:SearchLow();break;
		 case 9:SearchHigh();break;
		 case 0:exit(0);
		 default:  ;
	}
	Save();
}
	 return 0; 
} 
void Save() {
	FILE *fp = fopen("temp.txt", "w+");
	fprintf(fp, "%d\n", num);
	for (int i = 0 ; i < num ; i++) {
		fprintf(fp, "%s %s %f %f %f %f %f %f\n", students[i].ID, students[i].Name, students[i].Mark1, students[i].Mark2,
		        students[i].Mark3, students[i].Average1);
	}
	fclose(fp);
}

void Load() {
	FILE *fp = fopen("temp.txt", "r");
	fscanf(fp, "%d", &num);
	for (int i = 0 ; i < num ; i++) {
		fscanf(fp, "%s %s %f %f %f %f %f %f\n", students[i].ID, students[i].Name, &students[i].Mark1, &students[i].Mark2,
		       &students[i].Mark3, &students[i].Average1);
	}
	fclose(fp);
}

调试示例error09_1.cpp(结构)

输入一个正整数n(3≤n≤10),再输入n个雇员的信息,包括姓名、基本工资、浮动工资和支出,输出每人的姓名和实发工资,实发工资=基本工资+浮动工资-支出。

输入输出示例:括号内为说明

输入:

3 (n=3)

zhao 240 400 75

qian 360 120 50

zhou 560 0 80

输出:

 zhao 实发工资: 565.00

 qian 实发工资: 430.00

 zhou 实发工资: 480.00

#include <stdio.h>

int main (void)

{

    int i, n;

      struct emp{

        char  name[10];

        double jbg;

        double fdg;

        double zc;

    } s[10];

    scanf("%d", &n);

for(i=0;i<n;i++)

scanf("%s%lf%lf%lf",s[i].name, &s[i].jbg,&s[i].fdg,&s[i].zc);

    for (i = 0; i < n; i++)

        printf ("%5s 实发工资:%7.2f\n", s[i].name, s[i].jbg + s[i].fdg - s[i].zc);

}

90002    时间换算(结构)

输入一个正整数 repeat (0<repeat<10),做 repeat 次下列运算:

输入一个时间数值,再输入秒数 n,输出该时间再过 n 秒后的时间值,时间的表示形式为时:分:秒,超过 24 时从 0 时重新开始计时。

输入输出示例:括号内为说明

输入:

3    (repeat=3)

0:0:1

59    (秒数n=59)

11:59:40   

30    (秒数n=30)

23:59:40   

301    (秒数n=301)

输出:

time: 0:1:0    (0:0:01加上59秒的新时间)   

time: 12:0:10    (11:59:40加上30秒的新时间)

time: 0:4:41    (23:59:40加上301秒的新时间)

#include <stdio.h>

int main(void)

{

    int n;

    int repeat, ri;

    struct time{

        int hour, minute, second;

    }time;

    scanf("%d", &repeat);

    for(ri = 1; ri <= repeat; ri++){

        scanf("%d:%d:%d", &time.hour, &time.minute, &time.second);

        scanf("%d",&n);

time.second=time.second+n;

if(time.second>=60){

time.minute=time.minute+time.second/60;

time.second=time.second%60;

if(time.minute>=60){

time.hour=time.hour+time.minute/60;

time.minute=time.minute%60;

if(time.hour>=24)

time.hour=time.hour-24;

}

}

        printf("time: %d:%d:%d\n", time.hour, time.minute, time.second);

   }

}

90003    计算平均成绩(结构)

输入整数n(n<10),再输入n个学生的基本信息,包括序号、姓名和成绩,要求计算并输出他们的平均成绩(保留2位小数)。

输入输出示例:括号内为说明

输入:

3 (n=3)

1  zhang  70

2  wang  80

3  qian  90

输出:

average: 80.00

#include <stdio.h>

int main(void)

{

    int i, n;

    double average, sum;

    struct student{

        int num;

        char name[10];

        int score;

    }s[10];

    scanf("%d", &n);

sum=0;

for(i=0;i<n;i++){

scanf("%d%s%d",&s[i].num,s[i].name,&s[i].score);

sum+=s[i].score;

}

average=sum/n;

    printf("average: %.2f\n", average);

}

90004    计算两个复数之积(结构)

输入4个整数a1,b1,a2,b2,分别表示两个复数的实部与虚部,求两个复数之积(a1+b1i)*(a2+b2i),乘积的实部为:a1*a2-b1*b2,虚部为:a1*b2+a2*b1。

输入输出示例:括号内为说明

输入:

3 4 5 6

输出:

(3+4i) * (5+6i) = -9 + 38i

#include <stdio.h>

int main(void)

{

    struct complex{

        int real;

        int imag;

    }product, x, y;

    scanf("%d%d%d%d", &x.real, &x.imag, &y.real, &y.imag);

product.real=x.real*y.real-x.imag*y.imag;

product.imag=x.real*y.imag+x.imag*y.real;

    printf("(%d+%di) * (%d+%di) = %d + %di\n", x.real, x.imag, y.real, y.imag, product.real, product.imag);

}

示例问题:创建图书目录

Gwen Glenn要打印一份图书目录。她想打印每本书的各种信息:书名、

作者、出版社、版权日期、页数、册数和价格。其中的一些项目(如,书

名)可以储存在字符数组中,其他项目需要一个int数组或float数组。用 7 个

不同的数组分别记录每一项比较繁琐,尤其是 Gwen 还想创建多份列表:一

份按书名排序、一份按作者排序、一份按价格排序等。如果能把图书目录的

信息都包含在一个数组里更好,其中每个元素包含一本书的相关信息。

因此,Gwen需要一种即能包含字符串又能包含数字的数据形式,而且

还要保持各信息的独立。C结构就满足这种情况下的需求。我们通过一个示

例演示如何创建和使用数组。但是,示例进行了一些限制。第一,该程序示

例演示的书目只包含书名、作者和价格。第二,只有一本书的数目。当然,

别忘了这只是进行了限制,我们在后面将扩展该程序。请看程序清单14.1及

其输出,然后阅读后面的一些要点。

程序清单14.1 book.c程序

//* book.c -- 一本书的图书目录 */

#include <stdio.h>

#include <string.h>

char * s_gets(char * st, int n);

#define MAXTITL41 /* 书名的最大长度 + 1 */

#define MAXAUTL31 /* 作者姓名的最大长度 + 1*/

struct book { /* 结构模版:标记是 book */

char title[MAXTITL];

1007char author[MAXAUTL];

float value;

}; /* 结构模版结束 */

int main(void)

{

struct book library; /* 把 library 声明为一个 book 类型的变量 */

printf("Please enter the book title.\n");

s_gets(library.title, MAXTITL); /* 访问title部分*/

printf("Now enter the author.\n");

s_gets(library.author, MAXAUTL);

printf("Now enter the value.\n");

scanf("%f", &library.value);

printf("%s by %s: $%.2f\n", library.title,

library.author, library.value);

printf("%s: \"%s\" ($%.2f)\n", library.author,

library.title, library.value);

printf("Done.\n");

return 0;

}

1008char * s_gets(char * st, int n)

{

char * ret_val;

char * find;

ret_val = fgets(st, n, stdin);

if (ret_val)

{

find = strchr(st, '\n'); // 查找换行符

if (find) // 如果地址不是 NULL,

*find = '\0'; // 在此处放置一个空字符

else

while (getchar() != '\n')

continue; //处理输入行中剩余的字符

}

return ret_val;

}

我们使用前面章节中介绍的s_gets()函数去掉fgets()储存在字符串中的换

行符。下面是该例的一个运行示例:

Please enter the book title.

1009Chicken of the Andes

Now enter the author.

Disma Lapoult

Now enter the value.

29.99

Chicken of the Andes by Disma Lapoult: $29.99

Disma Lapoult: "Chicken of the Andes" ($29.99)

Done.

程序清单14.1中创建的结构有3部分,每个部分都称为成员(member)

或字段(

field)。这3部分中,一部分储存书名,一部分储存作者名,一部

分储存价格。下面是必须掌握的3个技巧:

为结构建立一个格式或样式;

声明一个适合该样式的变量;

访问结构变量的各个部分

建立结构声明

结构声明(

structure declaration)描述了一个结构的组织布局。声明类

似下面这样:

struct book {

char title[MAXTITL];

char author[MAXAUTL];

float value;

};

该声明描述了一个由两个字符数组和一个float类型变量组成的结构。该

声明并未创建实际的数据对象,只描述了该对象由什么组成。〔有时,我们

把结构声明称为模板,因为它勾勒出结构是如何储存数据的。如果读者知道

C++的模板,此模板非彼模板,C++中的模板更为强大。〕我们来分析一些

细节。首先是关键字 struct,它表明跟在其后的是一个结构,后面是一个可

选的标记(该例中是 book),稍后程序中可以使用该标记引用该结构。所

以,我们在后面的程序中可以这样声明:

struct book library;

这把library声明为一个使用book结构布局的结构变量。

在结构声明中,用一对花括号括起来的是结构成员列表。每个成员都用

自己的声明来描述。例如,title部分是一个内含MAXTITL个元素的char类型

数组。成员可以是任意一种C的数据类型,甚至可以是其他结构!右花括号

后面的分号是声明所必需的,表示结构布局定义结束。可以把这个声明放在

所有函数的外部(如本例所示),也可以放在一个函数定义的内部。如果把

结构声明置于一个函数的内部,它的标记就只限于该函数内部使用。如果把

结构声明置于函数的外部,那么该声明之后的所有函数都能使用它的标记。

1011例如,在程序的另一个函数中,可以这样声明:

struct book dickens;

这样,该函数便创建了一个结构变量dickens,该变量的结构布局是

book。

结构的标记名是可选的。但是以程序示例中的方式建立结构时(在一处

定义结构布局,在另一处定义实际的结构变量),必须使用标记。我们学完

如何定义结构变量后,再来看这一点。

 访问结构成员

结构类似于一个“超级数组”,这个超级数组中,可以是一个元素为char

类型,下一个元素为forat类型,下一个元素为int数组。可以通过数组下标单

独访问数组中的各元素,那么,如何访问结构中的成员?使用结构成员运算

符——点(

.)访问结构中的成员。例如,library.value即访问library的value

部分。可以像使用任何float类型变量那样使用library.value。与此类似,可以

像使用字符数组那样使用 library.title。因此,程序清单 14.1 中的程序中有

s_gets(library.title, MAXTITL);和scanf("%f", &library.value);这样的代码。

本质上,.title、.author和.value的作用相当于book结构的下标。

注意,虽然library是一个结构,但是library.value是一个float类型的变

量,可以像使用其他 float 类型变量那样使用它。例如,scanf("%f",...)需要一

个 float 类型变量的地址,而&library.float正好符合要求。.比&的优先级高,

因此这个表达式和&(library.float)一样。

指向结构的指针

喜欢使用指针的人一定很高兴能使用指向结构的指针。至少有 4 个理由

可以解释为何要使用指向结构的指针。第一,就像指向数组的指针比数组本

身更容易操控(如,排序问题)一样,指向结构的指针通常比结构本身更容

易操控。第二,在一些早期的C实现中,结构不能作为参数传递给函数,但

是可以传递指向结构的指针。第三,即使能传递一个结构,传递指针通常更

有效率。第四,一些用于表示数据的结构中包含指向其他结构的指针。

下面的程序(程序清单14.4)演示了如何定义指向结构的指针和如何用

这样的指针访问结构的成员。

程序清单14.4 friends.c程序

/* friends.c -- 使用指向结构的指针 */

#include <stdio.h>

#define LEN 20

struct names {

char first[LEN];

char last[LEN];

};

struct guy {

struct names handle;

char favfood[LEN];

char job[LEN];

1031float income;

};

int main(void)

{

struct guy fellow[2] = {

{ { "Ewen", "Villard" },

"grilled salmon",

"personality coach",

68112.00

},

{ { "Rodney", "Swillbelly" },

"tripe",

"tabloid editor",

432400.00

}

};

struct guy * him; /* 这是一个指向结构的指针 */

printf("address #1: %p #2: %p\n", &fellow[0], &fellow[1]);

him = &fellow[0]; /* 告诉编译器该指针指向何处 */

1032printf("pointer #1: %p #2: %p\n", him, him + 1);

printf("him->income is $%.2f: (*him).income is $%.2f\n",

him->income, (*him).income);

him++; /* 指向下一个结构 */

printf("him->favfood is %s: him->handle.last is %s\n",

him->favfood, him->handle.last);

return 0;

}

该程序的输出如下:

address #1: 0x7fff5fbff820 #2: 0x7fff5fbff874

pointer #1: 0x7fff5fbff820 #2: 0x7fff5fbff874

him->income is $68112.00: (*him).income is $68112.00

him->favfood is tripe: him->handle.last is Swillbelly

关键概念

我们在编程中要表示的信息通常不只是一个数字或一些列数字。程序可

能要处理具有多种属性的实体。例如,通过姓名、地址、电话号码和其他信

息表示一名客户;或者,通过电影名、发行人、播放时长、售价等表示一部

电影DVD。C结构可以把这些信息都放在一个单元内。在组织程序时这很重

要,因为这样可以把相关的信息都储存在一处,而不是分散储存在多个变量

中。

设计结构时,开发一个与之配套的函数包通常很有用。例如,写一个以

结构(或结构的地址)为参数的函数打印结构内容,比用一堆printf()语句强

得多。因为只需要一个参数就能打印结构中的所有信息。如果把信息放到零

散的变量中,每个部分都需要一个参数。另外,如果要在结构中增加一个成

员,只需重写函数,不必改写函数调用。这在修改结构时很方便。

联合声明与结构声明类似。但是,联合的成员共享相同的存储空间,而

且在联合中同一时间内只能有一个成员。实质上,可以在联合变量中储存一

个类型不唯一的值。

enum 工具提供一种定义符号常量的方法,typedef 工具提供一种为基本

或派生类型创建新标识符的方法。

指向函数的指针提供一种告诉函数应使用哪一个函数的方法。

本章小结

C 结构提供在相同的数据对象中储存多个不同类型数据项的方法。可以

使用标记来标识一个具体的结构模板,并声明该类型的变量。通过成员点运

算符(.)可以使用结构模版中的标签来访问结构的各个成员。

如果有一个指向结构的指针,可以用该指针和间接成员运算符(->)代

替结构名和点运算符来访问结构的各成员。和数组不同,结构名不是结构的

地址,要在结构名前使用&运算符才能获得结构的地址。

一贯以来,与结构相关的函数都使用指向结构的指针作为参数。现在的

C允许把结构作为参数传递,作为返回值和同类型结构之间赋值。然而,传

递结构的地址通常更有效。

联合使用与结构相同的语法。然而,联合的成员共享一个共同的存储空

间。联合同一时间内只能储存一个单独的数据项,不像结构那样同时储存多

种数据类型。也就是说,结构可以同时储存一个int类型数据、一个double类

型数据和一个char类型数据,而相应的联合只能保存一个int类型数据,或者

一个double类型数据,或者一个char类型数据。

通过枚举可以创建一系列代表整型常量(枚举常量)的符号和定义相关

联的枚举类型。

typedef工具可用于建立C标准类型的别名或缩写。

函数名代表函数的地址,可以把函数的地址作为参数传递给其他函数,

然后这些函数就可以使用被指向的函数。如果把特定函数的地址赋给一个名

为pf的函数指针,可以通过以下两种方式调用该函数:

#include <math.h> /* 提供sin()函数的原型:double sin(double) */

...

double (*pdf)(double);

1121double x;

pdf = sin;

x = (*pdf)(1.2); // 调用sin(1.2)

x = pdf(1.2); // 同样调用 sin(1.2)

第九章目录:

9.1定义和使用结构体变量293

9.1.1自己建立结构体类型293

9.1.2定义结构体类型变量295

9.1.3结构体变量的初始化和引用296

9.2使用结构体数组300

9.2.1定义结构体数组300

9.2.2结构体数组的应用举例301

9.3结构体指针303

9.3.1指向结构体变量的指针303

9.3.2指向结构体数组的指针304

9.3.3用结构体变量和结构体变量的指针作函数参数306

9.6使用枚举类型322

*9.7用typedef声明新类型名326

第九章课后题答案:

 C语言程序设计第五版谭浩强课后答案 第九章习题答案_月已满西楼的博客-CSDN博客_在第三题的基础上,编写一个函数input

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

时雨h

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值