【C语言】学习记录——结构体

学习内容C语言结构体与共用体部分
学习作用使我对结构体的结构掌握更加熟练

(一)时间换算

本题要求编写程序,以hh:mm:ss的格式输出某给定时间再过n秒后的时间值(超过23:59:59就从0点开始计时)。

输入格式:

输入在第一行中以hh:mm:ss的格式给出起始时间,第二行给出整秒数n(<60)。

输出格式:

输出在一行中给出hh:mm:ss格式的结果时间。

输入样例:

11:59:40
30

输出样例:

12:00:10

(1)实验代码

#include<stdio.h>
struct time
{
    int h;
    int m;
    int s;
};
int main(void)
{
    int n;
    struct time t;
    scanf("%d:%d:%d",&t.h,&t.m,&t.s);
    scanf("%d",&n);
    t.s+=n;
    if(t.s>=60)
    {
        t.m+=t.s/60;
        t.s=t.s%60;
    }
    if (t.m>=60)
    {
       t.h+=t.m/60;
       t.m=t.m%60;
    }
    if(t.h>=24)
    {
        t.h=t.h%24;
    }
    printf("%02d:%02d:%02d",t.h,t.m,t.s);
    return 0;
}

(2)设计思路
定义一个含有时分秒的结构体
将所加的秒加到秒上,判断秒与60的关系,看是否需要进位
判断分与60的关系,看是否需要进位
(3)所遇问题
在这里插入图片描述
(4)改进方法
加上判断时与24关系的代码块
(5)终极代码

#include<stdio.h>
struct time
{
    int h;
    int m;
    int s;
};
int main(void)
{
    int n;
    struct time t;
    scanf("%d:%d:%d",&t.h,&t.m,&t.s);
    scanf("%d",&n);
    t.s+=n;
    if(t.s>=60)
    {
        t.m+=t.s/60;
        t.s=t.s%60;
    }
    if (t.m>=60)
    {
       t.h+=t.m/60;
       t.m=t.m%60;
    }
    if(t.h>=24)
    {
      t.h=t.h%24;
    }
    printf("%02d:%02d:%02d",t.h,t.m,t.s);
    return 0;
}

(二)通讯录排序

输入n个朋友的信息,包括姓名、生日、电话号码,本题要求编写程序,按照年龄从大到小的顺序依次输出通讯录。题目保证所有人的生日均不相同。

输入格式:

输入第一行给出正整数n(<10)。随后n行,每行按照“姓名 生日 电话号码”的格式给出一位朋友的信息,其中“姓名”是长度不超过10的英文字母组成的字符串,“生日”是yyyymmdd格式的日期,“电话号码”是不超过17位的数字及+、-组成的字符串。

输出格式:

按照年龄从大到小输出朋友的信息,格式同输出。

输入样例:

3
zhang 19850403 13912345678
wang 19821020 +86-0571-88018448
qian 19840619 13609876543

输出样例:

wang 19821020 +86-0571-88018448
qian 19840619 13609876543
zhang 19850403 13912345678

(1)实验代码

#include<stdio.h>
struct people
{
    char name[11];
    int  bir;
    char tel[30];
}p[10],m;
int main(void)
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s %d %s",p[i].name,&p[i].bir,p[i].tel);
    }
    for(int i=0;i<n-1;i++)
    {
        for(int j=i+1;j<n;j++)
        {
            if(p[i].bir>p[j].bir)
            {
                m=p[i];p[i]=p[j];p[j]=m;
            }
        }
    }
    for(int i=0;i<n;i++)
    {
        printf("%s %d %s\n",p[i].name,p[i].bir,p[i].tel);
    }
    return 0;
}

(2)设计思路
定义一个结构体数组,和一个结构体变量(在后面比较大小交换时需要用到)
比较结构体中生日部分的大小(年份越大的岁数越小),顺序不对的进行交换

(三)一帮一

输入第一行给出正偶数N(≤50),即全班学生的人数。此后N行,按照名次从高到低的顺序给出每个学生的性别(0代表女生,1代表男生)和姓名(不超过8个英文字母的非空字符串),其间以1个空格分隔。这里保证本班男女比例是1:1,并且没有并列名次。

输出格式:

每行输出一组两个学生的姓名,其间以1个空格分隔。名次高的学生在前,名次低的学生在后。小组的输出顺序按照前面学生的名次从高到低排列。

