4.2 结构类型——结构

2/22/2017来源:ASP.NET技巧人气:335

1. 结构

#include<stdio.h> int main(int argc, const char *argv) { struct date{ int month; int day; int year; }; struct date today; today.month = 02; today.day = 16; today.year = 2017; // Today is 2017-2-16 PRintf("Today is %i-%i-%i\n", today.year, today.month, today.day); return 0; }

2.声明在函数内外

和本地变量一样:

在函数内部声明的结构类型,只能在函数内部使用 在函数外部声明的结构类型,可以被多个函数使用,通常在函数外部

3.声明结构的形式

// 方式一 struct point { int x; int y; }; struct point p1, p2;// p1 和 p2 都是point,都有x y // 方式二 struct { int x; int y; } p1, p2; //没有声明 point, p1, p2 是一种无名结构,有 x y // 方式三 struct point{ int x; int y; } p1, p2; // p1 p2 都是point,里边有 x y

4.结构的初始化

#include<stdio.h> struct date { int month; int day; int year; }; int main(int argc, const char *argv) { struct date today = { 02, 16, 2017 }; printf("Today is %i-%i-%i\n", today.year, today.month, today.day); // Today is 2017-2-16 // .c 文件支持,.cpp 不支持会报错:sorry, unimplemented: non-trivial designated initializers not supported struct date Month = {.year = 2017, .month = 02}; printf("this month is %i-%i-%i\n", Month.year, Month.month, Month.day); // this month is 2017-2-0 return 0; }

5. 结构成员

变量名.成员名

#include<stdio.h> struct date { int month; int day; int year; }; int main(int argc, const char *argv) { struct date today = { 02, 16, 2017 }; printf("Today is %i-%i-%i\n", today.year, today.month, today.day); // Today is 2017-2-16 return 0; }

6.结构运算

用结构变量的名字 访问整个结构 对于整个结构,可以做 赋值、取地址、函数参数 p1 = (struct point){5, 10}; // 相当于 p1.x = 5; p1.y = 10; p1 = p2; // 相当于 p1.x = p2.x; p1.y = p2.y; #include<stdio.h> struct date { int month; int day; int year; }; int main(int argc, const char *argv) { struct date today; today = (struct date){ 02, 16, 2017 }; struct date day; day = today; day.year = 2015; printf("day is %i-%i-%i\n", day.year, day.month, day.day); // day is 2015-2-16 return 0; }

7. 结构指针

用 & 取结构体的地址

#include<stdio.h> struct date{ int month; int day; int year; }; int main(int argc, const char *argv) { struct date today; today = (struct date){ 02, 16, 2017}; struct date *pDate = &today; printf("address of today is %p\n", today); // address of today is 000000000022FE20 printf("address of pDate is %p\n", pDate); // address of pDate is 000000000022FE30 printf("pDate=%X\n", *pDate); // pDate=22FE20 return 0; }

8. 结构作为函数参数

int numberOfDay(struct date d)

整个结构可以作为函数参数,在函数内新建一个结构变量,并复制调用者的结构的值 函数可以返回一个结构

输入今天的日期,打印明天的日期

#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, const char *argv) { struct date today, tomorrow; printf("输入今天的日期(mm dd yyyy):"); // 输入今天的日期(mm dd yyyy):02 16 2017 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; } // Tomorrow's date is 2017-2-17 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 leap = false; if((d.year % 4 == 0 && d.year % 100 != 0) || d.year % 400 == 0){ leap = true; } return leap; }

9.输入结构

没有直接的方式可以一次 scanf 一个结构,比如我们有一个函数 用于读入一个坐标的x y值,该函数中可以操作这个结果,但是怎么传出去呢? 可以在函数中,创建一个临时的结构变量,然后 返回这个结构变量

#include<stdio.h> struct point { int x; int y; }; struct point getPoint(void); void printPoint(struct point); int main(int argc, const char *argv) { struct point y = {0,0}; y = getPoint(); printPoint(y); return 0; } struct point getPoint() { struct point p; scanf("%d", &p.x);// 输入 2 回车 3 回车 scanf("%d", &p.y); printf("getPoint x=%d, y=%d\n", p.x, p.y); // getPoint x=2, y=3 return p; } void printPoint(struct point p) { printf("printfPoint x=%d, y=%d\n", p.x, p.y); // printfPoint x=2, y=3 }

10.指向结构的指针 作为参数

当传递给函数 一个很大的结构,传指针 比 结构 更高效

用 -> 表示指针所指的结构变量中的成员

#include<stdio.h> struct point { int x; int y; }; struct point* getPoint(struct point*); void printPoint(const struct point*); int main(int argc, const char *argv) { struct point y = {0,0}; getPoint(&y); printPoint(&y); // printPoint(getPoint(&y)); return 0; } struct point* getPoint(struct point* p) { scanf("%d", &p->x);// 输入 2 回车 3 回车 scanf("%d", &p->y); printf("getPoint x=%d, y=%d\n", p->x, p->y); // getPoint x=2, y=3 return p; } void printPoint(const struct point *p) { printf("printfPoint p->x=%d, p->y=%d\n", p->x, p->y); // printfPoint p->x=2, p->y=3 }

11.结构数组

#include<stdio.h> struct time{ int hour; int minute; int second; }; struct time timeUpdate(struct time now); int main(int argc, const char *argv) { struct time times[] = { {11, 59, 59}, {12, 1, 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", times[i].hour, times[i].minute, times[i].second); times[i] = timeUpdate(times[i]); printf("1s laster, Time is %.2i:%.2i:%.2i\n", times[i].hour, times[i].minute, times[i].second); } return 0; } // 计算1s之后的时间并返回 struct time timeUpdate(struct time now) { ++now.second; if(now.second == 60){ now.second = 0; ++now.minute; if(now.minute == 60){ now.minute = 0; ++now.hour; if(now.hour == 24) { now.hour = 0; } } } return now; }

12.嵌套的结构

struct point{ int x; int y; }; struct rectangle{ struct point p1; struct point p2; }; // 如果有 struct rectangle r; 就可以有 r.p1.x r.p2.y // 如果有: struct rectangle r, *rp; rp = &r; // 下边四种形式是等价的 r.p1.x; rp->p1.x; (r.p1).x; (rp->p1).x;

13.结构中的结构数组

#include<stdio.h> struct point{ int x; int y; }; struct rectangle{ struct point p1; struct point p2; }; void printRec(struct rectangle r) { printf("<%d,%d> to <%d,%d>\n", r.p1.x, r.p1.y, r.p2.x, r.p2.y); } int main(int argc, const char *argv) { struct rectangle rects[] = { {{1, 2}, {3, 4}}, {{5, 6}, {7, 8}} }; int i; for(i = 0; i < 2; i++){ printRec(rects[i]); } return 0; }