首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言結構體與聯合體經典例題全解析(含 9 大題型)

     編輯:關於C語言

前言

本文精選 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;
}

題目二:圖書管理函數化(show / init / input)

設計要點

  • 所有函數接受結構體指針,避免結構體拷貝開銷
  • `init` 負責默認值設置,`input` 處理用戶輸入,`show` 格式化輸出
  • 輸入處理需防緩衝區溢出(使用 `fgets` + `sscanf` 或寬度限制)

#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`(姓名、年級、分數),邏輯完全一致。重點掌握:

  • 結構體指針作為函數參數
  • 輸入緩衝區處理(`fgets` + `strcspn` 去換行)
  • 指定初始化器優雅創建對象

題目八:圖書數組按出版日期排序

關鍵修正點

原代碼存在多個嚴重錯誤:

  • 變長數組 (VLA) `book[n]` 在 `n` 未初始化前聲明 → 未定義行為
  • `scanf("%s", &book[i].data)` 對結構體成員錯誤,應分別讀取年月日
  • 排序邏輯比較 `publishunit`(出版社字符串)而非日期
  • 排序內輸出導致重複打印

正確實現


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` 被覆蓋。聯合體不適合同時保存兩個操作數。

正確理解聯合體用途

聯合體用於同一內存區域的不同解釋,如:

  • 端序檢測:`union { int i; char c[4]; }`
  • 類型懲罰:`union { float f; uint32_t u; }` 查看浮點數位模式
  • 節省空間的互斥字段(如題目四)

正確的計算器實現


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

// 多數運算:使用數組或鏈表存儲操作數
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved