结构体 结构数组 指向结构的指针

结构体

/* book.c -- 一本书的图书目录 */
#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n);
#define MAXTITL  41      /* 书名的最大长度 + 1    */
#define MAXAUTL  31      /* 作者姓名的最大长度 + 1*/

struct book {            /* 结构模版:标记是 book */
     char title[MAXTITL];
     char author[MAXAUTL];
     float value;
};                       // 结构模版结束
int main(void){
     struct book library;    //把 library 声明为一个 book 类型的变量 
     printf("Please enter the book title.\n");
     s_gets(library.title, MAXTITL);        /* 访问title部分*/
     printf("Now enter the author.\n");
     s_gets(library.author, MAXAUTL);
     printf("Now enter the value.\n");
     scanf("%f", &library.value);
     printf("%s by %s: $%.2f\n", library.title,
          library.author, library.value);
     printf("%s: \"%s\" ($%.2f)\n", library.author,
             library.title, library.value);
     printf("Done.\n");
}  
char * s_gets(char * st, int n){
     char * ret_val;
     char * find;
     ret_val = fgets(st, n, stdin);
     if (ret_val) {
          find = strchr(st, '\n');     // 查找换行符
          if (find)                    // 如果地址不是 NULL,
               *find = '\0';           // 在此处放置一个空字符
          else
               while (getchar() != '\n')
                    continue;          //处理输入行中剩余的字符
     }
     return ret_val;
}

输出

Please enter the book title.
enter
Now enter the author.
retne
Now enter the value.
23
enter by retne: $23.00
retne: "enter" ($23.00)
Done.

定义

是一种既能包含字符串又能包含数字的数据形式;还要保持各种信息的独立

结构的含义

Ⅰ结构布局

结构布局告诉编译器如何表示数据,并未让编译器为数据分配空间

把library声明为一个使用book结构布局的结构变量;该变量的结构布局为book

解构成员可以是任意一种c的数据类型,也可以是其他结构

#include <stdio.h>
#define maxtitle 41
#define maxauthor 31
struct book{ //本质:book结构声明创建了一个名为struct book的新类型
    char title[maxtitle];
    char author[maxauthor];
    float value;
};
int main(){
    struct book library; //把library声明为一个使用book结构布局的结构变量 ;book称为标记
}

Ⅱ创建结构变量

struct book library; 

struct book起的功能相当与int float;

可以定义两个struct book类型的变量甚至指针

struct book doyle,pan,*ptbook;

*简化

条件:只存在一个变量时

声明结构的过程和定义结构变量的过程可以组合成一个步骤。如下所示,组合后的结构声明和结构变量定义不需要使用结构标记:

struct { /* 无结构标记 */
     char title[MAXTITL];
     char author[MAXAUTL];
     float value;
} library;

初始化

结构变量可初始化;各初始化项用逗号隔开,独占一行;对特定成员的最后一次赋值才是它实际获得的值

第一种

struct book library = {
     "The Pious Pirate and the Devious Damsel",
     "Renee Vivotte",
     1.95
};

第二种

struct book gift= {.value = 18.90,
                   .author = "Philionna Pestle",
                   0.25
                  };

访问

使用结构成员运算符——点(.)访问结构中的成员

例如,library.value即访问library的value部分。可以像使用float类型变量一样使用
本质上.title、.author和.value的作用相当于book结构的下标

scanf(“%f”,…)需要一个float类型变量的地址,而&library.float正好符合要求

s_gets(library.title, MAXTITL);
scanf("%f", &library.value); //.比&的优先级高,因此这个表达式和&(library.float)一样

结构的指定初始化器使用点运算符和成员名(而不是方括号和下标)标识特定的元素

可以按照任意顺序使用指定初始化器;最后一次赋值为准

struct book surprise = { .value = 10.99};

嵌套结构

