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;
}