1. 程式人生 > 其它 >C語言 結構體

C語言 結構體

結構體

1.宣告結構的形式

1.1第一種形式

上面去宣告結構

下面去定義變數

#include <stdio.h>
struct date {//宣告:struct 結構名 {};
	int month;
	int day;
	int year;
};
int main() {
	struct date today;//使用結構的時候前面要跟上結構的名字
	today.month=07;
	today.day=31;
	today.year=2014;
	printf("Today's data is %i-%i-%i.\n",
	       today.year,today.month,today.day
	      );
	return 0;
}
  • 在函式內部宣告的結構型別只能在函式內使用
  • 所以我們通常在函式外部宣告結構型別,這樣可以被多個函式所使用了

1.2第二種形式

沒有結構的名字,p1和p2是一種無名結構,裡面有x和y,不會在其他地方使用

struct{
    int x;
    int y;
}p1,p2
//p1和p2裡面有x,y

1.3第三種形式

struct point{//定義結構
    int x;
    int y;
}p1,p2;//宣告變數
//p1和p2都是point裡面的有x和y的變數

2.結構變數

呼叫形式:變數名.成員名

2.1結構變數的初始化

可以給特定的值進行初始化

  • 方位為{值1,值2,值3}按照順序給值,先定義的為第一個值,以此類推

可以指定結構成員進行初始化

  • 方法為{.成員變數1,.成員變數2....}
  • 沒有給值的成員變數的值,會初始化為0和陣列類似
#include <stdio.h>
struct date {
	int month;
	int day;
	int year;
};
int main() {

	struct date today= {07,31,2014};
	struct date thismonth= {.month=7, .year=2014};

	printf("Today's data is %i-%i-%i.\n",
	       today.year,today.month,today.day
	      );
	printf("This month is %i-%i-%i.\n",
	       thismonth.year,thismonth.month,thismonth.day
	      );
	return 0;
}
//Today's data is 2014-7-31.
//This month is 2014-7-0.

3.結構成員

  • 結構的單元可以是不同的型別,陣列中的單元必須是同一型別
  • 結構同 . 運算子和名字訪問其成員,陣列用 陣列名[下標]來訪問

4.結構運算

要訪問整個結構,直接結構變數的名字

  • 對於整個結構,可以做賦值、取地址,也可以傳遞給函式做引數
pl =(struct point){5,10};//把{5,10}強制轉換為 point 結構變數
pl.x=5;
pl.y=10;

p1=p2; //相當於p1.x=p2.x;pl.y=p2.y;

例如:

#include <stdio.h>
struct date {
	int month;
	int day;
	int year;
};
int main() {

	struct date today;
	today=(struct date) {
		07,31,2014
	};
	struct date day;
	day=today;
	printf("Today's data is %i-%i-%i.\n",
	       today.year,today.month,today.day
	      );
	printf("The day's data is %i-%i-%i.\n",
	       day.year,day.month,day.day
	      );
	return 0;
}

5.結構指標

和陣列不同,結構變數的名字並不是結構變數的地址,必須使用&運算子

struct date *pDate = &today;
#include <stdio.h>
struct date {
	int month;
	int day;
	int year;
};
int main() {

	struct date today;
	today=(struct date) {
		07,31,2014
	};
	struct date day;
	day=today;
	struct date *pDate = &today;
	printf("Today's data is %i-%i-%i.\n",
	       today.year,today.month,today.day
	      );
	printf("The day's data is %i-%i-%i.\n",
	       day.year,day.month,day.day
	      );
	      
	printf("address of today is %p\n",pDate); 
	return 0;
}

6.結構作為函式的引數

int number0fDays(struct date d)
  • 整個結構可以作為引數的值傳入函式
  • 這時候是在函式內新建一個結構變數,並複製呼叫者的結構的值
  • 也可以返回一個結構

案例:

6.1計算明天的日期

