Question

J'écris un programme censé lire deux chaînes pouvant contenir des sauts de ligne et divers autres caractères. Par conséquent, j'utilise EOF (Ctrl-Z ou Ctrl-D) pour terminer la chaîne.

Cela fonctionne bien avec la première variable, mais avec la deuxième variable, toutefois, cela semble poser problème, car quelque chose est apparemment bloqué dans le tampon d'entrée et que l'utilisateur ne peut rien saisir.

J'ai essayé de nettoyer le tampon avec while (getchar ()! = '\ n'); et plusieurs variantes similaires, mais rien ne semble pouvoir vous aider. Toutes les tentatives de nettoyage ont abouti à une boucle infinie et, sans nettoyage, il est impossible d’ajouter la deuxième variable.

Les caractères des deux variables sont lus dans une boucle comme celle-ci: while ((c = getchar ())! = EOF) , ce qui suggérerait que c'est EOF ce que j'ai coincé mon tampon. Ou cela affecte-t-il le comportement du programme d'une autre manière? Y a-t-il quelque chose qui cloche dans la logique que j'utilise?

Je commence à être un peu désespéré après avoir lutté avec cela pendant des heures.

[edit: code ajouté ci-dessous]

[edit 2: clearerr () semble faire fonctionner cette solution EOF après tout.

Il semble fonctionner sous sa forme originale, comme je l'avais prévu sous Linux, je l'essayais avec Windows hier.]

code:

#include <stdio.h>
#include <string.h>

int main(void)
{
    int x = 0;
    int c;
    char a[100];
    char b[100];

    printf("Enter a: ");
    while((c = getchar()) != EOF)
    {
        a[x] = c;
        x++;
    }
    a[x] = '\0';
    x = 0;

    /*while (getchar() != '\n'); - the non-working loop*/

    printf("\nEnter b: ");
    while((c = getchar()) != EOF)
    {
        b[x] = c;
        x++;
    }
    b[x] = '\0';

    printf("\n\nResults:\na: %s\n", a);
    printf("b: %s\n", b);

    return(0);
}

[edit 3:]

Problème de mémoire dynamique:

Mon programme est également supposé gérer des chaînes de plus de 100 caractères. À l’origine, j’avais l’intention de résoudre ce problème par une allocation dynamique de la mémoire, mais lorsque j’ai eu des problèmes avec la boucle infinie décrite ci-dessus et des blocages liés à la mémoire, j’ai omis de le faire et suis passé à char [100].

Je pense que ce que j'ai essayé était généralement quelque chose comme ceci:

while((c = getchar()) != EOF)
{
  a = malloc(sizeof(char));
  a[x] = c;
  x++;
}

Est-ce une façon possible (ou sensée) de faire cela? J'essaie d'allouer plus de mémoire pour chaque personnage traité ici. Individuellement. Avec un code comme celui-ci (cet exemple contient probablement des erreurs de syntaxe), j’ai eu des plantages, j’ai donc l’impression que malloc n’est peut-être pas la bonne fonction ici, ou j’essaye de ne pas le faire. En supposant que ce soit même possible.

Était-ce utile?

La solution

Après avoir reçu une fin de vie du terminal, vous ne recevrez plus de données supplémentaires . Il n’ya aucun moyen de supprimer l’entrée EOF - la fin du fichier est, enfin, la fin.

Vous devez donc définir que chaque variable est entrée sur une ligne distincte, et demander aux utilisateurs d'appuyer sur Entrée au lieu de EOF. Vous devez toujours vérifier si vous avez reçu eof, car cela signifie que l'utilisateur a effectivement saisi EOF et vous ne verrez rien d'autre. Dans ce cas, vous devez sortir de la boucle et imprimer un message d'erreur.

Autres conseils

EOF n'est pas un caractère - il s'agit d'une valeur spéciale que les fonctions d'entrée renvoient pour indiquer une condition , à la fin de laquelle il se termine. du fichier " sur ce flux d'entrée a été atteint. Comme le dit Martin v. L '# 246; wis, une fois que "fin du dossier" Dans ce cas, cela signifie qu'aucune autre entrée ne sera disponible sur ce flux.

