Ce que j'ai l'intention de faire est de saisir le caractère et de l'utiliser comme motif. J'ai essayé d'utiliser getchar () mais cela ne fonctionnera pas. J'ai entendu parler de scanf mais il saute et s'arrête chaque fois que j'appuie sur "shift" pour les caractères spéciaux sur mon clavier.
int i, j, n;
char c;
c = getchar();
printf("Enter value of n: ");
scanf("%d", &n);
printf("Enter a Character: ");
getchar();
for(i=1; i<=n; i++)
{
for(j=1; j<=i; j++)
{
printf("%c", c);
}
printf("\n");
}
3 Réponses :
Vous devez attribuer la valeur renvoyée par getchar à la variable c , et vous avez eu un appel redondant à getchar c'est pourquoi il saute lecture de l'entrée souhaitée:
int i, j, n;
char c;
printf("Enter value of n: ");
scanf("%d", &n);
printf("Enter a Character: ");
scanf(" %c", &c);
for(i=1; i<=n; i++)
{
for(j=1; j<=i; j++)
{
printf("%c", c);
}
printf("\n");
}
Vous pouvez utiliser % c avec scanf:
scanf("%d %c", &n, %c);
Cela élimine le besoin des deux getchar code > appels.
L'espace est requis ; il dit à scanf d'ignorer les espaces.
Le problème que vous avez est que vos hypothèses sur getchar (3) sont incorrectes. Vous pensez que getchar () va retourner la prochaine touche enfoncée dans le flux d'entrée, mais vous supposez à tort que cela se fera sans mise en mémoire tampon ni traitement système (le pilote du terminal donne au programme des lignes complètes, ou pire encore, si vous lisez à partir d'un fichier, des blocs tampons complets, qui doivent être mis en mémoire tampon pour ne manquer aucun caractère dans le flux d'entrée)
Vous supposez à tort que la fin de ligne sur laquelle vous devez appuyer pour l'entrée être alimenté au programme ne compte pas dans le flux d'entrée.
Ce qui se passe réellement est:
retour . getchar () ou scanf () . L'idée de ce mécanisme de mise en mémoire tampon est de permettre à un programmeur de traiter caractère par caractère de grandes quantités de texte, sans la surcharge de faire un appel système par lecture de caractère (c'est un opération coûteuse), pensez donc à getchar () non pas comme un exemple de fonction pour introduire de nouveaux utilisateurs dans le monde de la programmation, mais comme un indice aux programmeurs expérimentés pour une utilisation efficace sans avoir à penser à mettre en mémoire tampon de grandes quantités de texte.
Avec le package stdio , chaque caractère compte, vous devez donc réfléchir lentement et minutieusement lorsque vous alimentez en entrée getchar (3) .
La question suivante est: Bien, comment puis-je résoudre et arrêter mon programme jusqu'à ce que j'appuie sur une touche? La première réponse, avec l'ensemble des outils que vous avez exposés ici est , faites attention à ce que vous saisissez , au lieu de demander une clé, demandez à l'utilisateur d'appuyer sur la touche retour, puis faites quelque chose comme:
/* pru.c -- program to show raw input from the terminal.
* Author: Luis Colorado <luiscoloradourcola@gmail.com>
* Date: Fri Sep 20 08:46:06 EEST 2019
* Copyright: (C) 2019 Luis Colorado. All rights reserved.
* License: BSD.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h> /* see termios(3) for a description on terminal conf */
#define F(_fmt) __FILE__":%d:%s: " _fmt, __LINE__, __func__
/* this function switches the terminal into raw mode and returns a malloc(3)ed
* terminal configuration, so it can be later restored. BEWARE that the returned
* configuration info must be deallocated by free(3) once it's not needed anymore.
* In case of failure of any system call, the function returns NULL, and errno is
* set to the failing cause. */
struct termios *set_raw(int fd)
{
struct termios *ret = malloc(sizeof *ret), cfg;
if (!ret) return NULL;
int res = tcgetattr(fd, &cfg);
if (res < 0) goto error;
*ret = cfg; /* save it for return */
cfmakeraw(&cfg);
/* set it after all buffered characters in the driver have drained out */
res = tcsetattr(fd, TCSADRAIN, &cfg);
if (res < 0) goto error;
return ret;
error:
free(ret);
return NULL;
} /* set_raw */
/* restores the configuration back to the associated file descriptor */
int restore_cfg(int fd, struct termios *cf)
{
/* set it after all buffered characters in the driver have drained out */
return tcsetattr(fd, TCSADRAIN, cf);
} /* restore_cfg */
int main()
{
struct termios *cfg = set_raw(fileno(stdin));
if (!cfg) {
fprintf(stderr, F("stdin: %s\n"),
strerror(errno));
}
setbuf(stdin, NULL); /* stdin unbuffered */
setbuf(stdout, NULL); /* stdout unbuffered */
/* BEWARE that raw mode doesn't process any characters, so no Ctrl-C(interrupt), Ctrl-D(EOF), etc.
* will be available, only if you read from a file, you'll get EOF, but you'll not be able to produce
* that on the terminal, you'll need to swith to another console and kill the process. */
int c;
while ((c = getchar()) != EOF && c != '\033') { /* ESCAPE key('\033') is a safeguard to end input */
/* print the input char as an hex number */
printf("[%02x]", c);
}
if (cfg) { /* if we were able to set the terminal to raw mode */
/* restore config */
restore_cfg(fileno(stdin), cfg);
/* and free it */
free(cfg);
}
exit(EXIT_SUCCESS);
} /* main */
ou, si vous préférez, vous pouvez écrire un fonction juste pour faire cela (comme il peut y avoir tellement de critères pour l'implémenter, personne n'a inclus une telle fonction dans la bibliothèque C standard, mes excuses pour cela. ;) )
void wait_for_enter()
{
/* I use stderr, for two reasons:
* o stderr is normally unbuffered, so there's no need to fflush()
* o stdout can be redirected, so the prompt will not be visible in
* case you want to save the output of your program.
*/
fprintf(stderr, "Hit <ENTER> to continue");
int c;
while ((c = getchar()) != EOF && c != '\n') {
/* just ignore the character we have received
* until we get the end of file (ctrl-d at the terminal)
* or a new line */
}
/* c == '\n' || c == EOF, so we can continue */
/* it's assumed that the user pressed the enter key, so the echoed
* enter already did a newline, no need to do it here */
} /* wait_for_enter */
Pour attendre n'importe quel caractère et en mode brut, vous devez d'abord vous assurer de votre l'entrée provient d'un terminal (vous ne pouvez pas faire ce qui suit sur un fichier normal), vous devez alors passer le pilote du terminal en mode brut, de sorte que chaque caractère est immédiatement donné au programme et aucun traitement d'édition de ligne n'est effectué, puis définissez le stdin descripteur pour pas de mise en mémoire tampon du tout. Ce n'est qu'alors que vous pouvez recevoir des caractères individuels avec getchar (3) , un par un, tels quels saisi. Je pense que cela sort du cadre de cette question, car le code pour faire cela est beaucoup plus complexe que celui ci-dessus.
Voici un exemple complet d'un programme qui utilise une entrée brute pour traiter les caractères au fur et à mesure qu'ils sont saisis.
printf("Hit <ENTER> to continue"); fflush(stdout); /* so we get the line out, bypassing the buffering mechanism */
int c;
while ((c = getchar()) != EOF && c != '\n') {
/* just ignore the character we have received */
}
/* c == '\n' || c == EOF, so we can continue */
Le code source complet peut également être téléchargé depuis ici .
Vous pouvez utiliser ce programme pour voir comment les touches de saisie sont mappées en caractères, car vous noterez que lorsque vous appuyez sur la touche enter , l'entrée brute est [0d] ( ascii char 13, CARRY RETURN) en mode ligne normale, vous obtenez '\ n' qui est [0a] ou ASCII LINE FEED, à la place (vous pouvez vérifier ceci si vous rediriger l'entrée du fichier texte pru.c ). Vous verrez également que vous ne pouvez pas spécifier EOF depuis le pilote du terminal avec Ctrl-D et que Ctrl-C ne vient pas à Aidez-moi. Eh bien, j'ai inclus une sauvegarde, en terminant le programme au cas où vous appuyez sur la touche ESC , qui génère un caractère ASCII ESCAPE ( \ 033 ). Ceci est également commenté dans le code source.
Tout ce traitement est effectué par le pilote du noyau, donc toutes les implémentations unix obtiennent les mêmes caractères de fin de ligne ou interprètent les caractères de contrôle de la même manière.
double l'instruction
getchar ();pour consommer le saut de ligne du scanf précédent. Ces fonctions de scan C sont délicatesPardon, que voulez-vous dire par mais cela ne fonctionnera pas ? Quel est le comportement attendu de votre programme? quel est celui observé? Croyez-moi,
getchar ()fonctionne , mais parfois vos hypothèses sur ce que l'on attend de lui sont fausses, il est donc très important d'exprimer à quoi vous attendez-vous, car l'erreur est probablement là.