#include <stdio.h>
#include <stdlib.h>
struct date {
	int month;
	int day;
	int year;
};
bool isLeap(struct date d); //這個函式用於判斷是否是閏年 
int number0fDays(struct date d);//這個函式用於判斷輸入的月份有幾天 
int main() {
	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 != number0fDays(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 data is %i-%i-%i.\n",
	       tomorrow.year,tomorrow.month,tomorrow.day
	      );

	return 0;
}

int number0fDays(struct date d) {
	int days;

	const int daysPerMonth[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
	//一個字面量int型別的陣列 
	if( d.month==2 &&isLeap(d)) { //若為閏年 2月就為29天 
		days=29;
	} else {
		days=daysPerMonth[d.month-1];
	}
	return days;
}
//判斷是否是閏年,閏年的二月有29天
bool isLeap(struct date d) {
	bool leap =false;
	if((d.year %4==0 && d.year%100 !=0)||d.year%400 ==0)
		leap= true;
	return leap;
}

7.輸入結構

  • 沒有直接的方式可以一次scanf一個結構

  • 如果我們打算寫入一個函式來讀入結構

    #include <stdio.h>
    
    struct point{
    	int x;
    	int y;
    }; 
    
    void getStruct(struct point p);
    void output(struct point p);
    int main()
    {
    	struct point y={0,0};
    	getStruct(y);
    	output(y);	
    	return 0;
    } 
    
    void getStruct(struct point p)
    {
    	scanf("%d",&p.x);
    	scanf("%d",&p.y);
    	printf("%d,%d\n",p.x,p.y);
    }
    
    void output(struct point p)
    {
    	printf("%d,%d\n",p.x,p.y);
    }
    //12 23
    //12,23
    //0,0 可以看到值並沒有傳回來,再一次呼叫還是0和0
    
  • 所以在函式中的p與main中的y是不同的

解決方案:

  1. 在這個輸入函式中,完全可以建立一個臨時的結構變數,然後把這個結構返回給呼叫者
#include <stdio.h>

struct point{
	int x;
	int y;
}; 

struct point getStruct(void);
void output(struct point p);
int main()
{
	struct point y={0,0};
	y=getStruct(); 
	output(y);	
	return 0;
} 

struct point getStruct(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)
{
	printf("%d,%d\n",p.x,p.y);
}
/*12 23
12,23
12,23*/
  1. 利用結構體指標引數
#include <stdio.h>

struct point{
	int x;
	int y;
}; 

struct point *getStruct(struct point *p);
//傳入一個struct point型別的指標p,並返回一個struct point型別的指標getStruct 
void output(struct point p);
//傳入一個 struct point型別 p 
void print(const struct point *p); 
//傳入一個 struct point的指標 p 
int main()
{
	struct point y={0,0};
	getStruct(&y);
	output(y);
	output(*getStruct(&y));	
	print(getStruct(&y));
    *getStruct(&y)=(struct point){1,2,3};
	
	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);
	
} 

8.指向結構的指標

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

struct date *p= &myday;

(*p).month =12;//一般不建議這麼寫
p->month =12;
  • 用->表示指標所指的結構變數中的成員

9.結構陣列

struct date dates[100];
struct date dates[]={{4,5,2005},{2,4,2005}}
//dates[1]:{4}

示例:

#include <stdio.h>
struct time {
	int hour;
	int minutes;
	int seconds;
};
struct time timeUpdate(struct time now);

int main(void) {
	struct time testTimes[5]= {
		{11,59,59},{12,0,0},{1,29,59},{23,59,59},{19,12,17}
	};
	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's %.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; //返回結構體 
}

10.結構中的結構

struct dateAndTime{
	struct date sdate;
	struct time stime;
}; 

10.1巢狀的結構

struct point{
	int x;
    int y;
};
struct rectangele{
	struct point pt1;
    struct point pt2;
};
如果有變數
    struct rectangele r;
	r.pt1.x,r.pt1.y //.pt1是一個結構
    r.pt2.x和r.pt2.y
        
如果有變數定義:
    struct rectangele r,*rp;
	rp=&r;
那麼下面的四種運算形式是等價的
    r.pt1.x
    rp->pt1.x
    (r.pt1).x
    (rp->pt1).x
    但是沒有rp->pt1->x(因為pt1不是指標)