天天看點

【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. 不要使用帶伸縮型數組成員的結構作為數組成員或另一種結構的成員。

繼續閱讀