2017-06-01 56 views
3

我有一個C程序,用一段代碼在while循環中讀取stdin(直到按下Enter鍵),詢問用戶名字。 我確保用戶只能輸入ASCII值從32到126防止鍵盤輸入中的ANSI轉義字符C

問題是,當我按下箭頭(光標)鍵,或類似的東西PAGE_DOWN或其他... 我最終的ANSI打印到終端的轉義序列([A,[6〜等))。

以下是代碼段。

char name[6]; 
char c; 
uint8_t i = 0; 
while ((c = getchar()) != '\n') { 
    if (c == 127 || c == 8) { // Checks if backspace or del is pressed 
     i--; 
     name[i] = ' '; 
    } else if (c >= 32 && c <= 126) { // Only legal key presses please! 
     name[i] = c; 
     i++; 
    } else { 

    } 

    if ((c >= 32 && c <= 126) || c == 127 || c == 8) { 
     printf_P(PSTR("%c"), c); 
    } 
} 
name[5] = '\0'; 
move_cursor(15, 18); 
printf_P(PSTR("%s"), name); 

我當然選擇忽略32到126範圍以外的ASCII值,那麼這是什麼原因?有任何想法嗎?乾杯!

+2

提供了一個MCVE _https://stackoverflow.com/help/mcve_ – CIsForCookies

+0

@CIsForCookies謝謝!我已經添加了合適的剪切,但是我正在編寫一個在串口上偵聽的終端,所以對於常規的stdout,代碼有點不同。 –

+0

如果是一項任務,請單獨留下用戶的終端。如果您希望生產程序的用戶體驗更好,請使用GNU readline或類似的庫來代替stdio。 –

回答

5

這按預期工作。隨着VT100家庭的終端仿真,一個按鍵來光標向上例如發送下列順序應用程序:

<ESC>[A 

現在,ESC(0x1b)就是被剝奪,因爲它超出了你有效範圍。但其他角色完全有效。因此,爲了也剝離這些,你的程序必須識別終端轉義代碼;一個簡單的規則是將所有字符從轉義字符中刪除到下一個字母。這不會捕獲所有的終端轉義序列,但最常見的做法。

在這裏,您可以查看一個list of common terminal control escape sequences

+0

我會放手一搏!當你說「這不會捕獲所有的終端轉義序列」時,這是因爲有些是不同的長度?例如,大多數表單的形式爲「[X」,但下一頁爲「[6〜」? –

+0

@TristanBatchler不同的長度是沒有問題的,因爲你將所有的字母都去掉(不是數字!),但是如果在序列結束之前有字母,它就不會去掉足夠的字母。但是你很少會遇到其中之一 – Ctx

+0

太棒了!我剛開始嘗試你的建議,並且它已經看起來不錯。感謝你的回答! –

0

張貼的代碼不包含某些關鍵信息。

爲了使此功能正常工作,代碼需要修改與終端通信的'模式'。

正常的'模式'是'熟練的',其中擊鍵回顯到終端,鍵盤筆畫'退格'由終端驅動程序處理。

要啓用所需的功能,'模式'必須是'原始','回聲'必須關閉。