【C语言】学习笔记9——结构struct(2)

1.如果使用 malloc() 分配内存并使用指针存储该地址,那么在结构中使用指针处理字符串就会显得比较合理。

#include <stdio.h>
#include <string.h>     // 提供strcpy()、strlen() 的原型
#include <stdlib.h>     // 提供malloc()、free() 的原型
#define SLEN 81

struct namect {
    char * fname;
    char * lname;
    int letters;
}; 

void getinfo(struct namect *);
void makeinfo(struct namect *);
void showinfo(const struct namect *);
void cleanup(struct namect *);
char * s_gets(char *, int );

int main()
{
    struct namect person;
    getinfo(&person);
    makeinfo(&person);
    showinfo(&person);
    cleanup(&person);
    return 0;
}

void getinfo(struct namect * pst)
{
    char temp[SLEN];
    printf("Please enter your first name:\n");
    s_gets(temp, SLEN);
    
    //分配内存以存储first name
    pst->fname = (char *) malloc(strlen(temp) + 1);
    //把first name 拷贝到分配的动态内存中 
    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);
}

void makeinfo(struct namect * pst)
{
    pst->letters = strlen(pst->fname) + strlen(pst->lname);
}

void showinfo(const struct namect *pst){
    printf("%s %s, your name contains %d letters.\n", pst->fname, pst->lname, pst->letters);
}


void cleanup(struct namect * pst)
{
    free(pst->fname);
    free(pst->lname);
}


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; 
        
}

/*
output:
Please enter your first name:
James
Please enter your last name:
Harden
James Harden, your name contains 11 letters.
*/

2.复合字面量和结构:C99 的复合类型字面量特性可用于结构和数组。如果只需要一个临时结构值,符合字面量很好用。 可以把复合字面量创建一个数组作为函数的参数,或赋值给另一个结构。

下面是struct book 类型的复合字面量

#define MAXTITL 41
#define MAXAUTL 31

struct book{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
}; 

(struct book) {"Crime and Punishment", "Fyodor Dostoyevsky", 11.25};         /* 使用复合字面量给赋值*/
#include <stdio.h>
#define MAXTITL 41
#define MAXAUTL 31

struct book{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
}; 

int main()
{
    struct book readfirst;
    int score;
    
    printf("Enter test score: ");
    scanf("%d", &score);
    
    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
        };
    
    printf("Your assigned reading:\n");
    printf("%s by %s: $%.2f\n", readfirst.title, readfirst.author, readfirst.value);
    return 0;
}

/*
output:
Enter test score: 100
Your assigned reading:
Crime and Punishment by Fyodor Dostoyevsky: $11.25
*/ 

3. 伸缩型数据成员

  声明一个伸缩型数组成员必须遵守如下规则:

  a. 伸缩型数组成员必须是结构的最后一个成员;

  b. 结构中必须至少有一个成员;

  c. 伸缩数组的声明类似于普通数组,只是他的方括号中是空的。

struct flex
{
    int count;
    double average;
    double scores[];
};

  声明一个struct flex类型的结构变量时, 不能用scores做任何事,因为没有给这个数组预留存储空间。 这个用法的意图并不是让你声明struct flex 类型的变量, 而是希望你声明一个指向struct flex类型的指针,然后用malloc()来分配足够的空间,以存储struct flex类型结构的常规内容和伸缩型数组成员所需的额外空间。例如

struct flex * pf;   //声明一个指向 struct flex的指针
pf = malloc(sizeof(struct flex) + 5 * sizeof(double)); //请求为一个结构和一个数组分配存储空间

  然后你就有足够的存储空间去存储count, average 和 5个double类型的数组。用指针访问这些成员

pf->count = 5;            //设置count成员
pf->scores[2] = 18.5; //访问数组成员的一个元素

   但是, 带伸缩型数组成员的结构确实有一些特殊的处理要求

    a. 不能用结构进行赋值或拷贝   

struct flex *pf1, * pf2;
...
*pf2 = *pf1 //不要这样做,这样做只能拷贝伸缩型数组成员以外的其它成员。应使用memcpy()函数

    b. 不要按值方式把这种结构传递给结构

    c. 不要使用带伸缩型数组成员的结构作为数组成员或另一种结构的成员。

 

上一篇:【算法导论】最大子数组——暴力求解


下一篇:Blend 3状态为空的解决方法