結構體(和其它數據結構)學習總結

前言:設計程序時,選擇一種合適的方式表達數據很重要。很多情況下,簡單的變量甚至數組還不夠。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;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章