输入样例:

8
0 Amy
1 Tom
1 Bill
0 Cindy
0 Maya
1 John
1 Jack
0 Linda

输出样例:

Amy Jack
Tom Linda
Bill Maya
Cindy John

(1)实验代码

#include<stdio.h>
struct people
{
    int s;
    char name[10];
}p[80];
int main(void)
{
    int n,c=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d %s",&p[i].s,p[i].name);    }
    for(int i=0;i<n;i++)
    {
        for(int j=n-1;j>=0;j--)
        {
            if (p[j].s!=p[i].s)
            {
                printf("%s %s\n",p[i].name,p[j].name);
                c++;break;
            }
        }
        if(c==n/2) break;
    }
}

(2)设计思路
定义一个结构体数组包括性别(数字表示)和姓名
从结构体数组的第一个元素开始,和从结构体数组的最后一个元素开始,寻找性别不一样的,匹配输出
由于男女比例一样,当输出次数等于人数的一半次数时即匹配完毕
(3)所遇问题
输出结果不正确,我测试了几组数据后发现每次输出的异性都是倒数第一个异性,因为每次输出没有删除或者标记已输出的数据,那么怎么标记呢?
(4)改进方法
在结构体中多添加一个整数k,在主函数中将k初始化为1,如果已经输出了结构体数组中的某元素,则将k改变,用k是否为初始值来判断是否输出改元素。
(5)终极代码

#include<stdio.h>
struct people
{
    int s;
    char name[10];
    int k;
}p[80];
int main(void)
{
    int n,c=0;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%d %s",&p[i].s,p[i].name);
        p[i].k=1;
    }
    for(int i=0;i<n;i++)
    {
        for(int j=n-1;j>=0;j--)
        {
            if (p[j].s!=p[i].s&&p[j].k==1)
            {
                p[j].k=0;
                printf("%s %s\n",p[i].name,p[j].name);
                c++;break;
            }
        }
        if(c==n/2) break;
    }
}

(四)计算职工工资

给定N个职员的信息,包括姓名、基本工资、浮动工资和支出,要求编写程序顺序输出每位职员的姓名和实发工资(实发工资=基本工资+浮动工资-支出)。

输入格式:

输入在一行中给出正整数N。随后N行,每行给出一位职员的信息,格式为“姓名 基本工资 浮动工资 支出”,中间以空格分隔。其中“姓名”为长度小于10的不包含空白字符的非空字符串,其他输入、输出保证在单精度范围内。

输出格式:

按照输入顺序,每行输出一位职员的姓名和实发工资,间隔一个空格,工资保留2位小数。

输入样例:

3
zhao 240 400 75
qian 360 120 50
zhou 560 150 80

输出样例:

zhao 565.00
qian 430.00
zhou 63

(1)实验代码

#include<stdio.h>
struct people
{
    char name[100];
    float  bs;
    float  fs;
    float  pay;
}p[1000];
int main(void)
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%s %f %f %f",p[i].name,&p[i].bs,&p[i].fs,&p[i].pay);
        printf("%s %.2f\n",p[i].name,p[i].bs+p[i].fs-p[i].pay);
    }   return 0;
    
}

(2)设计思路
定义一个结构体数组(建议:把数组定义的大一点,要不然很容易出现段错误)
略,下来就很简单啦~

(五)有理数加法

本题要求编写程序,计算两个有理数的和。

输入格式:

输入在一行中按照a1/b1 a2/b2的格式给出两个分数形式的有理数,其中分子和分母全是整形范围内的正整数。

输出格式:

在一行中按照a/b的格式输出两个有理数的和。注意必须是该有理数的最简分数形式,若分母为1,则只输出分子。

输入样例1:

1/3 1/6

输出样例1:

1/2

输入样例2:

4/3 2/3

输出样例2:

2

(1)实验代码

#include<stdio.h>
int GYS(int a,int b)
{
    for(int i=a;i>=1;i--)
    {
        if((a%i==0)&&(b%i==0))
          return i;
    }
}
struct shu
{
    int m;
    int n;
}s[2];
int main(void)
{
    int r,p,q,c;
    for(int i=0;i<2;i++)
    {
        scanf("%d/%d",&s[i].m,&s[i].n);
    }
    r=s[0].n*s[1].n/GYS(s[0].n,s[1].n);
    s[0].m*=r/s[0].n;s[1].m*=r/s[1].n;
    p=s[0].m+s[1].m;q=r;
    if(p%q==0)
       printf("%d",p/q);
    else
       printf("%d/%d",p/GYS(p,q),q/GYS(p,q));
    return 0;
}

