14.结构体

14.复杂数据类型-结构体


14.1 知识点

基本概念

结构体

结构体是一种自定义变量类型,类似枚举需要自己定义。它是数据和函数的集合,用于表现存在关系的数据集合,例如学生、动物、人类等。

基本语法

结构体一般写在 namespace 语句块中

  • 结构体关键字 struct
  • 结构体名采用帕斯卡命名法
// struct 自定义结构体名
// {
//     // 第一部分
//     // 变量
//     // 第二部分
//     // 构造函数(可选)
//     // 第三部分 
//     // 函数
// }

实例

声明结构体和声明结构体变量

  • 声明结构体相当于创建自定义变量类型
  • 声明结构体变量相当于使用自定义变量类型声明变量
namespace YourNamespace
{
    // 声明表现学生数据的结构体
    struct Student
    {
        // 变量
        public int age;
        public bool sex;
        public int number;
        public string name;

        // 构造函数
        // 函数方法
        public void Speak()
        {
            // 函数中可以直接使用结构体内部声明的变量
            Console.WriteLine("我的名字是{0},我今年{1}岁", name, age);
        }

        // 可以根据需求写无数个函数的
    }
}

结构体的使用

主函数内
  • 声明结构体变量
  • 修改结构体变量的内部变量
  • 调用结构体的函数
  • 使用结构体的构造函数声明结构体变量
// 变量类型 变量名;
Student s1;

// 修改结构体变量的内部变量
s1.age = 10;
s1.sex = false;
s1.number = 1;
s1.name = "韬老狮";

// 调用结构体的函数
s1.Speak();

// 使用结构体的构造函数声明结构体变量
Student s2 = new Student(18, true, 2, "小红");
s2.Speak();

访问修饰符

  • 修饰结构体中变量和方法是否能被外部使用
  • public:公共的,可以被外部访问
  • private:私有的,只能在内部使用,默认不写为私有

构造函数

基本概念

  • 没有返回值
  • 函数名必须和结构体名相同
  • 必须有参数
  • 如果声明了构造函数,必须在其中对所有变量数据初始化

结构体语句块内

// 构造函数一般是用于在外部方便初始化的
public Student(int age, bool sex, int number, string name)
{
    // 新的关键字 this 
    // 代表自己
    this.age = age;
    this.sex = sex;
    this.number = number;
    this.name = name;
}

总结

  • 概念: 结构体 struct 是变量和函数的集合,用来表示特定的数据集合。
  • 访问修饰符: publicprivate 用来修饰变量和方法,public 外部可以调用,private 内部用,不写的话默认是私有。
  • 构造函数: 没有返回值,函数名和结构体名相同,可以重载,主要帮助快速初始化结构体对象。注意在结构体中声明的变量不能初始化,只能在外部或者在函数中赋值(初始化)。在结构体中声明的函数不需要加 static

14.2 知识点代码

using System;

namespace Lesson12_结构体
{
    #region 知识点一 基本概念
    //结构体 是一种自定义变量类型  类似枚举需要自己定义
    //它是数据和函数的集合
    //在结构体中 可以声明各种变量和方法

    //作用:用来表现存在关系的数据集合 比如用结构体表现学生 动物 人类等等
    #endregion

    #region 知识点二 基本语法
    //1.结构体一般写在 namespace语句块中
    //2.结构体关键字 struct

    //struct 自定义结构体名
    //{
    //    // 第一部分
    //    // 变量

    //    // 第二部分
    //    // 构造函数(可选)

    //    // 第三部分 
    //    // 函数
    //}
    // 注意 结构体名字 我们的规范 是 帕斯卡命名法
    #endregion

    #region 知识点三 实例
    // 声明结构体 和 声明结构体变量 也是两个概念
    // 声明结构体 可以理解为 自己创造一个变量类型
    // 声明结构体变量 可以理解为 拿自己写的变量类型声明变量进行所使用

    //namespace语句块内 class语句块外

    // 声明 表现学生数据 的 结构体
    struct Student
    {
        #region 知识点五 访问修饰符
        //修饰结构体中变量和方法 是否能被外部使用
        //public 公共的 可以被外部访问
        //private 私有的 只能在内容使用
        //默认不写 为private
        #endregion


