C语言初阶⑧(结构体)知识点和笔试题

目录

结构体的基础知识

结构体的声明

结构成员的类型

结构体变量的定义和初始化

数据类型定义 typedef

结构体成员的访问

结构变量的成员通过点操作符访问

结构体指针访问指向变量的成员

结构体传参

笔试题

程序的输出结果是:( )

下面哪个是指针数组:( )

打印自幂数(水仙花数)

喝汽水问题

打印棱形图案

字符串逆序


结构体的基础知识

① 结构体是一些值的集合,这些值称为成员变量;

② 结构体的每个成员可以是不同类型得变量;

结构体的声明

注意事项:

① 成员变量之间用分号隔开,全局变量之间用逗号隔开;

② 结构体末大括号后 必须加上分号(即使不写全局变量也要加上);

结构体的声明:使用结构体描述一个学生

描述一个学生需要一些数据:姓名、年龄、性别、学号

/* struct 结构体关键字   Stu - 结构体标签 struct   Stu - 结构体类型 */
struct Stu 
{
    /* 成员变量 */
    char name[20]; // 定义一个结构体类型
    int age;
    char sex[10];
    char id[20];
} s1, s2, s3; //创建三个全局的结构体变量(可以不创建),再次提醒,分号不能丢!

int main()
{
    struct Stu s; // 创建局部的结构体变量

    return 0;
}

结构成员的类型

结构的成员可以是标量、数组、指针,甚至是其他结构体。


#include<stdio.h>
struct Stu 
{
    char name[20];
    int age;
    char sex[10];
    char id[20];
};

struct School
{
    char school_name[30]; // 数组
    struct Stu s; // 结构体
    char* pc; // 地址
};

int main()
{
    char arr[] = "地球\n";
    struct School bili = { "哔哩大学", {"小明", 19, "男", "641664"}, arr };

    printf("校名 - %s\n", bili.school_name);
    printf("学生 - 姓名:%s, 年龄:%d, 性别:%s, 学号:%s\n",bili.s.name,bili.s.age,bili.s.sex,bili.s.id);
    printf("地址 - %s\n", bili.pc);
    return 0;
}

结构体变量的定义和初始化

定义方法:

① 在定义结构体时定义(全局);

② 在创建结构体变量时定义(局部);

初始化方法:使用大括号对结构体进行初始化;


typedef struct Stu 
{
    char name[20]; // 定义一个结构体类型
    int age;
    char sex[10];
    char id[20];
} Stu;

int main()
{
    Stu s1 = { "GR", 19, "男", "35" };// 使用大括号初始化
    Stu s2 = { "小明", 21, "男", "54645661146" };

    return 0;
}

#include<stdio.h>
struct Point
{
    int x;
    int y;
}p1; //声明类型的同时定义变量p1   这里定义的变量都是全局变量,
//把下一行放在mian函数里就是局部变量

struct Point p2; //定义结构体变量p2

//初始化:定义变量的同时赋初值。
struct Point p3 = { 1, 2 };

struct Stu        //类型声明
{
    char name[15];//名字
    int age;      //年龄
};

struct Stu s = { "zhangsan", 20 };//初始化

struct Node
{
    int data;
    struct Point p;
    struct Node* next;
}n1 = { 10, {4,5}, NULL }; //结构体嵌套初始化

struct Node n2 = { 20, {5, 6}, NULL };//结构体嵌套初始化

数据类型定义 typedef


typedef struct Stu 
{
    char name[20];
    int age;
    char sex[10];
    char id[20];
} Stu;

int main()
{
    Stu s1; // 加了之后可以作为一个单独的类型来使用
    struct Stu s2;// 不影响

    return 0;
}

结构体成员的访问

结构变量的成员通过点操作符访问

结构变量的成员通过点操作符(.)访问的。点操作符接受两个操作数。

例如:


#include<stdio.h>
struct Stu 
{
    char name[20];
    int age;
};

int main()
{
    struct Stu s = { "GR", 19 };
    printf("%s\n", s.name);//使用点操作符访问age成员
    printf("%d\n", s.age);//使用点操作符访问age成员
    return 0;
}

结构体指针访问指向变量的成员

有时候我们得到的不是一个结构体变量,而是指向一个结构体的指针。那该如何访问成员。

结构体传参

传参形式:

① 传结构体(使用结构体接收);

② 传地址(使用结构体指针接收);

如果选用传地址,可以通过 箭头操作符 访问

如下:


#include<stdio.h>
struct Stu        //类型声明
{
    char name[20];//名字
    int age;      //年龄
};
void print(struct Stu* ps)
{
    printf("name = %s   age = %d\n", (*ps).name, (*ps).age);
    //使用结构体指针访问指向对象的成员
    printf("name = %s   age = %d\n", ps->name, ps->age);
}
int main()
{
    struct Stu s = { "zhangsan", 20 };
    print(&s);//结构体地址传参
    return 0;
}

传结构体 和 传地址 哪种方法更好些? 答案:传地址更好;

原因:

函数传参的时候,参数是需要压栈的。

如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。

结论:

结构体传参的时候,要传结构体的地址。

知识点完

笔试题

程序的输出结果是:( )


struct stu
{
    int num;
    char name[10];
    int age;
};