(2)设计思路
定义一个长度为2的结构体数组,结构体包括两个元素分别表示分子和分母
r代表两个分数分母的最小公倍数,接下来的操作相当于通分
然后判断通分后的相加数是否可以表示为整数

(六)平面向量加法

本题要求编写程序,计算两个二维平面向量的和向量。

输入格式:

输入在一行中按照“x​1 y1 x2 y2”的格式给出两个二维平面向量v1=(x1,y1)和v2=(x​2,y2)的分量。

输出格式:

在一行中按照(x, y)的格式输出和向量,坐标输出小数点后一位(注意不能输出−0.0)。

输入样例:

3.5 -2.7 -13.9 8.7
输出样例:

(-10.4, 6.0)

(1)实验代码

#include<stdio.h>
struct zubiao
{
    double x;
    double y;
}z[2];
int main(void)
{
    double x,y;
    for(int i=0;i<2;i++)
    {
        scanf("%lf %lf",&z[i].x,&z[i].y);
    }
    x=z[0].x+z[1].x;y=z[0].y+z[1].y;
    printf("(%.1f, %.1f)",x,y);
    return 0;
}

(2)设计思路
这个思路很简单啦!但我还是出错了…(哭泣)
(3)所遇问题

在这里插入图片描述
测试点1 过不去!!!
(4)改进方法
上面提示的很清楚是舍入和-0的问题,我查了一下大概意思就是“大于-0.05的值要变为0.0“,那就要再加一个判断语句啦!
(5)终极代码

#include<stdio.h>
#include<math.h>
struct zubiao
{
    double x;
    double y;
}z[2];
int main(void)
{
    double x,y;
    for(int i=0;i<2;i++)
    {
        scanf("%lf %lf",&z[i].x,&z[i].y);
    }
    x=z[0].x+z[1].x;y=z[0].y+z[1].y;
    if(fabs(x)<0.05)
        x=0.0;
    if(fabs(y)<0.05)
        y=0.0;
    printf("(%.1f, %.1f)",x,y);
    return 0;
}

(七)查找书籍

给定n本书的名称和定价,本题要求编写程序,查找并输出其中定价最高和最低的书的名称和定价。

输入格式:

输入第一行给出正整数n(<10),随后给出n本书的信息。每本书在一行中给出书名,即长度不超过30的字符串,随后一行中给出正实数价格。题目保证没有同样价格的书。

输出格式:

在一行中按照“价格, 书名”的格式先后输出价格最高和最低的书。价格保留2位小数。

输入样例:

3
Programming in C
21.5
Programming in VB
18.5
Programming in Delphi
25.0

输出样例:

25.00, Programming in Delphi
18.50, Programming in VB

(1)实验代码

#include<stdio.h>
struct shu
{
    char name[32];
    double price;
}a[10];
int main(void)
{
    int n,p=0,q=0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        gets(a[i].name);
        scanf("%lf", &a[i].price);
    }
    for (int i = 0; i < n; i++)
    {
        if (a[i].price < a[p].price)
        {
            p=i;
        }
        if (a[i].price > a[q].price)
        {
            q=i;
        }
    }
    printf("%.2f, %s\n", a[q].price, a[q].name);
    printf("%.2f, %s\n", a[p].price, a[p].name);
    return 0;
}

(2)设计思路
定义结构体数组
输入数据,因为有空格所以不能直接用scanf("%s",);哦!要用gets()获取
利用for循环遍历比较,找出最大和最小组的下标
(3)所遇问题
缓冲区里面的回车符——”回车还在缓冲区里面,循环用gets输入书名时,gets获得是回车字符串“(没有遇到过这样的问题,这是在网上查找到的)
(4)改进方法
用了一个getchar()将缓冲区里面的回车符’\0’取出
(5)终极代码