        //变量
        //结构体声明的变量 不能直接初始化
        //变量类型 可以写任意类型 包括结构体 但是 不能是自己的结构体 可以是其它的
        //Student s;// 不能是自己的结构体
        //年龄
        public int age;
        //性别
        public bool sex;
        //学号
        public int number;
        //姓名
        public string name;

        //构造函数
        #region 知识点六 结构体的构造函数
        //基本概念
        //1.没有返回值
        //2.函数名必须和结构体名相同
        //3.必须有参数
        //4.如果声明了构造函数 那么必须在其中对所有变量数据初始化

        //结构体语句块内
        //构造函数 一般是用于在外部方便初始化的
        public Student(int age, bool sex, int number, string name)
        {
            //新的关键字 this 
            //代表自己
            this.age = age;
            this.sex = sex;
            this.number = number;
            this.name = name;
        }

        #endregion

        //函数方法
        //表现这个数据结构的行为

        //注意 在结构体中的方法 目前不需要加static关键字 
        public void Speak()
        {
            //函数中可以直接使用结构体内部声明的变量
            Console.WriteLine("我的名字是{0},我今年{1}岁", name, age);
        }
        //可以根据需求 写无数个函数的
    }

    #endregion


   

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("结构体");

            #region 知识点四 结构体的使用
            //主函数内

            //声明结构体变量
            //变量类型 变量名;
            Student s1;

            //修改结构体变量的内部变量
            //要将结构体变量的内部变量的访问修饰符改成public才能在外部进行修改和访问
            s1.age = 10;
            s1.sex = false;
            s1.number = 1;
            s1.name = "韬老狮";

            //调用结构体的函数
            //要将结构体的函数的访问修饰符改成public才能在外部进行修改和访问
            s1.Speak();

            //使用结构体的构造函数声明结构体变量
            Student s2 = new Student(18, true, 2, "小红");
            s2.Speak();
            #endregion
        }
    }

    // 总结
    // 概念:结构体 struct 是变量和函数的集合 用来表示特定的数据集合

    // 访问修饰符: public 和private 用来修饰变量和方法的 public 外部可以调用 private内部用 不写的话默认就是private
    // 构造函数 : 没有返回值 函数名和结构体名相同 可以重载 主要是帮助我们快速初始化结构体对象的

    // 注意:
    // 1.在结构体中声明的变量 不能初始化  只能在外部或者在函数中赋值(初始化)
    // 2.在结构体中声明的函数 不用加static的
}

14.3 练习题

使用结构体描述学员的信息,姓名,性别,年龄,班级,专业,创建两个学员对象,并对其基本信息进行初始化并打印

namespace 语句块内 class 语句块外

struct Student
{
    public string name;
    public bool sex;
    public int age;
    public int clas;
    public string major;

    public Student(string name, bool sex, int age, int clas, string major)
    {
        this.name = name;
        this.sex = sex;
        this.age = age;
        this.clas = clas;
        this.major = major;
    }

    public void Speak()
    {
        Console.WriteLine("姓名:{0} 性别:{1} 年龄:{2} 班级:{3} 专业:{4}", name, sex ? "女" : "男", age, clas, major);
    }
}

主函数内

Student s1 = new Student("韬老狮", false, 18, 3, "软件工程");
s1.Speak(); // 输出:姓名:韬老狮 性别:男 年龄:18 班级:3 专业:软件工程

Student s2;
s2.name = "小明";
s2.sex = false;
s2.age = 10;
s2.clas = 1;
s2.major = "网络工程";
s2.Speak(); // 输出:姓名:小明 性别:男 年龄:10 班级:1 专业:网络工程

请简要描述 private 和 public 两个关键字的区别

  • 他们都是访问修饰符,用来修饰变量和函数。
  • 如果默认不写访问修饰符,则为 private。
  • private: 私有的,被它修饰的变量和函数只能在结构体内部使用,外部无法使用。
  • public: 公共的,被它修饰的变量和函数能在内外都访问。

使用结构体描述矩形的信息,长,宽;创建一个矩形,对其长宽进行初始化,并打印矩形的长、宽、面积、周长等信息。

namespace 语句块内 class 语句块外

struct Rect
{
    public float w;
    public float h;
    public float area;
    public float perimeter;

