C語言 結構體
阿新 • • 發佈:2021-10-18
結構體
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是不同的
解決方案:
- 在這個輸入函式中,完全可以建立一個臨時的結構變數,然後把這個結構返回給呼叫者
#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*/
- 利用結構體指標引數
#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不是指標)