本文精選 9 道涵蓋結構體、聯合體、嵌套結構、函數指針、數組排序等核心考點的經典例題,附帶詳細解析與標準化代碼。適合期末複習、面試準備、嵌入式開發基礎夯實。
設計結構體保存書名、作者、價格;演示三種初始化方式;修改價格並輸出。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char title[100];
char author[50];
double price;
} Book_t;
void print_book(const Book_t *b) {
printf("Title: %s\nAuthor: %s\nPrice: %.2f\n\n", b->title, b->author, b->price);
}
int main(void) {
// 1. 完全初始化(順序依賴)
Book_t doyle = {"My Life as a Budgie", "Mack Tom", 14.6};
// 2. 部分初始化(其餘零初始化)
Book_t dicken = {"Thinking in C++", "Stephen Prata", 78.0};
// 3. C99 指定初始化器(推薦,順序無關)
Book_t panshin = {
.title = "C++ Primer",
.author = "Stanley Lippman",
.price = 92.5
};
print_book(&doyle);
print_book(&dicken);
print_book(&panshin);
// 修改價格
printf("Adjusting price of \"Thinking in C++\"...\n\n");
dicken.price = 85.0;
print_book(&dicken);
return EXIT_SUCCESS;
}
#define MAX_TITLE 100
#define MAX_AUTHOR 50
typedef struct {
char title[MAX_TITLE];
char author[MAX_AUTHOR];
double price;
} Book_t;
void book_show(const Book_t *b) {
printf("Title: %s\nAuthor: %s\nPrice: %.2f\n", b->title, b->author, b->price);
}
void book_init(Book_t *b, const char *title, const char *author, double price) {
strncpy(b->title, title, MAX_TITLE - 1);
b->title[MAX_TITLE - 1] = '\0';
strncpy(b->author, author, MAX_AUTHOR - 1);
b->author[MAX_AUTHOR - 1] = '\0';
b->price = price;
}
int book_input(Book_t *b) {
printf("Title: ");
if (!fgets(b->title, MAX_TITLE, stdin)) return 0;
b->title[strcspn(b->title, "\n")] = '\0'; // 去除換行
printf("Author: ");
if (!fgets(b->author, MAX_AUTHOR, stdin)) return 0;
b->author[strcspn(b->author, "\n")] = '\0';
printf("Price: ");
char buf[32];
if (!fgets(buf, sizeof(buf), stdin)) return 0;
b->price = atof(buf);
return 1;
}
使用結構體數組管理多本書,結合上述函數:
#define MAX_BOOKS 100
int main(void) {
Book_t library[MAX_BOOKS];
int count = 0, i;
// 初始化預設數據
book_init(&library[count++], "Book1", "Author1", 10.0);
book_init(&library[count++], "Book2", "Author2", 20.0);
book_init(&library[count++], "Book3", "Author3", 30.0);
// 用戶輸入新書
while (count < MAX_BOOKS && book_input(&library[count])) {
count++;
}
// 顯示所有
for (i = 0; i < count; i++) {
printf("--- Book %d ---\n", i + 1);
book_show(&library[i]);
}
return 0;
}
車輛可能是私家車(有車主信息)或租賃車(有公司信息),二者互斥,用聯合體節省空間。
typedef struct {
char name[50];
char gender[10];
char buy_date[20];
} Owner_t;
typedef struct {
char name[50];
char tel[20];
} Company_t;
typedef union {
Owner_t owner;
Company_t lease;
} OwnerInfo_t;
typedef struct {
char make[30];
int status; // 0: 私家車, 1: 租賃車
OwnerInfo_t info;
} CarData_t;
int main(void) {
CarData_t car = {
.make = "Volvo",
.status = 0,
.info.owner = {"Robert Carter", "M", "2008-11-21"}
};
if (car.status == 0)
printf("Owner: %s, Gender: %s, Buy Date: %s\n",
car.info.owner.name, car.info.owner.gender, car.info.owner.buy_date);
else
printf("Lease Co: %s, Tel: %s\n",
car.info.lease.name, car.info.lease.tel);
return 0;
}
typedef struct {
char company[100];
float diameter;
float weight;
} Pizza_t;
int main(void) {
Pizza_t p;
printf("Company: "); fgets(p.company, sizeof(p.company), stdin);
p.company[strcspn(p.company, "\n")] = '\0';
printf("Diameter: "); scanf("%f", &p.diameter);
printf("Weight: "); scanf("%f", &p.weight);
printf("\n--- Pizza Info ---\n");
printf("Company: %s\nDiameter: %.2f\nWeight: %.2f\n", p.company, p.diameter, p.weight);
return 0;
}
結構同圖書系統,將 `Book_t` 替換為 `Student_t`(姓名、年級、分數),邏輯完全一致。重點掌握:
原代碼存在多個嚴重錯誤:
typedef struct {
int year, month, day;
} Date_t;
typedef struct {
char title[100];
char author[50];
Date_t pub_date;
char publisher[100];
int lent, stock;
} BookEx_t;
int date_cmp(const Date_t *a, const Date_t *b) {
if (a->year != b->year) return a->year - b->year;
if (a->month != b->month) return a->month - b->month;
return a->day - b->day;
}
void sort_books(BookEx_t *books, int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (date_cmp(&books[j].pub_date, &books[j+1].pub_date) > 0) {
BookEx_t tmp = books[j];
books[j] = books[j+1];
books[j+1] = tmp;
}
}
}
}
原代碼邏輯錯誤:聯合體成員共用內存,`f.a = a; sum += f.a; f.b = b; sum += f.b;` 會導致 `f.a` 被覆蓋。聯合體不適合同時保存兩個操作數。
聯合體用於同一內存區域的不同解釋,如:
typedef struct { double a, b; } Operands_t;
double add(Operands_t op) { return op.a + op.b; }
double sub(Operands_t op) { return op.a - op.b; }
double mul(Operands_t op) { return op.a * op.b; }
double div(Operands_t op) { return op.b != 0 ? op.a / op.b : NAN; }
// 多數運算:使用數組或鏈表存儲操作數