14.结构和其他数据类型

14.2 创建结构声明

struct book{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};
//结构布局

14.3 定义结构变量

struct book library;//结构变量

struct book{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
} library;  //声明的简化

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

14.3.1 初始化结构

struct book library = {
    "yds",
    "wwh",
    12.1
}; //初始化用的逗号

14.3.2 访问结构成员

library.title;
library.author;
....

14.3.3 结构初始化器

struct book library = {
    .author = "yds";
    0.25;//接着下一个初始化,即是value
};

14.4 结构数组

14.4.1 声明结构数组

struct book library[40];

14.4.2 标识结构数组的成员

library[0].value

14.5嵌套结构

struct names {
    char first[LEN];
    char last[LEN];
};
struct guy {
    struct names handle;
    char favfood[LEN];
    char job[LEN];
    float income;
};

/*初始化*/
struct guy fellow = {
    {"wang","hao"},
    "xigua",
    "student",
    "600"
}

14.6 指向结构的指针

14.6.1 声明初始化指针

struct guy *him;//声明
him = &barney;//赋值
  • 和数组不同,结构变量名并不是结构的地址,因此要加&运算符

14.6.2 用指针访问成员

  1. 用->运算符
  2. (*).
struct guy *him;
him = &barney;
barney.income == him->income == (*him).income

14.7 向函数传递结构信息

程序员可以选择传递结构本身,还可以传递指向结构的指针,也可以把结构的成员作为参数

函数不仅可以把结构本身作为参数传递,还可以把结构作为返回值返回

14.7.5 结构和结构指针的选择

  • 指针参数的优缺点:
  1. 执行速度快
  2. 无法保护数据,不过ANSIC新增的const限制符解决了这个问题
  • 结构作为参数的优点:
  1. 函数处理的是原始数据的副本,保护数据。
  2. 代码风格清楚

14.7.6 结构中的字符数组和结构指针

#define LEN 20
struct names{
    char first[LEN];
    char last[LEN];
};
struct pnames{
    char *first;
    char *last;
};
struct names veep = {"talia","summer"};
struct pnames treas = {"brad","fallingjaw"};

对于veep,以上字符串都存储在结构内部,结构总共分配40字节存姓名,然而,对于treas,以上字符都存储在编译器存储常量的位置,结构本身只存储两个地址,总共占16字节

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

14.7.7 结构、指针和malloc()

void getinfo (struct namect * pst)
{
    char temp[SLEN];
    printf("Please enter your first name.\n");
    s_gets(temp, SLEN);
    pst->fname = (char *) malloc(strlen(temp) + 1);//分配内存,加1存储/0
    strcpy(pst->fname, temp);
    printf("Please enter your last name.\n");
    s_gets(temp, SLEN);
    pst->lname = (char *) malloc(strlen(temp) + 1);
    strcpy(pst->lname, temp);
}
//事后记得free()释放内存

14.7.8 复合字面量和结构

如果需要一个临时结构值,符合字面量就很好用,语法就是类型名放在圆括号中,后面紧跟一个用花括号括起来的初始化列表。

(struct book){"bkname","bkzuthor",9.9};
  • 举例
if(score >= 84)
    readfirst = (struct book) {"Crime and Punishment",
                                "Fyodor Dostoyevsky",
                                11.25};
else
    readfirst = (struct book) {"Mr. Bouncy's Nice Hat",
                                "Fred Winsome",
                                5.99};

14.7.9 伸缩型数组成员

该成员不会立即存在,但程序员通过合适的代码,就好像他确实存在所需数目的元素一样

  • 声明一个伸缩性数组成员有如下规则:
  1. 伸缩性数组成员必须是最后一个成员
  2. 结构中必须存在至少一个成员
  3. 伸缩性数组成员类似普通数组,只是方括号是空的
struct flex
{
    int count;
    double average;
    double score[];//伸缩型数组成员
};
struct flex *pf;//声明一个指针
pf = malloc(sizeof(struct flex)+5*sizeof(double)); //请求为一个结构和一个数组分配空间
pf->count = 5;
pf->score[2] = 18.5;
  • 注意事项
  1. 不能用结构进行赋值或拷贝
  2. 不要按值的方式把结构传递给结构,要把结构的地址传递给函数
  3. 不要把带伸缩型数组成员的结构作为数组成员或另一个结构的成员

14.7.10 匿名结构

struct person{
    int id;
    struct{char first[20];char last[20];};
};//声明
struct person ted = {124,{"asd","saq"}} //初始化
puts(ted.first); //访问时就当是ted的成员

14.7.11 使用结构数组的函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXTITL  40
#define MAXAUTL  40
#define MAXBKS   10             /* 书籍数量的最大值 */
char * s_gets(char * st, int n);
struct book {                   /* 声明书的结构   */
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

int main(void)
{
    struct book library[MAXBKS]; /* 结构数组    */
    int count = 0;
    int index, filecount;
    FILE * pbooks;
    int size = sizeof (struct book);
    
    if ((pbooks = fopen("book.dat", "a+b")) == NULL) //二进制读写模式打开,只可以在末尾写
    {
        fputs("Can't open book.dat file\n",stderr);
        exit(1);
    }
    
    rewind(pbooks);            /* 回到文件开头 */
    while (count < MAXBKS &&  fread(&library[count], size,
                                    1, pbooks) == 1) //
    {
        if (count == 0)
            puts("Current contents of book.dat:");
        printf("%s by %s: $%.2f\n",library[count].title,
               library[count].author, library[count].value);
        count++;
    }  //输出文件现有的书籍
    filecount = count;
    if (count == MAXBKS)
    {
        fputs("The book.dat file is full.", stderr);
        exit(2);
    }
    
    puts("Please add new book titles.");
    puts("Press [enter] at the start of a line to stop.");
    while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL
           && library[count].title[0] != '\0')
    {
        puts("Now enter the author.");
        s_gets(library[count].author, MAXAUTL);
        puts("Now enter the value.");
        scanf("%f", &library[count++].value);
        while (getchar() != '\n')
            continue;                /* 清空多余输入  */
        if (count < MAXBKS)
            puts("Enter the next title.");
    }
    
    if (count > 0)
    {
        puts("Here is the list of your books:");
        for (index = 0; index < count; index++)
            printf("%s by %s: $%.2f\n",library[index].title,
                   library[index].author, library[index].value);
        fwrite(&library[filecount], size, count - filecount,
               pbooks); //写入新增的书籍
    }
    else
    	puts("No books? Too bad.\n");
    
    puts("Bye.\n");
    fclose(pbooks);
    
    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');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '\0';          // place a null character there
        else
            while (getchar() != '\n')
                continue;          // dispose of rest of line
    }
    return ret_val;
}

14.9 链式结构

通常每个结构包含一两项数据和一两个指向其他同类型的指针,这些指针把一个结构和另一个结构链接起来

14.10 联合简介

和结构类似,在同一个内存空间存储不同的数据类型,但不是同时存储

union hold{
    int digit;
    double bigfl;
    char letter;
} //联合只能存储一个int,或double,或char,但会分配占用最大字节的类型的空间,上例皆会分配一个double类型的空间,即8字节

14.11 枚举类型

。。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值