结构体(和其它数据结构)学习总结

前言:设计程序时,选择一种合适的方式表达数据很重要。很多情况下,简单的变量甚至数组还不够。C语言提供了结构变量,该数据类型可以包含多个基本类型及数组类型,而且还能保持各个类型独立,满足程序对复杂数据类型的需求。

一、声明结构的形式

//(1)类型1
struct point{    //point 为结构标记,可以看成结构类型名
	int x;
	int y;
};
struct point p1,p2;// struct point 类比于int,p1,p2为struct point类型的结构变量

//(2)
struct{
	int x;
	int y;
}p1,p2;  //无结构标记point,可以看成没有结构类型名

//(3)
struct point{
	int x;
	int y;
}p1,p2;  //是类型(1)的简化模式

二、结构成员(与数组的区别)及结构运算
1、 结构和数组有点像

  • 数组用[ ]运算符和下标访问其成员:a[0] = 10;

  • 结构用.运算符和名字访问其成员:p1.x;
    注:.比&优先级高,所以&p1.x=&(p1.x);

2、结构运算

  • 要访问整个结构,直接用结构变量的名字;
  • 对于整个结构,可以做赋值,取地址,也可以传递给函数参数;
p1 = (struct point){5,10};//相当于p1.x=5;p1.y=10;

p1 = p2;  //相当于p1.x = p2.x;p1.y=p2.y;

3、结构指针
和数组不同,结构变量的名字并不是结构变量的地址,
必须使用&运算符;

struct date *pDate = &today;

三、结构与函数
1、结构作为函数参数

int numberofDays(struct date d)//实现函数在文章最后的程序段里
  • 整个结构可以作为参数的值传入函数;
  • 这个时候是在函数内创建一个结构变量,并复制调用者的结构的值;
  • 也可以返回一个结构;(与数组完全不同)

2、结构指针作为参数

struct date{
	int month;
	int day;
	int year;
}myday;

struct date *p = &myday;  //把myday的地址赋给p
(*p).month = 12;
p->month = 12; //与上面表达方式一样,更方便
//用->表示指针所指的结构变量中的成员

四、结构数组与结构中的结构
1、结构数组

struct date dates[100];
	struct date dates[] = {
	{4,5,2005},{2,4,2005}};//初始化
	

2、结构中的结构

struct point{
	int x;
	int y;
};

struct rectangle{
	struct point pt1;
	struct point pt2;
};

如果有变量struct rectangle r;
可以有:r.pt1.x.、r.pt2.x;
如果有变量定义:

struct rectangle r,*rp;
rp = &r;

那么一下四种形式等价:

r.pt1.x
r->pt1.x
(r.pt1).x
(rp->pt1).x
//注意没有rp->pt1->x,pt1不是指针

五、自定义数据类型(typedef)
C语言提供了一个叫typedef的功能来声明一个已有的数据类型的新名字;
如:typedef int length;
使得length成为int类型的新名字;
这样,length就可以代替int来定义变量和声明函数;

作用

  • 新的名字是某种类型的别名;
  • 改善了程序的可读性;
typedef long int64_t;//重载已有类型名字,新名字具有可移植性

typedef struct ADate{
 	int month;
 	int day;
 	int year;
 }Date;  //简化了复杂的名字,用Date可以替换struct ADate;

六、附录练习程序:

/* 结构体学习1,结构体初始化 */
#include<stdio.h>

struct date{
	int year;
	int month;
	int day
}; 

int main(int argc, char const *argv)
{
	struct date today = {2020,02,18};
	struct date thismonth = {.month = 02, .year = 2020
	};
	printf("Today's date is %d-%d-%d.\n'",
	today.year,today.month,today.day);	
	printf("This month is %i-%i-%i/.\n",
	thismonth.year,thismonth.month,thismonth.day);
	
	return 0;
}


/*结构体练习2,结构体作为函数参数,
该程序为一个输出年月日的程序,包含了闰年的判断函数
结构体包含了年月日三个成员*/

#include<stdio.h>
#include<stdbool.h>

struct date{
	int month;
	int day;
	int year;
}; 

bool isleap(struct date d);  //声明判断闰年函数,参数为结构体
int numberofDays(struct date d);   //判断每个月多少天的函数 

int main(int argc,char const *argv[])
{
	struct date today,tomorrow;
	
	printf("Enter today's date (mm dd yyyy):");
	scanf("%i %i %i",&today.month, &today.day, &today.year);
	
	if(today.day != numberofDays(today)){
		tomorrow.day = today.day + 1;
		tomorrow.month = today.month;
		tomorrow.year = today.year;
	}else if( today.month == 12){
		tomorrow.day = 1;
		tomorrow.month = 1;
		tomorrow.year = today.year + 1;
	}else{
		tomorrow.day = 1;
		tomorrow.month = today.month + 1;
		tomorrow.year = today.year;
	}
	
	printf("Tomorrow's date is %i-%i-%i.\n",
		tomorrow.year,tomorrow.month,tomorrow.day);
		
return 0;
}

