97 votes

Comment éviter de taper enter avec any getchar ()

C'est un "novato" question pour le langage de programmation C:

Dans le code suivant:

#include<stdio.h>

int main(void){   
  int c;   
  while((c=getchar())!= EOF)      
    putchar(c); 
  return 0;
}

J'ai appuyer sur ENTRÉE pour imprimer toutes les lettres que je saisis avec getchar, mais je ne veux pas faire ça, ce que je veux faire est d'appuyer sur la lettre et de voir immédiatement la lettre que j'ai introduit répété sans en appuyant sur ENTRÉE. Par exemple, si j'appuie sur la lettre 'a' je veux voir un autre " a " à côté, et ainsi de suite:

aabbccddeeff.....

Mais quand j'appuie sur " a " rien ne se passe, je peux écrire d'autres lettres et de la copie s'affiche uniquement lorsque j'appuie sur ENTRÉE:

abcdef
abcdef

Comment puis-je faire cela?

Je suis l'aide de la commande cc -o example example.c sous Ubuntu pour la compilation.

124voto

Lucas Points 5723

Cela dépend de votre système d'exploitation, si vous êtes dans un UNIX comme environnement de la ICANON flag est activé par défaut, de sorte que l'entrée est mise en mémoire tampon jusqu'à la prochaine '\n' ou expressions du FOLKLORE. En désactivant le mode canonique, vous obtiendrez les personnages immédiatement. Cela est également possible sur d'autres plates-formes, mais il n'y a pas de droit de l'avant de la croix-plate-forme de solution.

EDIT: je vois que vous avez spécifié que vous utilisez Ubuntu. Je viens de poster quelque chose de similaire hier, mais sachez que cela va désactiver de nombreux comportements par défaut de votre terminal.

#include<stdio.h>
#include <termios.h>            //termios, TCSANOW, ECHO, ICANON
#include <unistd.h>     //STDIN_FILENO


int main(void){   
    int c;   
    static struct termios oldt, newt;

    /*tcgetattr gets the parameters of the current terminal
    STDIN_FILENO will tell tcgetattr that it should write the settings
    of stdin to oldt*/
    tcgetattr( STDIN_FILENO, &oldt);
    /*now the settings will be copied*/
    newt = oldt;

    /*ICANON normally takes care that one line at a time will be processed
    that means it will return if it sees a "\n" or an EOF or an EOL*/
    newt.c_lflag &= ~(ICANON);          

    /*Those new settings will be set to STDIN
    TCSANOW tells tcsetattr to change attributes immediately. */
    tcsetattr( STDIN_FILENO, TCSANOW, &newt);

    /*This is your part:
    I choose 'e' to end input. Notice that EOF is also turned off
    in the non-canonical mode*/
    while((c=getchar())!= 'e')      
        putchar(c);                 

    /*restore the old settings*/
    tcsetattr( STDIN_FILENO, TCSANOW, &oldt);


    return 0;
}

Vous remarquerez, que chaque personnage apparaît deux fois. C'est parce que l'entrée est immédiatement renvoyé à la borne, puis votre programme met de retour avec putchar() aussi. Si vous souhaitez dissocier l'entrée de la sortie, vous avez également à son tour de l'ÉCHO du pavillon. Vous pouvez le faire en changeant simplement la ligne appropriée:

newt.c_lflag &= ~(ICANON | ECHO);

77voto

goldPseudo Points 2479

Sur un système linux, vous pouvez modifier terminal de comportement à l'aide de l' stty commande. Par défaut, le terminal de tampon toutes les informations jusqu'à l' ENTRÉE est pressée, avant même de l'envoyer à la C programme.

Un rapide, sale, et pas particulièrement portatif par exemple, pour modifier le comportement de l'intérieur le programme lui-même:

#include<stdio.h>

int main(void){
  int c;
  /* use system call to make terminal send all keystrokes directly to stdin */
  system ("/bin/stty raw");
  while((c=getchar())!= '.') {
    /* type a period to break out of the loop, since CTRL-D won't work raw */
    putchar(c);
  }
  /* use system call to set terminal behaviour to more normal behaviour */
  system ("/bin/stty cooked");
  return 0;
}

Veuillez noter que ce n'est pas vraiment optimale, car c'est juste suppose qu' stty cooked est le comportement que vous voulez, quand le programme se termine, plutôt que de vérifier ce que les paramètres du terminal ont été. Aussi, depuis tout traitement spécial est ignorée en mode raw, de nombreuses séquences de touches (comme CTRL-C ou CTRL-D) ne sera pas réellement de travail comme vous le souhaitez, sans explicitement le traitement dans le programme.

Vous pouvez man stty pour les plus de contrôle sur le terminal de comportement, selon exactement ce que vous voulez atteindre.

15voto

Eric J. Points 73338

getchar () est une fonction standard et vous oblige à appuyer sur ENTREE pour obtenir l'entrée. De nombreux compilateurs / plates-formes supportent la méthode getch () non standard qui ne nécessite pas ENTER.

6voto

David Thornley Points 39051

I/O est une fonction du système d'exploitation. Dans de nombreux cas, le système d'exploitation ne sera pas le caractère tapé à un programme jusqu'à ce que la touche ENTRÉE est pressée. Cela permet à l'utilisateur de modifier l'entrée (tels que reculer et de retaper) avant de l'envoyer au programme. Dans la plupart des cas, cela fonctionne bien, présente une interface cohérente pour l'utilisateur, et soulage le programme d'avoir à traiter avec cela. Dans certains cas, il est souhaitable qu'un programme pour obtenir les caractères de touches sur lesquelles vous appuyez.

La bibliothèque C de lui-même traite les fichiers, et ne pas se préoccuper de la façon dont les données dans le fichier d'entrée. Par conséquent, il n'y a aucune façon dans la langue elle-même pour obtenir les clés qu'ils sont pressés; au lieu de cela, c'est une plate-forme spécifique. Puisque vous n'avez pas spécifié de l'OS ou le compilateur, on ne peut pas le chercher pour vous.

Aussi, la sortie standard est normalement mis en mémoire tampon pour l'efficacité. Ceci est fait par les bibliothèques C, et donc il y a un C solution, qui est d' fflush(stdout); après chaque caractère écrit. Après cela, si les caractères sont affichés immédiatement est le système d'exploitation, mais tous les Systèmes d'exploitation, je suis familier avec la volonté d'afficher la sortie immédiatement, ce qui n'est pas normalement un problème.

-1voto

Andomar Points 115404

Par défaut, la bibliothèque C met la sortie en mémoire tampon jusqu'à ce qu'elle obtienne un retour. Pour imprimer les résultats immédiatement, utilisez fflush :

 while((c=getchar())!= EOF)      
{
    putchar(c);
    fflush(stdout);
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X