    public Rect(int w, int h)
    {
        this.w = w;
        this.h = h;
        area = w * h;
        perimeter = 2 * (w + h);
    }

    public void WriteInfo()
    {
        Console.WriteLine("该矩形宽为{0}高为{1}面积为{2}周长为{3}", w, h, area, perimeter);
    }
}

主函数内

Rect r = new Rect(5, 4);
r.WriteInfo(); // 输出:该矩形宽为5高为4面积为20周长为18

用结构体描述玩家信息,玩家名字,玩家职业。请用户输入玩家姓名,选择玩家职业,最后打印玩家的攻击信息

namespace 语句块内 class 语句块外

// 声明玩家职业枚举
enum E_Occupation
{
    Warrior,
    Hunter,
    Master,
}

// 声明玩家信息结构体
struct PlayerInfo
{
    public string name;
    public E_Occupation occupation;

    public PlayerInfo(string name, E_Occupation occupation)
    {
        this.name = name;
        this.occupation = occupation;
    }

    public void Atk()
    {
        string o = "";
        string s = "";
        switch (occupation)
        {
            case E_Occupation.Warrior:
                o = "战士";
                s = "冲锋";
                break;
            case E_Occupation.Hunter:
                o = "猎人";
                s = "假死";
                break;
            case E_Occupation.Master:
                o = "法师";
                s = "奥术冲击";
                break;
            default:
                o = "无职业者";
                s = "无招胜有招";
                break;
        }
        Console.WriteLine("{0}{1}释放了{2}", o, name, s);
    }
}

主函数内

Console.WriteLine("请输入你的姓名");
string name = Console.ReadLine();
Console.WriteLine("请输入职业(0战士 1猎人 2法师)");
try
{
    E_Occupation o = (E_Occupation)int.Parse(Console.ReadLine());
    // 根据输入的内容初始化了一个玩家对象
    PlayerInfo info = new PlayerInfo(name, o);
    info.Atk();
}
catch
{
    Console.WriteLine("请输入数字");
}

使用结构体描述小怪兽

namespace 语句块内 class 语句块外

struct Monster
{
    public string name

;
    public int atk;

    public Monster(string name)
    {
        this.name = name;
        Random r = new Random();
        atk = r.Next(10, 30);
    }

    public void Atk()
    {
        Console.WriteLine("{0}的攻击力是{1}", name, atk);
    }
}

定义一个数组存储10个上面描述的小怪兽,每个小怪兽的名字为(小怪兽+数组下标)

主函数内

Monster[] monsters = new Monster[10];
for (int i = 0; i < monsters.Length; i++)
{
    monsters[i] = new Monster("小怪兽" + i);
    monsters[i].Atk();
}

实现奥特曼打小怪兽

namespace 语句块内 class 语句块外

// 声明奥特曼结构体
struct OutMan
{
    public string name;
    public int atk;
    public int def;
    public int hp;

    public OutMan(string name, int atk, int def, int hp)
    {
        this.name = name;
        this.atk = atk;
        this.def = def;
        this.hp = hp;
    }

    // 结构体是值类型,想要在函数内部改变值类型信息,外部受影响,一定记住用 ref 或者 out
    public void Atk(ref Boss monster)
    {
        // 奥特曼打小怪兽的逻辑
        monster.hp -= atk - monster.def;
        Console.WriteLine("{0}攻击了{1},造成了{2}伤害,{3}剩余血量{4}", name, monster.name, atk - monster.def, monster.name, monster.hp);
    }
}

// 声明怪兽结构体
struct Boss
{
    public string name;
    public int atk;
    public int def;
    public int hp;

    public Boss(string name, int atk, int def, int hp)
    {
        this.name = name;
        this.atk = atk;
        this.def = def;
        this.hp = hp;
    }

    public void Atk(ref OutMan outMan)
    {
        // 小怪兽打奥特曼的逻辑
        outMan.hp -= atk - outMan.def;
        Console.WriteLine("{0}攻击了{1},造成了{2}伤害,{3}剩余血量{4}", name, outMan.name, atk - outMan.def, outMan.name, outMan.hp);
    }
}

主函数内

OutMan outMan = new OutMan("雷欧奥特曼", 10, 5, 100);
Boss boss = new Boss("哥斯拉", 8, 4, 100);

