首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C 語言鍵盤映射修正:輸入錯位字串還原原始輸入完整解析

     編輯:程式設計綜合問答

經典 C 語言練習:輸入鍵盤上向右偏移一鍵的字串,輸出原始意圖字串。開發者困惑於 for 迴圈中 i 變化邏輯。本文完整解析程式流程、修正語法錯誤並優化實作。

題目需求

  • 鍵盤佈局參考字串:"1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./"
  • 輸入:使用者實際按下的鍵 (向右偏移一位)
  • 輸出:使用者原本想輸入的字元 (向左對應一位)
  • 範例:輸入 W → 輸出 Q (因 W 在參考字串中位於 Q 右側)

原始代碼問題分析

// 原始有語法錯誤
while ((c = getchar()) != EOF) {
    for (i = 1; s[i] && s[i] != c; i++);  // ← 分號導致迴圈體為空!
    {
        if (s[i]) putchar(s[i - 1]);      // ← 這塊脫離 for 迴圈,只執行一次
    }
}

關鍵錯誤:for (...) ; 尾隨分號

  • for (i = 1; s[i] && s[i] != c; i++); → 空迴圈體,i 直接跑到條件失敗為止
  • 隨後的 { if (s[i]) putchar(s[i-1]); } 是**獨立區塊**,非迴圈體
  • 結果:i 直接跳到找到字元或字串結尾的位置,再輸出前一字元

修正版代碼

#include <stdio.h>
#include <stdlib.h>

char *s = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./"; // 加上 ` 鍵 (ESC 下方)

int main() {
    int i, c;
    while ((c = getchar()) != EOF) {
        // 移除分號,大括號包裹迴圈體
        for (i = 1; s[i] && s[i] != c; i++) {
            // 迴圈體為空,僅尋找位置
        }
        // 迴圈結束後,i 停在找到的位置或字串結尾
        if (s[i]) {           // 找到字元 (非結尾 \0)
            putchar(s[i - 1]); // 輸出左側鄰居
        }
        // 否則:輸入字元不在映射表中 (如 Enter、Ctrl 等),不輸出
    }
    return 0;
}

執行流程追蹤:輸入 W

步驟ci 初值s[i]條件 s[i] && s[i]!=ci 變化迴圈結束 i輸出
1'W'1'1'真i=2--
...'W'......真遞增--
N'W'15'W'假 (s[i]!=c 為假)不變15-
迴圈後-----15s[14] = 'Q'Q

優化版:預建映射表 O(1) 查找

#include <stdio.h>

int main() {
    char *ref = "`1234567890-=QWERTYUIOP[]\\ASDFGHJKL;'ZXCVBNM,./";
    char map[256] = {0}; // ASCII 映射表
    
    // 建立映射:右鍵 -> 左鍵
    for (int i = 1; ref[i]; i++) {
        map[(unsigned char)ref[i]] = ref[i - 1];
    }
    // 特殊鍵處理 (空格、換行等保持原樣)
    map[' '] = ' '; map['\n'] = '\n'; map['\t'] = '\t';
    
    int c;
    while ((c = getchar()) != EOF) {
        if (map[c]) putchar(map[c]);
        else putchar(c); // 不在映射表中,原樣輸出
    }
    return 0;
}

優化版優勢

常見邊界情況處理

  • 輸入字元不在映射表 (如中文、功能鍵) → 原樣輸出或忽略
  • 映射表首字元 (`) 無左鄰居 → 映射表從索引 1 開始建立,` 不會被輸出 (符合題意)
  • 大小寫敏感 → 參考字串為大寫,輸入小寫需轉大寫查找再轉回
  • 反斜桿轉義 → 字串中需寫 \\\\ 代表單一 \

總結

原始代碼核心問題是 for 迴圈**尾隨分號導致迴圈體為空**,使 i 直接跳至目標位置。修正分號並理解「迴圈尋找位置、迴圈後輸出左鄰居」的兩階段邏輯即可。工程實務中,**預建映射表**以空間換時間、簡化邏輯、提升擴展性,是更優解法。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
指標原版 (線性搜尋)優化版 (映射表)
時間複雜度O(n × m) n=輸入長度, m=映射表長度(~47)O(n) 單次查找
程式碼複雜度巢狀迴圈、易出邊界錯單層迴圈、邏輯清晰
擴展性修改映射需改搜尋邏輯修改 ref 字串自動重建