#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 {                   // 第1个结构
     char first[LEN];
     char last[LEN];
};
struct guy {                     // 第2个结构
     struct names handle;        // 嵌套结构
     char favfood[LEN];
     char job[LEN];
     float income;
};
int main(void){
     struct guy fellow = {        // 初始化一个结构变量
               { "Ewen", "Villard" },
               "grilled salmon",
               "personality coach",
               68112.00
     };
     printf("Dear %s, \n\n", fellow.handle.first);
     printf("%s%s.\n", msgs[0], fellow.handle.first);
     printf("%s%s\n", msgs[1], fellow.job);
     printf("%s\n", 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("\n%40s%s\n", " ", "See you soon,");
     printf("%40s%s\n", " ", "Shalala");
}
//下面是该程序的输出:
//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

访问

 printf("Dear %s, \n\n", fellow.handle.first);

结构数组

/* manybook.c -- 包含多本书的图书目录 */
#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n);
#define MAXTITL   40
#define MAXAUTL   40
#define MAXBKS   100         /* 书籍的最大数量  */

struct book {                /* 建立 book 模板     */
     char title[MAXTITL];
     char author[MAXAUTL];
     float value;
};

int main(void){
     struct book library[MAXBKS];    /*  book 类型结构的数组 */
     int count = 0;
     int index;

     printf("Please enter the book title.\n");
     printf("Press [enter] at the start of a line to stop.\n");
     while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL
          && library[count].title[0] != '\0'){ //弥补了scanf函数遇到空格和换位符就结束读取的问题
          printf("Now enter the author.\n");
          s_gets(library[count].author, MAXAUTL);
          printf("Now enter the value.\n");
          scanf("%f", &library[count++].value);
          while (getchar() != '\n')
               continue;        /* 清理输入行*/
          if (count < MAXBKS)
               printf("Enter the next title.\n");
     }

     if (count > 0){
          printf("Here is the list of your books:\n");
          for (index = 0; index < count; index++)
               printf("%s by %s: $%.2f\n", library[index].title,
               library[index].author, library[index].value);
     }
     else
          printf("No books? Too bad.\n");
     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, '\n');    // 查找换行符
          if (find)                   // 如果地址不是 NULL,
               *find = '\0';          // 在此处放置一个空字符
          else
               while (getchar() != '\n')
                    continue;         // 处理输入行中剩余的字符
     }
     return ret_val;
}
Please enter the book title.
Press [enter] at the start of a line to stop.​​My Life as a Budgie​​Now enter the author.​​Mack Zackles​​Now enter the value.​​12.95​​Enter the next title.
...(此处省略了许多内容)...
Here is the list of your books:
My Life as a Budgie by Mack Zackles: $12.95
Thought and Unthought Rethought by Kindra Schlagmeyer: $43.50
Concerto for Financial Instruments by Filmore Walletz: $49.99
The CEO Power Diet by Buster Downsize: $19.25
C++ Primer Plus by Stephen Prata: $59.99
Fact Avoidance: Perception as Reality by Polly Bull: $19.97
Coping with Coping by Dr. Rubin Thonkwacker: $0.02
Diaphanous Frivolity by Neda McFey: $29.99
Murder Wore a Bikini by Mickey Splats: $18.95
A History of Buvania, Volume 8, by Prince Nikoli Buvan: $50.04
Mastering Your Digital Watch, 5nd Edition, by Miklos Mysz: $28.95
A Foregone Confusion by Phalty Reasoner: $5.99
Outsourcing Government: Selection vs. Election by Ima Pundit: $33.33​​

栈大小的潜在问题

声明结构数组

library为数组名,该数组中每个元素都是struct book类型的结构变量

struct book library[MAXBKS];

标识结构数组的成员

采用访问单独结构的规则

library[0].value;
library.value[2];//错误示范
library[2].value[4]; //第三个结构变量的title中的第5个字符
library[2]; //一个数组元素,为book结构

指向结构的指针

#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(void){
     struct guy fellow[2] = {
               { { "Ewen", "Villard" },
                    "grilled salmon",
                    "personality coach",
                    68112.00
               },
               { { "Rodney", "Swillbelly" },
                    "tripe",
                    "tabloid editor",
                    432400.00
               }
     };
     struct guy * him;        /* 这是一个指向结构的指针 */

     printf("address #1: %p #2: %p\n", &fellow[0], &fellow[1]);
     him = &fellow[0];        /* 告诉编译器该指针指向何处  */
     printf("pointer #1: %p #2: %p\n", him, him + 1);
     printf("him->income is $%.2f: (*him).income is $%.2f\n",
               him->income, (*him).income);
     him++;                /* 指向下一个结构      */
     printf("him->favfood is %s:  him->handle.last is %s\n",
               him->favfood, him->handle.last);
}

输出

address #1: 0x7fff5fbff820 #2: 0x7fff5fbff874
pointer #1: 0x7fff5fbff820 #2: 0x7fff5fbff874
him->income is $68112.00: (*him).income is $68112.00
him->favfood is tripe: him->handle.last is Swillbelly

好处

指向结构的指针通常比结构本身更容易操作;

传递指针通常更有效率;

一些用于表示数据的结构中包含指向其他结构的指针

声明和初始化

声明

该声明并未创造一个新的结构,指针him可以指向任意现有的guy类型结构

struct guy * him;        //关键字 struct 结构标记guy

初始化

him=&barney; //结构变量名并不是结构变量的地址
him=&barney[0]; //barney为一个结构数组时可行

访问

第一种 ->

如果 him==&barney 那么 him->income 即是访问barney.income
如果 him==&fellow[0] 那么 him->income 即是访问fellow[0].income

P.S. 不能写成him.income

him->income为float类型的变量

第二种

fellow[0].income==(*him).income; //.比*优先级高
barney.income == (*him).income == him->income // 假设 him == &barney
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值