#include<stdio.h>
struct shu
{
    char name[32];
    double price;
}a[10];
int main(void)
{
    int n, p = 0, q = 0;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        getchar();
        gets(a[i].name);
        scanf("%lf", &a[i].price);
    }
    for (int i = 0; i < n; i++)
    {
        if (a[i].price < a[p].price)
        {
            p = i;
        }
        if (a[i].price > a[q].price)
        {
            q = i;
        }
    }
    printf("%.2f, %s\n", a[q].price, a[q].name);
    printf("%.2f, %s\n", a[p].price, a[p].name);
    return 0;
}

(八)计算两个复数之积

本题要求实现一个计算复数之积的简单函数。

函数接口定义:
struct complex multiply(struct complex x, struct complex y);

其中struct complex是复数结构体,其定义如下:

struct complex{
    int real;
    int imag;
};

裁判测试程序样例:

#include <stdio.h>

struct complex{
    int real;
    int imag;
};

struct complex multiply(struct complex x, struct complex y);

int main()
{
    struct complex product, x, y;

    scanf("%d%d%d%d", &x.real, &x.imag, &y.real, &y.imag);
    product = multiply(x, y);
    printf("(%d+%di) * (%d+%di) = %d + %di\n", 
            x.real, x.imag, y.real, y.imag, product.real, product.imag);

    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例:

3 4 5 6
输出样例:

(3+4i) * (5+6i) = -9 + 38i

(1)实验代码

struct complex multiply(struct complex x, struct complex y)
{
    struct complex n;
    n.real=x.real*y.real-x.imag*y.imag;
    n.imag=x.real*y.imag+x.imag*y.real;
    return n;
}

(2)设计思路
这是一道要用到结构体的函数题,我们只需要再定义一个新的结构体变量,存储计算后的结果就OK啦!(复数之积的运算有没有忘记怎么算呀?嘿嘿)

(九)按等级统计学生成绩

本题要求实现一个根据学生成绩设置其等级,并统计不及格人数的简单函数。

函数接口定义:
int set_grade( struct student *p, int n );
其中p是指向学生信息的结构体数组的指针,该结构体的定义为

struct student{
    int num;
    char name[20];
    int score;
    char grade;
};

要求
n是数组元素个数。学号num、姓名name和成绩score均是已经存储好的。set_grade函数需要根据学生的成绩score设置其等级grade。等级设置:85-100为A,70-84为B,60-69为C,0-59为D。同时,set_grade还需要返回不及格的人数。
裁判测试程序样例:

#include <stdio.h>
#define MAXN 10

struct student{
    int num;
    char name[20];
    int score;
    char grade;
};

int set_grade( struct student *p, int n );

int main()
{   struct student stu[MAXN], *ptr;
    int n, i, count;

    ptr = stu;
    scanf("%d\n", &n);
    for(i = 0; i < n; i++){
       scanf("%d%s%d", &stu[i].num, stu[i].name, &stu[i].score);
    } 
   count = set_grade(ptr, n);
   printf("The count for failed (<60): %d\n", count);
   printf("The grades:\n"); 
   for(i = 0; i < n; i++)
       printf("%d %s %c\n", stu[i].num, stu[i].name, stu[i].grade);
    return 0;
}

/* 你的代码将被嵌在这里 */

输入样例
10
31001 annie 85
31002 bonny 75
31003 carol 70
31004 dan 84
31005 susan 90
31006 paul 69
31007 pam 60
31008 apple 50
31009 nancy 100
31010 bob 78
输出样例
The count for failed (<60): 1
The grades:
31001 annie A
31002 bonny B
31003 carol B
31004 dan B
31005 susan A
31006 paul C
31007 pam C
31008 apple D
31009 nancy A
31010 bob B

(1)实验代码

int set_grade( struct student *p, int n )
{
    int c=0;
    for(int i=0;i<n;i++)
    {
        if(p->score<60)
        {  
            c++;
            p->grade='D';
        }
        else if(p->score<=69)
             p->grade='C';
        else if(p->score<=84)
             p->grade='B';
        else if(p->score<=100)
             p->grade='A';
        p++;
    }
    return c;
}

(2)设计思路
这道题思路很简单,只是这道题涉及到了指针、函数以及结构体的多元应用,如果大家感兴趣,可以试试不参考裁判测试样例,自己动动手写写呀!


如果你觉得以上对你有帮助,阔以点点左下角的👍吗?
♥就酱紫啦~byebye 大家一起努力,加油!!!
在这里插入图片描述

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值