int numberofDays(struct date d)
{
	int days;
	
	const int daysPerMonth[12] = {31, 28 ,31 ,30 ,31 ,30  ,31 ,31  ,30 ,31 ,30 , 31};
	
	if( d.month == 2 && isleap(d))
		days = 29;
	else
		days = daysPerMonth[d.month-1];
		
	return days;
}
 
bool isleap(struct date d)   //这里函数类型为bool型,为真返回true(1),为假返回0; 
{
	bool leap = false;
	
	if(( d.year %4 == 0 && d.year %100 != 0) || d.year % 400  == 0)  //四年一润,百年不润,四百年再润 
		leap = true;
	
	return leap; 
 } 
/* 结构体练习3,尝试编写一个输入函数,能够一次获得结构体所有参数 */

#include<stdio.h>

struct point{
	int x;
	int y;
}; 

struct point getStruct(void);  //相当于封装一个输入函数,不需要每一次输入该结构都要分好几个成员输入 
void output(struct point);  // 同理封装一个输出函数 

int main(int argc, char const *argv[])
{
	struct point y = {0,0};
	y = getStruct();
	output(y);
}

struct point getStruct(void)  //这里的void表示该函数没有传入值 
{
	struct point p;
	scanf("%d",&p.x);
	scanf("%d",&p.y);
	printf("%d, %d\n",p.x,p.y);
	
	return p;
}

void output(struct point p)  //这里的void表示该函数没有返回值 
{
	printf("%d, %d\n ",p.x,p.y);
}

/* 结构体练习4,结构指针作为参数重写结构输入函数 */
//直接通过结构指针操作函数值效率更高,避免传入函数时要重新创建复制体的问题 

#include<stdio.h>

struct point{
	int x;
	int y;
}; 

struct point* getStruct(struct point*); 
void output(struct point);
void print(const struct point *p);

int main(int argc, char const *argv[])
{
	struct point y ={0,0};
	getStruct(&y);
	output(y);
	print(getStruct(&y));
	
	return 0;
}

struct point* getStruct(struct point* p)
{
	scanf("%d",&p->x);  //->表示指针所指的结构变量中的成员 
	scanf("%d",&p->y);
	printf("%d,%d\n",p->x,p->y);
	
	return p;
}

void output(struct point p)
{
	printf("%d,%d\n",p.x,p.y);
}

void print(const struct point *p)
{
	printf("%d,%d\n",p->x,p->y);
}

/* 结构体练习6,结构中的结构 */

#include<stdio.h>

struct point{
	int x;
	int y;
}; 

struct rectangle{
	struct point p1;
	struct point p2;
};

void printRect( struct rectangle r){
	printf("<%d,%d> to <%d,%d>\n",r.p1.x,r.p2.y,r.p2.x,r.p2.y);
}

int main(int argc, const char *argv[])
{
	int i;
	struct rectangle rects[] = {
		{{1,2},{3,4}},
		{{5,6},{7,8}}
	};   //初始化了两个rectangle结构 
	for(i=0; i<2; i++){
		printRect(rects[i]);
	} 
	
	return 0;
}

/* 结构数组练习 */

#include<stdio.h>

struct time{
	int hour;
	int minutes;
	int seconds;
}; 

struct time timeUpdate(struct time ); 

int main(void)
{
//声明并初始化一个结构数组 
struct time testTimes[5] = {
	{11,59,59},{12,0,0},{1,29,59},{23,59,59},{19,12,27}
};
int i;

for( i=0; i<5; i++){
	printf("Time is %.2i:%.2i:%.2i\n",
		testTimes[i].hour,testTimes[i].minutes,testTimes[i].seconds);
		
		testTimes[i] = timeUpdate(testTimes[i]);
		
		printf("One second later it is %.2i:%.2i:%.2i\n",
			testTimes[i].hour,testTimes[i].minutes,testTimes[i].seconds);
			
}

return 0;	
}

struct time timeUpdate(struct time now)  //一个实时更新下一秒的函数 
{
	++now.seconds;
	if(now.seconds == 60){
		now.seconds = 0;
		++now.minutes;
	} if(now.minutes == 60){
		now.minutes = 0;
		++now.hour;
	} if(now.hour == 24){
		now.hour = 0;
	}
	
	return now;
}

The end;

发布了9 篇原创文章 · 获赞 9 · 访问量 258

猜你喜欢

转载自blog.csdn.net/Star_jiang/article/details/104474201