結構體(struct)與聯合體(union)是 C 語言構建複雜數據模型的核心工具。本文通過 9 道遞進式例題,系統講解結構體定義、初始化、指針操作、函數封裝、數組管理、嵌套聯合體設計、動態輸入輸出及排序算法集成,幫助開發者建立完整的結構體編程思維。
struct Books {
char title[100];
char author[20];
double price;
};
// 1. 順序初始化
struct Books doyle = {"My life as a budgie", "Mack Tom", 14.6};
// 2. 變量定義時初始化
struct Books dicken = {"Thinking in C++", "Stephen Prata", 78};
// 3. C99 指定初始化器 (推薦,順序無關、可讀性強)
struct Books panshin = {
.title = "C++ Primer",
.author = "Stanley Lippman",
.price = 92.5
};
printf("Title: %s\nAuthor: %s\nPrice: %.1f\n",
dicken.title, dicken.author, dicken.price);
// 修改價格
dicken.price = 85;
#include
#include
struct Library {
char title[50];
char author[30];
double price;
};
// 顯示函數:const 指針承諾不修改
void show(const struct Library *book) {
printf("Title: %s\nAuthor: %s\nPrice: %.1f\n",
book->title, book->author, book->price);
}
// 初始化函數:靜態默認值
void init(struct Library *book) {
strcpy(book->title, "Unknown");
strcpy(book->author, "Anonymous");
book->price = 0.0;
}
// 輸入函數:返回狀態碼,處理輸入錯誤
int input(struct Library *book) {
printf("Enter title: ");
if (scanf("%49s", book->title) != 1) return 0;
printf("Enter author: ");
if (scanf("%29s", book->author) != 1) return 0;
printf("Enter price: ");
if (scanf("%lf", &book->price) != 1) return 0;
return 1;
}
int main() {
struct Library books[3];
for (int i = 0; i < 3; i++) {
init(&books[i]);
if (!input(&books[i])) {
fprintf(stderr, "Input error for book %d\n", i+1);
return EXIT_FAILURE;
}
}
for (int i = 0; i < 3; i++) show(&books[i]);
return 0;
}
#include
#include
#include
struct Date { int year, month, day; };
struct Book {
char title[100];
char author[50];
struct Date pub_date;
char publisher[100];
int lent_count;
int stock_count;
};
// 比較函數:按年月日升序
int cmp_books(const void *a, const void *b) {
const struct Book *pa = a, *pb = b;
if (pa->pub_date.year != pb->pub_date.year)
return pa->pub_date.year - pb->pub_date.year;
if (pa->pub_date.month != pb->pub_date.month)
return pa->pub_date.month - pb->pub_date.month;
return pa->pub_date.day - pb->pub_date.day;
}
int main() {
int n;
printf("Number of books: ");
scanf("%d", &n);
struct Book *books = malloc(n * sizeof(struct Book));
if (!books) { perror("malloc"); return 1; }
for (int i = 0; i < n; i++) {
printf("Book %d:\n", i+1);
scanf("%99s %49s %d %d %d %99s %d %d",
books[i].title, books[i].author,
&books[i].pub_date.year, &books[i].pub_date.month, &books[i].pub_date.day,
books[i].publisher,
&books[i].lent_count, &books[i].stock_count);
}
qsort(books, n, sizeof(struct Book), cmp_books);
for (int i = 0; i < n; i++) {
printf("%s | %s | %04d-%02d-%02d | %s | Lent:%d | Stock:%d\n",
books[i].title, books[i].author,
books[i].pub_date.year, books[i].pub_date.month, books[i].pub_date.day,
books[i].publisher, books[i].lent_count, books[i].stock_count);
}
free(books);
return 0;
}
同例題 2-4 模式,定義 Student 結構,實現 show()、init()、input(),主函數驅動流程。關鍵點:
const struct Student* 保護只讀操作。scanf 返回值,防止格式錯誤導致數據破損。%19s)防止緩衝區溢出。
struct Owner {
char name[50];
char gender; // 'M'/'F'
char buy_date[20];
};
struct Company {
char name[50];
char phone[20];
};
union OwnerInfo {
struct Owner owner;
struct Company company;
};
struct CarData {
char make[30];
int status; // 0=私有, 1=租賃
union OwnerInfo info;
};
// 使用示例
struct CarData mycar = {
.make = "Volvo",
.status = 0,
.info.owner = {"Robert Carter", 'M', "2008-11-21"}
};
// 訪問:必須先檢查 status
if (mycar.status == 0) {
printf("Owner: %s\n", mycar.info.owner.name);
}
注意:此例僅演示聯合體語法,實際計算器不應使用聯合體(數值並非互斥)。
union Calc {
int a, b;
} reg;
int add(int a, int b) {
reg.a = a; reg.b = b;
return reg.a + reg.b; // 等價於 a + b
}
// sub, mul, div 同理
正確設計應直接使用參數運算,聯合體適用於「同一時刻僅一種數據有效」的場景(如協議解析、異構數據存儲)。
const。init/input/show),實現數據與行為的邏輯聚合。qsort 實現高效排序。status/type)區分活動成員,實現類多態。scanf("%49s", buf)、檢查返回值、清理輸入緩衝區。#pragma pack。