C语言_0329笔记_结构:结构做函数参数/scanf输入结构变量值/结构数组/结构又结构/无限嵌套

目录

11.2.2 结构与函数

scanf 输入结构

 解决方法(一):临时变量

解决方法(二):结构指针作为参数(更推荐)

11.2.3 结构中的结构

结构数组

结构中的结构

 嵌套的结构(以两个对角点确定的矩形)

 结构中的结构的数组 


11.2.2 结构与函数

int、float等数据类型可以作为函数的参数,结构作为一种数据类型也可以做到(上面说过)

int NumberOfDays(struct date d)

  • 整个结构可以作为参数的值传入函数 
  • 此时是在函数内新建了一个结构变量,并复制了调用者的结构的值
  • 返回值也可以是结构
  • (以上特性与数组完全不同)

例子


 //求明天的日期
#include<stdio.h>
#include<stdbool.h>
//定义了一个 结构 类型,里面包含三个int类型的变量 
struct date{
    int month;
    int day;
    int year;
};
 
bool isLeap(struct date d);//判断是否是闰年函数
int numberOfDays(struct date d);//给出每个月有几天的函数
 
int main()
{
    struct date today;
    struct date tomorrow;
 	int sig=1;
    printf("Enter today's date (mm dd yyyy):");
    scanf("%i %i %i",&today.month,&today.day,&today.year);
//%i是旧写法,和%d一样是输出十进制整数的格式控制符
//&today.month是先进行点运算,取成员month,再将输入的数据用&取地址。
    //因此点运算优先级高
 
 
//若今天不是本月最后一天(也就是本月的天数)
//明天就是天数加一
//	printf("today mm %d\n",today.month);
	//printf("这个月有%d天\n",numberOfDays(today));//这个月有32764天
if(today.day > numberOfDays(today) ||
	today.month >12 ){
		sig =0;
	printf("非法输入,请检查输入是否正确");
	
}
if(today.day != numberOfDays(today)){
    tomorrow.day = today.day+1;
    tomorrow.month = today.month;
    tomorrow.year = today.year;
//12月的最后一天,那么第二天就是第二年
}else if(today.month == 12){
    tomorrow.day = 1;
    tomorrow.month = 1;
    tomorrow.year = today.year+1;
}else{
//不是12月,而且今天是本月最后一天,明天就是下个月第一天
    tomorrow.day = 1;
    tomorrow.month = today.month+1;
    tomorrow.year = today.year;
}
if (sig){
	printf("Tomorrow's date is %i-%i-%i.\n",
    tomorrow.month,tomorrow.day,tomorrow.year);
}
 
return 0;
}
int numberOfDays(struct date d) //给出每个月有几天的函数
{
    int days=0;
    const int daysPerMonth[12]={31,28,31,30,31,30,31,31,30,31,30,31};
 	//printf("函数中的月份 %d\n",d.month); // 3
 	//printf("daysPerMonth[d.month-1]: %d\n",daysPerMonth[d.month-1]); //31
    if(d.month == 2 && isLeap(d))//【if语句里面 判断相等!!一定要用==啊啊啊】 
        days = 29;
    else{
    	days = daysPerMonth[d.month-1]; 
		//因为数组下标从0开始,month.1对应数组【0】
	}
       //printf("days %d\n",days); 
    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;
}

//结构变量是可以直接在函数之间传递的

bool isLeap(struct date d);    //判断是否是闰年函数
int numberOfDays(struct date d);      //给出每个月有几天的函数

scanf 输入结构

  • 没有直接对应的格式控制符对应一整个结构类型,因为其中含有用户自定义的各种类型的数据
  • 如果打算用一个函数来读入结构,如:
  • #include<stdio.h>
    struct point{
        int x;
        int y;  };
     
    void getStruct(struct point);
    void output(struct point);
    void main(){
        struct point y = {0,0};
        getStruct(y);
        output(y);
    }
     
    void getStruct(struct point p){
    //接收到y结构变量的值,是另外一个结构变量
    //因此执行完这个程序后,y不会改变,output函数输出0,0
        scanf("%d",&p.x);
        scanf("%d",&p.y);
        printf("getstruct:%d,%d\n",p.x,p.y);
    }
    void output(struct point p){
        printf("output:%d,%d\n",p.x,p.y);
    }

 结果:(没有改变main里面的值)但由于传入函数的是外面结构的克隆体,而不是指向内容的指针

 解决方法(一):临时变量

 上面用函数读入结构想法是好的,但由于传入函数的是外面结构的克隆体,而不是指向内容的指针,所以有一个方法是:

在传入函数中,创建一个临时的结构变量,然后把临时结构返回给调用者

#include<stdio.h>
struct point{
    int x;
    int y;  };
 
struct point getStruct(void);
void output(struct point);
 