while (true)
{
    outMan.Atk(ref boss);
    if (boss.hp <= 0)
    {
        Console.WriteLine("{0}胜利", outMan.name);
        break;
    }
    boss.Atk(ref outMan);
    if (outMan.hp <= 0)
    {
        Console.WriteLine("{1}胜利", boss.name);
        break;
    }
    Console.WriteLine("按任意键继续");
    Console.ReadKey(true);
}

14.4 练习题代码

using System;

namespace Lesson12_练习题
{
    #region 练习题一
    //使用结构体描述学员的信息,姓名,性别,年龄,班级,专业,
    //创建两个学员对象,并对其基本信息进行初始化并打印

    //namespace语句块内 class语句块外
    struct Student
    {
        public string name;
        public bool sex;
        public int age;
        public int clas;
        public string major;

        public Student(string name, bool sex, int age, int clas, string major)
        {
            this.name = name;
            this.sex = sex;
            this.age = age;
            this.clas = clas;
            this.major = major;
        }

        public void Speak()
        {
            Console.WriteLine("姓名:{0}性别:{1}年龄:{2}班级:{3}专业:{4}", name, sex ? "女":"男", age, clas, major);
        }
    }
    #endregion

    #region 练习题二
    //请简要描述private和public两个关键字的区别

    // 他们都是访问修饰符 用来修饰变量和函数的
    // 如果默认不写访问修饰符 则为private
    // private 私有的 被它修饰的变量和函数只能在结构体内部使用 外部无法使用  
    // public 公共的 被它修饰的变量和函数 能在内外都访问
    #endregion

    #region 练习题三
    //使用结构体描述矩形的信息,长,宽;创建一个矩形,
    //对其长宽进行初始化,并打印矩形的长、宽、面积、周长等信息。

    //namespace语句块内 class语句块外
    struct Rect
    {
        public float w;
        public float h;
        public float area;
        public float perimeter;

        public Rect(int w, int h)
        {
            this.w = w;
            this.h = h;
            area = w * h;
            perimeter = 2 * (w + h);
        }

        public void WriteInfo()
        {
            Console.WriteLine("该矩形宽为{0}高为{1}面积为{2}周长为{3}", w, h, area, perimeter);
        }
    }
    #endregion

    #region 练习题四
    //使用结构体描述玩家信息,玩家名字,玩家职业
    //请用户输入玩家姓名,选择玩家职业,最后打印玩家的攻击信息
    //职业:
    //战士(技能:冲锋)
    //猎人(技能:假死)
    //法师(技能:奥术冲击)

    //打印结果:猎人韬老狮释放了假死

    //namespace语句块内 class语句块外
    //声明玩家信息结构体
    struct PlayerInfo
    {
        public string name;
        public E_Occupation occupation;

        public PlayerInfo(string name, E_Occupation occupation)
        {
            this.name = name;
            this.occupation = occupation;
        }

        public void Atk()
        {
            string o = "";
            string s = "";
            switch (occupation)
            {
                case E_Occupation.Warrior:
                    o = "战士";
                    s = "冲锋";
                    //Console.WriteLine("战士{0}释放了冲锋");
                    break;
                case E_Occupation.Hunter:
                    o = "猎人";
                    s = "假死";
                    //Console.WriteLine("猎人{0}释放了假死");
                    break;
                case E_Occupation.Master:
                    o = "法师";
                    s = "奥术冲击";
                    //Console.WriteLine("法师0}释放了奥数冲击");
                    break;
                default:
                    o = "无职业者";
                    s = "无招胜有招";
                    break;
            }
            Console.WriteLine("{0}{1}释放了{2}", o, name, s);
        }
    }

    //声明玩家职业枚举
    enum E_Occupation
    {
        /// <summary>
        /// 战士
        /// </summary>
        Warrior,
        /// <summary>
        /// 猎人
        /// </summary>
        Hunter,
        /// <summary>
        /// 法师
        /// </summary>
        Master,
    }
    #endregion

    #region 练习题五
    //使用结构体描述小怪兽

    //namespace语句块内 class语句块外

    struct Monster
    {
        public string name;
        public int atk;

        public Monster(string name)
        {
            this.name = name;
            Random r = new Random();
            atk = r.Next(10, 30);
        }

