2017-06-01 6 views
3

J'ai un programme C qui demande à l'utilisateur son nom avec un bit de code qui lit depuis stdin sur une boucle while (jusqu'à ce que l'entrée soit enfoncée). Je fais que l'utilisateur ne peut entrer des clés des valeurs ASCII de 32 à 126.Prévention des caractères d'échappement ANSI dans l'entrée du clavier en C

Le problème est quand je presse ma flèche (curseur), ou quelque chose comme PAGE_DOWN ou autre ... Je finissent par avoir la norme ANSI séquence d'échappement imprimée sur le terminal ([A, [6 ~, etc.]).

Voici la section du code.

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

J'ai certainement choisi d'ignorer les valeurs ASCII en dehors de la gamme de 32 à 126, alors quelle est la cause de cela? Des idées? À votre santé!

+2

fournir un MCVE _https: //stackoverflow.com/help/mcve_ – CIsForCookies

+0

@CIsForCookies Merci! J'ai ajouté le code approprié, mais je code pour un terminal qui écoute sur un port série, donc le code est un peu différent pour la sortie standard. –

+0

S'il s'agit d'une affectation, laissez le terminal de l'utilisateur seul. Si vous voulez un meilleur UX pour un programme de production, utilisez GNU readline ou une bibliothèque similaire à la place de stdio. –

Répondre

5

Cela fonctionne comme prévu. Avec émulations de terminal de la VT100-famille, pression d'une touche à curseur pour exemple envoie la séquence suivante à votre application:

<ESC>[A 

maintenant, le CES (0x1b) est ce qui est dépouillé, car il est hors de votre Plage valide. Mais les autres caractères sont parfaitement valables. Donc, pour les dépouiller également, votre programme doit reconnaître les codes d'échappement du terminal; une règle facile est de supprimer tous les caractères de l'échappement à la lettre suivante. Cela n'attrapera pas toutes les séquences d'échappement terminales, mais pour le plus commun cela fera l'affaire.

Ici, vous pouvez consulter un list of common terminal control escape sequences

+0

Je vais essayer! Quand vous dites "Cela n'attrape pas toutes les séquences d'échappement terminales", est-ce parce que certaines sont de longueurs différentes? Par exemple, la plupart sont de la forme "[X" mais la page est "[6 ~"? –

+0

@TristanBatchler Différentes longueurs ne sont pas un problème, puisque vous dépouillez toutes jusqu'à la lettre suivante (pas de chiffre!), Mais s'il y a des lettres avant la fin de la séquence, il ne sera pas assez de bande.Mais vous rencontrerez rarement l'un de ces – Ctx

+0

Fantastique! Je viens de commencer à essayer ce que tu as suggéré et ça a déjà l'air bien. Merci d'avoir répondu! –

0

Le code affiché ne contient pas certaines informations clés.

Pour que cette fonctionnalité fonctionne, le code doit modifier le «mode» de la communication avec le terminal.

Le "mode" normal est "cuit" où les frappes de touches sont répercutées sur le terminal et les frappes de touches comme "retour arrière" sont traitées par le pilote du terminal.

Pour activer la fonctionnalité souhaitée, le 'mode' doit être 'brut' et 'echo' doit être désactivé.