int main()
{    
    struct point y = {0,0};
    y = getStruct();//这个函数不需要传入参数
//结构之间可以直接赋值,将临时结构p赋给y
    output(y);
}
 
//一个返回类型为结构的函数
struct point getStruct(void)//这个函数不需要传入参数 但是它返回一个结构类型 
{
    struct point p;
    scanf("%d",&p.x);
    scanf("%d",&p.y);
    printf("getStruct: %d,%d\n",p.x,p.y);
    return p;//但是它返回一个结构类型 
}
 
void output(struct point p){
    printf("output: %d,%d\n",p.x,p.y);
}

解决方法(二):结构指针作为参数(更推荐)

 当你向函数里传递一个很大的结构,传递指针是比复制更有效的方法。因为C传递结构的方式是值的传递,在被调函数里要建立一个与外面完全相同的结构,既费空间又费时间。

有一个更加简便的符号来表示指针所指的结构变量中的成员->

struct date{int month; int day; int year ;} myday;  //声明了结构类型 同时创建了结构变量

struct date *p = &myday; //取出myday的地址 交给指针p

——指针所指的结构变量(myday)中的成员(month)——

(*p).month = 12; //写法1

p->month = 12; //写法2,中文称为 p所指的month

知道了这个简化写法,解决方法1中的程序就可以写为:

#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()
{    
    struct point y = {0,0};
    getStruct(&y);//int *p=&a; 得到p(指向输出的xy) //getstruct函数返回的是指针p 也就是地址
    output(y);
    output(*getStruct(&y));
//output函数对其进行了*运算(地址上面的值)
//最后用%d 输出 printf函数拿出了地址 所以要用->指向指针p对应的地址
//才能用%d输出
/************************************************************************************************ */
//这里的参数意义:
//*代表了他要取出指针指向的变量,而此时指针指向的是另一个函数的返回值
//所以实际上传入的参数就是上一个函数的返回值
    print(getStruct(&y)); //getStruct得到的指针 传给print print继续操作 
//还可以做的是:
	*getStruct(&y) = (struct point){1,2};
//为什么?因为左边实际上是个变量,这完全符合编译规则和语法
}
 
//传入指针操作之后又返回,好处是可以在之后继续调用这个指针
struct point* getStruct(struct point *p) //返回指针 struct point * 参数指针 
{
    scanf("%d",&p->x); //取p所指的y的x
    scanf("%d",&p->y); //取p所指的y的y
    printf("getStruct:%d,%d\n",p->x,p->y);
    
    return p;
    //返回得到的参数p
}
 
	void output(struct point p){
	    printf("output:%d,%d\n",p.x,p.y);
	}
	 
	void print(const struct point *p)
	{
	//由于只进行输出,传入指针可以是const
	    printf("print: %d %d",p->x,p->y);
	}

11.2.3 结构中的结构

结构数组

定义了一个数组,数组里面的每一个单元都是我自己定义的变量

int a[100]  //基础类型

struct time a[100] //自己声明的类型

例子:

struct date dates[100];
//定义了一个结构数组,100字节大小的数组,每一个单元都是一个结构变量
struct date dates[]={
    {4,5,2005},//dates[0]
    {2,4,2005} //dates[1]
};
 
//调用内部数据:
printf("%i",dates[0].day);

printf("%.2f");

表示以实型(也成浮点型)输出且保留两位小数.如果小数点后不够两位用0表示或着随机的数字,如果超过2位,四舍五入

结构中的结构

结构变量中可以是基础变量类型,也可以是结构变量

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

 嵌套的结构(以两个对角点确定的矩形)

struct point{
    int x;
    int y;
};
 
struct rectangle{
    struct point p1;
    struct point p2;
};
 
int main()
{
    struct rectangle r;
}
就可以有r.p1.x、r.p1.y、r.p2.x、r.p2.y等
来表示每个点
 

若有
    struct rectangle r,*rp;
    rp = &r;

则有四种等价形式

  1. r.p1.x        取出r里的p1的x
  2. rp->p1.x      rp指向的p1里的x
  3. (r.p1).x      加不加括号没什么区别,因为点运算符是从左往右的
  4. (rp->p1).x    同上,因为是指针先指,结构再取
  5. 但没有rp->p1->x (因为p1不是指针,它是个结构,当然不能指向别的东西)

 结构中的结构的数组 

无限套娃:

#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.p1.y, r.p2.x, r.p2.y);
}
 
int main()
{
    int i;
    struct rectangle rects[]=
    {    {{1,2},{3,4}},//{ 1 2, 3 4} 12是p1 34是p2
         {{5,6},{7,8}}
    }
//rects[0].p1.x和y == {1,2}
//rects[0].p2.x和y == {3,4}
 
    for(i=0;i<2;i++)
    printRect(rects[i]);
 
return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值