zoukankan      html  css  js  c++  java
  • 【C语言】学习笔记8——结构struct(1)

    1. 先看个例子

    #include <stdio.h>
    #include <string.h>
    #define MAXTITL 41
    #define MAXAUTL 31
    
    struct book {                   /*结构模板,标记是 book */
        char title[MAXTITL];
        char author[MAXAUTL];
        float value;
    }; 
    
    char * s_gets(char *, int);
    
    int main()
    {
        struct book library;    /* 把 library 声明为一个 book 类型的变量*/
        printf("请输入书的标题:
    ");
        s_gets(library.title, MAXTITL);
        printf("现在输入书的作者姓名:
    ");
        s_gets(library.author, MAXAUTL);
        printf("现在输入书本的价格:
    ");
        scanf("%f", &library.value);
        
        printf("%s by %s: $%.2f
    ", library.title, library.author, library.value);
        printf("%s: "%s"($%.2f)
    ", library.author, library.title, library.value);
        printf("Done.
    ");
        return 0;
     } 
     
     char * s_gets(char *st, int n)
     {
         char * ret_val;
         char * find;
         ret_val = fgets(st, n, stdin);
         if (ret_val)
         {
             find = strchr(st, '
    '); //查找换行符
            if (find)            //如果地址不是NULL 
                *find = '';   //在此放置一个空字符
            else
                while (getchar() != '
    ')
                    continue;    //处理输入行中剩余的字符 
         }
         return ret_val;
     }
     
     /*
     output:
     请输入书的标题:
    我与地坛
    现在输入书的作者姓名:
    史铁生
    现在输入书本的价格:
    20
    我与地坛 by 史铁生: $20.00
    史铁生: "我与地坛"($20.00)
    Done.
     */

    结构变量:为了提高C语言表示数据的能力。

      比如说描述一本书,我们会用一个char数组表示书名, 再用一个char数组表示作者,一个float表示书的描述,但是我们要描述很5本书的时候,我们就得用5个char数组分别表示5本书名,5个char数组表示五本书的作者,5个float表示五本书的价格。这样做很麻烦,而且不容易维护他们之间的关系。所以就有了结构。

      结够有点像面向对象,但是只有属性,没有行为;

    2. 建立结构声明,并声明一个结构变量

    struct book {               /*带标记定义结构,可重用*/   
        char title[MAXTITL];
        char author[MAXAUTL];
        float value;
    }; 
    
    struct book library;
    
    struct {               /*不带标记定义结构, 不可重用*/   
        char title[MAXTITL];
        char author[MAXAUTL];
        float value;
    } library;             /*定义结构的同时,声明一个结构变量。*/

    3. 结构的内存模型

    4. 初始化结构变量

    struct book library = {   /*按顺序初始化*/
        "我与地坛""史铁生"20.00
    };
    
    struct book library = {   /*按成员名称初始化*/
        .value = 20.00,
        .author = "史铁生",
        .title = "我与地坛"
    };
    
    struct book library = {   /*局部初始化*/
        .value = 20.00
    };
    
    struct book library = {   /*瞎j8初始化*/
        .value = 20.00,
        .author = "史铁生"5.00    
    };                 //因为value紧跟author, 最终value = 5.00,

    5. 访问结构的数据,用结构成员运算符 (. )

    6. 声明结构数组

    struct book library[5];

    7.结构数组内存模型

    8. 嵌套结构

    #include <stdio.h>
    #define LEN 20
    
    const char * msgs[5] = 
    {
        "  Thank you for the wonderful evening, ",
        "You certainly prove that a ",
        "is a special kind of guy. We must get together",
        "over a delicious ",
        " and have a few laughs"
    };
    
    struct names{
        char first[LEN];
        char last[LEN];
    }; 
    
    struct guy{
        struct names handle;
        char favfood[LEN];
        char job[LEN];
        float income;
    };
    
    int main()
    {
        struct guy fellow = {
            {"Ewen", "Villard"},
            "grilled salmon",
            "personality coach",
            68112.0
        };
        printf("Dear %s, 
    
    ", fellow.handle.first);
        printf("%s%s.
    ", msgs[0], fellow.handle.first);
        printf("%s%s
    ", msgs[1], fellow.job);
        printf("%s
    ", msgs[2]);
        printf("%s%s%s", msgs[3], fellow.favfood, msgs[4]);
        if (fellow.income > 150000.0)
            puts("!!");
        else if (fellow.income > 75000.0)
            puts("!");
        else
            puts(".");
        
        printf("
    %40s%s
    ", " ", "See you soon,");
        printf("%40s%s
    ", " ", "Shalala");
        
        return 0;
    }
    
    /*
    output:
    Dear Ewen,
    
      Thank you for the wonderful evening, Ewen.
    You certainly prove that a personality coach
    is a special kind of guy. We must get together
    over a delicious grilled salmon and have a few laughs.
    
                                            See you soon,
                                            Shalala
    */

    9. 指向结构的指针

    #include <stdio.h>
    #define LEN 20
    
    struct names{
        char first[LEN];
        char last[LEN];
    }; 
    
    struct guy{
        struct names handle;
        char favfood[LEN];
        char job[LEN];
        float income;
    };
    
    int main()
    {
        struct guy fellows[2] = {
            {
                {"Ewen", "Villard"},
                "grilled salmon",
                "personality coach",
                68112.0
            },
            {
                {"Rondeny", "Swillbelly"},
                "tripe",
                "tabloid editor",
                432400.00
            }
        };
        
        struct guy * him; /* 声明一个指向结构的指针 */
        printf("address #1: %p #2: %p
    ", &fellows[0], &fellows[1]);
        him = &fellows[0];  /* 告诉编译器该指针指向何处 */
        printf("him->income is $%.2f: (*him).income is $%.2f
    ", him->income, (*him).income);
        him++;
        printf("him->favfood is %s: (*him).handle.last is %s
    ", him->favfood, (*him).handle.last);
        return 0;
    }
    
    /*
    output:
    
    address #1: 000000000062FD90 #2: 000000000062FDE4
    him->income is $68112.00: (*him).income is $68112.00
    him->favfood is tripe: (*him).handle.last is Swillbelly
    
    */

    10. 用指针访问结构成员

    struct guy * him;   //声明一个指向结构变量的指针
    
    struct guy barney;
    
    him = &barney;      //让指针指向结构变量barney
    him->income;      //使用 -> 运算符访问结构的成员变量,即 barney.income
    
    (*him).income       //将指针解引用,即barney.income

    11. 向函数传递结构的信息

      a. 传递结构成员

      b. 传递结构地址

      c. 传递结构

    #include <stdio.h>
    #define FUNDLEN 50
    
    struct funds {
        char bank[FUNDLEN];
        double bankfund;
        char save[FUNDLEN];
        double savefund;
    };
    
    double sum1(double, double);
    double sum2(const struct funds *); 
    double sum3(struct funds);
    
    int main()
    {
        struct funds stan = {
            "Garlic-Melon Bank",
            4032.27,
            "Lucky's Savings and Loan",
            8543.94
        };
        printf("Stan has a total if $%.3f.
    ", sum1(stan.bankfund, stan.savefund));  //向函数传递结构成员 
        printf("Stan has a total if $%.3f.
    ", sum2(&stan));  //向函数传递结构的地址 
        printf("Stan has a total if $%.3f.
    ", sum3(stan));  //向函数传递结构
        
        return 0;
    }
    
    double sum1(double x, double y)
    {
        return (x + y);
    }
    
    double sum2(const struct funds * money)
    {
        return (money->bankfund + money->savefund);
    }
    double sum3(struct funds moolah)
    {
        return (moolah.bankfund + moolah.savefund);
    }
    
    /*
    output:
    
    Stan has a total if $12576.210.
    Stan has a total if $12576.210.
    Stan has a total if $12576.210.
    
    --------------------------------
    */

    12.  结构中的字符数组和指针

      假设有一个结构声明

    #define LEN 20
    struct names{
        char first[LEN];
        char last[LEN];
    };

      使用指向char的指针来代替字符数组

    struct pnames{
        char * first;
        char * last;
    };

      这样做是可以的。但是会带来麻烦。考虑以下代码

    struct names veep = {"Talia", "Summers};
    struct pnames treas = {"Brad", "Fallingjaw"};
    printf("%s and %s
    ", veep.first, treas.first);

      代码运行都没有问题,内存分配是怎么做的?

      对于struct names 类型的结构变量 veep , 以上字符串都存储在结构内部,结构总共要分配40字节存储姓名。

      然而对于 struct pnames类型结构变量 treas,以上字符串存储在编译器存储常量的地方,结构本身只存储了两个地址, 在我们的系统中共占16字节(64位系统一个地址是8字节)。 struct pnames 结构不用为字符串分配任何存储空间。他使用的是存储在别处的字符串。

      考虑以下代码

    struct names accountant;
    struct pnames attorney;
    puts("Enter the last name of your accountant:");
    scanf("%s", accountant.last);
    puts("Enter the last name of your attorney:");
    scanf("%s", attorney.last);  //潜在的危险

      用户的输入存储到哪里去了? 

           对于 accountant, 它的姓被存储在names的last中。

      对于 attorney,它的姓被存储在 attorney.last所指向的地址中。由于attorney未被初始化,所以attorney.last可能指向任何一个地址,所以这个操作可能会造成不想要的修改。

      因此,如果要用结构存储字符串,用字符数组作为成员笔记简单。用指向char的指针也行,但是误用会导致严重的问题。

  • 相关阅读:
    auto_ptr解析
    C++ auto_ptr智能指针的用法
    C++ 默认构造函数
    phpdisk 盲注 &前台任意用户登录
    冒泡排序
    关于C++中的友元函数的总结
    python中的闭包
    reverse Polish notation
    PostScript
    sqlite
  • 原文地址:https://www.cnblogs.com/yeyeck/p/9589344.html
Copyright © 2011-2022 走看看