        public void Atk()
        {
            Console.WriteLine("{0}的攻击力是{1}", name, atk);
        }
    }
    #endregion

    #region 练习题六
    //定义一个数组存储10个上面描述的小怪兽,每个小怪兽的名字为(小怪兽+数组下标)
    //举例:小怪兽0,最后打印10个小怪兽的名字+攻击力数值
    #endregion

    #region 练习题七
    //应用已学过的知识,实现奥特曼打小怪兽
    //提示:
    //结构体描述奥特曼与小怪兽
    //定义一个方法实现奥特曼攻击小怪兽
    //定义一个方法实现小怪兽攻击奥特曼

    //namespace语句块内 class语句块外

    //声明奥特曼结构体
    struct OutMan
    {
        public string name;
        public int atk;
        public int def;
        public int hp;

        public OutMan(string name, int atk, int def, int hp)
        {
            this.name = name;
            this.atk = atk;
            this.def = def;
            this.hp = hp;
        }

        //结构体是值类型 想要在函数内部改变值类型信息 外部受影响 一定 记住 用 ref或者out
        public void Atk( ref Boss monster )
        {
            //奥特曼打小怪兽的逻辑
            monster.hp -= atk - monster.def;
            Console.WriteLine("{0}攻击了{1},造成了{2}伤害,{3}剩余血量{4}", name, monster.name, atk - monster.def, monster.name, monster.hp);
        }
    }

    //声明怪兽结构体
    struct Boss
    {
        public string name;
        public int atk;
        public int def;
        public int hp;

        public Boss(string name, int atk, int def, int hp)
        {
            this.name = name;
            this.atk = atk;
            this.def = def;
            this.hp = hp;
        }

        public void Atk(ref OutMan outMan)
        {
            //小怪兽打奥特曼的逻辑
            outMan.hp -= atk - outMan.def;
            Console.WriteLine("{0}攻击了{1},造成了{2}伤害,{3}剩余血量{4}", name, outMan.name, atk - outMan.def, outMan.name, outMan.hp);
        }
    }

    #endregion

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("结构体练习题");

            #region 练习题一
            //主函数内

            Student s1 = new Student("韬老狮", false, 18, 3, "软件工程");
            s1.Speak();//姓名:韬老狮性别:男年龄:18班级:3专业:软件工程

            Student s2;
            s2.name = "小明";
            s2.sex = false;
            s2.age = 10;
            s2.clas = 1;
            s2.major = "网络工程";
            s2.Speak();
            //姓名:小明性别:男年龄:10班级:1专业:网络工程

            #endregion

            #region 练习题三
            //主函数内

            Rect r = new Rect(5, 4);
            r.WriteInfo();
            //该矩形宽为5高为4面积为20周长为18
            #endregion

            #region 练习题四
            //主函数内

            Console.WriteLine("请输入你的姓名");
            string name = Console.ReadLine();
            Console.WriteLine("请输入职业(0战士 1猎人 2法师)");
            try
            {
                E_Occupation o = (E_Occupation)int.Parse(Console.ReadLine());
                //根据输入的内容初始化了一个玩家对象
                PlayerInfo info = new PlayerInfo(name, o);
                info.Atk();
            }
            catch
            {
                Console.WriteLine("请输入数字");
            }
            #endregion

            #region 练习题六
            //主函数内
            //变量类型[] 数组名 = new 变量类型[10];
            Monster[] monsters = new Monster[10];
            for (int i = 0; i < monsters.Length; i++)
            {
                monsters[i] = new Monster("小怪兽" + i);
                monsters[i].Atk();
            }

            #endregion

            #region 练习题七
            //主函数内

            OutMan outMan = new OutMan("雷欧奥特曼", 10, 5, 100);
            Boss boss = new Boss("哥斯拉", 8, 4, 100);

            while(true)
            {
                outMan.Atk(ref boss);
                if( boss.hp <= 0 )
                {
                    Console.WriteLine("{0}胜利",outMan.name);
                    break;
                }
                boss.Atk(ref outMan);
                if (outMan.hp <= 0)
                {
                    Console.WriteLine("{1}胜利", boss.name);
                    break;
                }
                Console.WriteLine("按任意键继续");
                Console.ReadKey(true);
            }
            #endregion

        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