La confusion survient parce que:

  • De nombreux types de terminaux reconnaissent une frappe spéciale pour signaler "fin du fichier". lorsque le " fichier " est un terminal interactif (par exemple, Ctrl-Z ou Ctrl-D); et
  • La valeur EOF est l'une des valeurs pouvant être renvoyées par la famille de fonctions getchar () .

Vous devrez utiliser une valeur de caractère réelle pour séparer les entrées - le caractère nul ASCII '\ 0' peut constituer un bon choix, s'il ne peut pas apparaître comme une valeur valide dans le champ. les entrées elles-mêmes.

Je lance le code sur ma machine Linux, voici le résultat:

Enter a: qwer
asdf<Ctrl-D><Ctrl-D>
Enter b: 123
456<Ctrl-D><Ctrl-D>

Results:
a: qwer
asdf
b: 123
456

Deux Ctrl-D étaient nécessaires car le tampon d'entrée du terminal n'était pas vide.

Vous pouvez utiliser le caractère null ( '\ 0' ) pour séparer les variables. Divers outils UNIX (par exemple, find ) sont capables de séparer leurs éléments de sortie de cette manière, ce qui donne à penser qu'il s'agit d'une méthode relativement standard.

Un autre avantage est que vous pouvez lire le flux dans un seul tampon, puis créer un tableau de char * pour qu'il pointe vers les chaînes individuelles et que chaque chaîne sera correctement . '\ 0' - terminé sans que vous ayez à changer quoi que ce soit dans le tampon manuellement. Cela signifie moins de temps d’allocation de mémoire, ce qui peut ralentir considérablement l’exécution de votre programme en fonction du nombre de variables que vous lisez. Bien sûr, cela n’est nécessaire que si vous devez conserver toutes les variables en mémoire en même temps. Si vous les traitez une par une, vous n’obtenez pas cet avantage particulier.

Ce que vous essayez est fondamentalement impossible avec EOF.

Bien qu'il se comporte d'une certaine manière, EOF n'est pas un caractère dans le flux, mais une macro définie par l'environnement représentant la fin du flux. Je n'ai pas vu votre code, mais je suppose que vous faites quelque chose comme ceci:

while ((c=getchar()) != EOF) {
    // do something
}
while ((c=getchar()) != EOF) {
    // do something else
}

Lorsque vous tapez le caractère EOF pour la première fois, le flux est définitivement fermé pour mettre fin à la première chaîne. En d'autres termes, l'état du flux est qu'il est fermé.

Ainsi, le contenu de la seconde boucle while n'est jamais exécuté.

Plutôt que d'arrêter la lecture d'une entrée à EOF - qui n'est pas un caractère - arrêtez-vous à ENTREE.

while((c = getchar()) != '\n')
{
    if (c == EOF) /* oops, something wrong, input terminated too soon! */;
    a[x] = c;
    x++;
}

EOF est un signal indiquant que l'entrée est terminée. Vous êtes presque certain que toutes les entrées de l’utilisateur se terminent par '\ n': c’est la dernière clé saisie par l’utilisateur !!!

Éditer: vous pouvez toujours utiliser Ctrl-D et clearerr () pour réinitialiser le flux d'entrée.

#include <stdio.h>

int main(void) {
  char a[100], b[100];
  int c, k;

  printf("Enter a: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    a[k++] = c;
  }
  a[k] = 0;

  clearerr(stdin);

  printf("Enter b: "); fflush(stdout);
  k = 0;
  while ((k < 100) && ((c = getchar()) != EOF)) {
    b[k++] = c;
  }
  b[k] = 0;

  printf("a is [%s]; b is [%s]\n", a, b);
  return 0;
}
$ ./a.out
Enter a: two
lines (Ctrl+D right after the next ENTER)
Enter b: three
lines
now (ENTER + Ctrl+D)
a is [two
lines (Ctrl+D right after the next ENTER)
]; b is [three
lines
now (ENTER + Ctrl+D)
]
$
  

Comment entrez-vous null dans le programme?

Vous pouvez implémenter la fonction -print0 en utilisant:

putchar(0);

Ceci imprimera un caractère nul '\ 0' ASCII sur tout le reste.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top