void fun(struct stu *p)
{
    printf(“%s\n”,(*p).name);
    return;
}

int main()
{
    struct stu students[3] = {{9801,”zhang”,20},
                              {9802,”wang”,19},
                              {9803,”zhao”,18}
                             };
    fun(students + 1);
    return 0;
}

A.zhang

B.zhao

C.wang

D.18

答案解析:

在main函数中先定义了一个stu结构体类型的数组students,students指向结构体的起始位置,students+1表示该数组中的第一个元素,因此fun的形参实际指向的是students数组中的第一个元素,故打印的是wang

因此:选择C


下面哪个是指针数组:( )

A.int* arr[10];

B.int * arr[];

C.int **arr;

D.int (*arr)[10];

答案解析:

指针数组是一个数组,该数组的每个元素是一个指针

A:正确,定义了一个数组,该数组中有10个元素,每个元素都是int*的指针类型

B:错误,编译失败,定义数组时,要给出空间的大小,如果没有给时,必须要给出初始化结果

C:错误,定义了一个二级指针

D:错误,*和arr先结合,说明arr不是数组。实际上arr是一个指针,一个指向数组的指针。

因此:选择A


打印自幂数(水仙花数)

求出0~100000之间的所有“自幂数”并输出。

自幂数是指一个 n 位数,它的每个位上的数字的 n 次幂之和等于它本身。(例如:当n为3时,有1^3 + 5^3 + 3^3 = 153,153即是n为3时的一个自幂数。)

n为1时,自幂数称为独身数。显然,0,1,2,3,4,5,6,7,8,9都是自幂数;

n为2时,没有自幂数;

n为3时,自幂数称为水仙花数,有4个:153,370,371,407;

n为4时,自幂数称为四叶玫瑰数,共有3个:1634,8208,9474;

n为5时,自幂数称为五角星数,共有3个:54748,92727,93084;

n为6时,自幂数称为六合数,只有1个:548834;

n为7时,自幂数称为北斗七星数,共有4个:1741725,4210818,9800817,9926315;

n为8时,自幂数称为八仙数,共有3个:24678050,24678051,88593477;

n为9时,自幂数称为九九重阳数,共有4个:146511208,472335975,534494836,912985153;

n为10时,自幂数称为十全十美数,只有1个:4679307774。


#include<stdio.h>
#include<math.h>
int main()
{
    for (int i = 0;i <= 100000;i++)
    {
        int tmp = i, sum = 0, n = 1;
        while (tmp /= 10)//1. 求判断数字的位数
        {
            n++;
        }
        tmp = i;
        for (;tmp;tmp /= 10)//2. 计算每一位的次方和
        {
            sum += pow(tmp % 10, n);
        }
        if (sum == i)//3. 判断
            printf("%d ", i);
    }
    return 0;
}

喝汽水问题

喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水(编程实现)。


#include<stdio.h>
int main()
{
    int money = 0, total = 0, empty = 0;//钱,得到的汽水总数,空瓶
    scanf("%d", &money);
    total = money;
    empty = total;
    while (empty > 1)
    {
        total += empty / 2;
        empty = empty / 2 + empty % 2;
    }
    printf("%d", total);
    return 0;
}

打印棱形图案

用C语言在屏幕上输出以下图案:


/*
思路:
仔细观察图形,可以发现,此图形中是由空格和*按照不同个数的输出组成的。
上三角:先输出空格,后输出*,每行中
  空格:从上往下,一行减少一个
  *:2*i+1的方式递增
  
下三角:先输出空格,后输出*,每行中
  空格:从上往下,每行多一个空格
  *: 从上往下,按照2*(line-1-i)-1的方式减少,其中:line表示总共有多少行
按照上述方式,将上三角和下三角中的空格和*分别输出即可。 
*/
#include<stdio.h>
int main()
{
    int line = 0;
    int i = 0;
    scanf("%d", &line);//7
    //打印上半部分
    for(i=0; i<line; i++)
    {
        //打印一行
        //打印空格
        int j = 0;
        for(j=0; j<line-1-i; j++)
        {
            printf(" ");
        }
        //打印*
        for(j=0; j<2*i+1; j++)
        {
            printf("*");
        }
        printf("\n");
    }
    //打印下半部分
    for(i=0; i<line-1; i++)
    {
        //打印一行
        int j = 0;
        for(j=0; j<=i; j++)
        {
            printf(" ");
        }
        for(j=0; j<2*(line-1-i)-1; j++)
        {
            printf("*");
        }
        printf("\n");
    }
    return 0;
}

字符串逆序

写一个函数,使用指针逆序一个字符串的内容。


#include<stdio.h>
#include<string.h>
void reverse(char* p)
{
    int sz = strlen(p);
    int left = 0, right = sz - 1;
    while (left < right)
    {
        int tmp = *(p + left);
        *(p + left) = *(p + right);
        *(p + right) = tmp;
        left++;
        right--;
    }
}
int main()
{
    char arr[50] = { 0 };
    scanf("%s", arr);
    reverse(arr);
    for (int i = 0;i < sizeof(arr) / sizeof(arr[0]);i++)
    {
        printf("%c", arr[i]);
    }
    return 0;
}

本篇完。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GR鲸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值