經典的字符菜單交互模式,包含:選項顯示、輸入驗證、功能分發、輸入緩衝清理。
#include <stdio.h>
char get_choice(void);
char get_first(void);
int get_int(void);
void count(void);
int main() {
int choice;
while ((choice = get_choice()) != 'q') {
switch (choice) {
case 'a': printf("Buy low, sell high\n"); break;
case 'b': putchar('\a'); break; // 蜂鳴器
case 'c': count(); break;
default: printf("Invalid choice\n"); break;
}
}
printf("Bye.\n");
return 0;
}
// 計數功能
void count(void) {
int n, i;
printf("Count how far? Enter an integer: ");
n = get_int();
for (i = 1; i <= n; i++) printf("%d\n", i);
while (getchar() != '\n') continue; // 清理緩衝區
}
// 獲取合法選項
char get_choice(void) {
char ch;
printf("Enter the letter of your choice:\n");
printf("a. advice b. bell\n");
printf("c. count d. quit\n");
ch = get_first();
while ((ch < 'a' || ch > 'c') && ch != 'q') {
printf("Please respond with a, b, c, or q\n");
ch = get_first();
}
return ch;
}
// 獲取首個非換行字符
char get_first(void) {
char ch = getchar();
while (getchar() != '\n') continue; // 丟棄行內剩餘字符
return ch;
}
// 獲取合法整數
int get_int(void) {
int input;
char ch;
while (scanf("%d", &input) != 1) {
while ((ch = getchar()) != '\n') putchar(ch); // 回顯錯誤輸入
printf(" is not an integer.\nPlease enter an integer (e.g. 25, -178, 3): ");
}
return input;
}
get_first()char get_first(void) {
char ch = getchar();
while (getchar() != '\n') continue; // 關鍵:讀取並丟棄直到換行
return ch;
}
解決 scanf/getchar 留下的換行符干擾後續輸入問題。
get_int()while (scanf("%d", &input) != 1) { // 返回值非1表示匹配失敗
while ((ch = getchar()) != '\n') putchar(ch); // 回顯非法字符
printf(" is not an integer...\n");
}
scanf 返回成功匹配的項數,非 1 即格式錯誤get_choice():只負責顯示菜單、獲取並驗證選項main():只負責分發調用count())獨立實現| 需求 | 實現方向 |
|---|---|
| 子菜單 | 菜單函數返回枚舉/結構體,main 狀態機調度 |
| 動態菜單 | 選項存結構體數組:{鍵, 描述, 函數指針} |
| 輸入歷史/編輯 | 使用 readline 庫或自行實現行編輯 |
| 本地化 | 菜單字串外置資源文件,運行時加載 |
scanf/getchar 後必須清理到 '\n'getchar() 返回 EOF 時應退出,避免死循環tolower(ch) 統一gets(),用 fgets() 或手寫長度限制