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

简介: 1.如果使用 malloc() 分配内存并使用指针存储该地址,那么在结构中使用指针处理字符串就会显得比较合理。 #include #include // 提供strcpy()、strlen() 的原型 #include // 提供malloc()、free() 的原型...

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. 不要使用带伸缩型数组成员的结构作为数组成员或另一种结构的成员。

 

相关文章
|
4天前
|
存储 编译器 程序员
C语言程序的基本结构
C语言程序的基本结构包括:1)预处理指令,如 `#include` 和 `#define`;2)主函数 `main()`,程序从这里开始执行;3)函数声明与定义,执行特定任务的代码块;4)变量声明与初始化,用于存储数据;5)语句和表达式,构成程序基本执行单位;6)注释,解释代码功能。示例代码展示了这些组成部分的应用。
22 10
|
2天前
|
C语言
C语言程序设计核心详解 第四章&&第五章 选择结构程序设计&&循环结构程序设计
本章节介绍了C语言中的选择结构,包括关系表达式、逻辑表达式及其运算符的优先级,并通过示例详细解释了 `if` 语句的不同形式和 `switch` 语句的使用方法。此外,还概述了循环结构,包括 `while`、`do-while` 和 `for` 循环,并解释了 `break` 和 `continue` 控制语句的功能。最后,提供了两道例题以加深理解。
|
2天前
|
存储 算法 C语言
数据结构基础详解(C语言): 二叉树的遍历_线索二叉树_树的存储结构_树与森林详解
本文从二叉树遍历入手,详细介绍了先序、中序和后序遍历方法,并探讨了如何构建二叉树及线索二叉树的概念。接着,文章讲解了树和森林的存储结构,特别是如何将树与森林转换为二叉树形式,以便利用二叉树的遍历方法。最后,讨论了树和森林的遍历算法,包括先根、后根和层次遍历。通过这些内容,读者可以全面了解二叉树及其相关概念。
|
2天前
|
C语言
C语言程序设计核心详解 第三章:顺序结构,printf(),scanf()详解
本章介绍顺序结构的基本框架及C语言的标准输入输出。程序从`main()`开始依次执行,框架包括输入、计算和输出三部分。重点讲解了`printf()`与`scanf()`函数:`printf()`用于格式化输出,支持多种占位符;`scanf()`用于格式化输入,需注意普通字符与占位符的区别。此外还介绍了`putchar()`和`getchar()`函数,分别用于输出和接收单个字符。
|
2天前
|
存储 机器学习/深度学习 C语言
数据结构基础详解(C语言): 树与二叉树的基本类型与存储结构详解
本文介绍了树和二叉树的基本概念及性质。树是由节点组成的层次结构,其中节点的度为其分支数量,树的度为树中最大节点度数。二叉树是一种特殊的树,其节点最多有两个子节点,具有多种性质,如叶子节点数与度为2的节点数之间的关系。此外,还介绍了二叉树的不同形态,包括满二叉树、完全二叉树、二叉排序树和平衡二叉树,并探讨了二叉树的顺序存储和链式存储结构。
|
29天前
|
C语言
C语言------选择结构
这篇文章是C语言选择结构的入门实训,包括多个练习题及其源代码,旨在帮助读者熟练掌握条件语句和选择结构程序设计方法,并熟悉switch语句和程序调试过程。
C语言------选择结构
|
2月前
|
C语言
|
2月前
|
C语言
|
2月前
|
C语言
C语言学习笔记-W3
w3 条件,循环和数组
24 0
|
2月前
|
编译器 C语言
C语言编程语法—结构
C语言基础概要:令牌包括关键字、标识符、常量、字符串和符号,如`printf(&quot;Hello,World!\n&quot;);`含5个令牌。分号是语句结束符,注释用`/*...*/`包围。标识符是变量等的名称,以字母、下划线开头,后跟字母、数字。C语言有32个关键字,如`int`,空格用于分隔语句元素,提升可读性。
19 0