Problème avec L'EOF in C

j'écris un programme qui est censé lire deux chaînes qui peuvent 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 très bien avec la première variable, mais avec la deuxième variable, cependant, cela semble problématique car apparemment quelque chose est coincé dans le tampon d'entrée et l'utilisateur n'a pas le droit de taper quoi que ce soit.

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

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

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

[edit: ajout de code ci-dessous]

[edit 2: clearerr() semble finalement faire fonctionner cette solution EOF.

il semble fonctionner sous sa forme originale comme je l'avais prévu sous Linux, je l'ai essayé 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] = '"151900920"';
    x = 0;

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

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

    printf("nnResults:na: %sn", a);
    printf("b: %sn", b);

    return(0);
}

[edit 3:]

problème de mémoire dynamique:

mon programme est aussi supposé gérer des chaînes de caractères de plus de 100 caractères. À l'origine, j'avais l'intention de résoudre ce problème par l'allocation dynamique de la mémoire, mais lorsque j'ai eu des problèmes avec la boucle infinie décrite ci-dessus et les crashs liés à la mémoire, je l'ai laissé de côté et je 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 raisonnable) de le faire? Je suis en train de allouer plus de mémoire pour chaque personnage qui est manipulé. Individuellement. Avec un code comme celui-ci (cet exemple contient probablement des erreurs de syntaxe) j'ai connu des crashs, donc il me semble que malloc n'est peut-être pas la bonne fonction ici, ou je l'essaie mal. En supposant que c'est encore possible.

2
demandé sur Martin v. Löwis 2009-10-26 00:16:20

7 réponses

après avoir reçu un EOF du terminal, vous ne recevrez pas de données supplémentaires . Il n'y a aucun moyen de désactiver l'entrée-la fin du fichier est, bien, la fin.

ainsi vous devriez définir que chaque variable est entrée sur une ligne séparée, et que les utilisateurs pressent enter au lieu de EOF. Vous devez toujours vérifier si vous avez reçu eof, parce que cela signifie que l'Utilisateur a effectivement tapé EOF, et vous ne verrez rien d'autre - dans ce case, vous devez sortir de la boucle et imprimer un message d'erreur.

9
répondu Martin v. Löwis 2009-10-25 21:20:25

EOF n'est pas un caractère - c'est une valeur spéciale que les fonctions d'entrée retournent pour indiquer une condition , que la "fin du fichier" sur ce flux d'entrée a été atteint. Comme le dit Martin v. Löwis, une fois que cette condition de "fin de fichier" se produit, cela signifie qu'aucune entrée ne sera plus disponible sur ce flux.

la confusion naît parce que:

  • plusieurs types de terminaux reconnaissent une touche spéciale pour signaler la "fin du fichier" lorsque le "fichier" est un terminal interactif (p. ex. Ctrl-Z ou Ctrl-D); et
  • la valeur EOF est l'une des valeurs qui peuvent être retournées par la famille de fonctions getchar() .

vous aurez besoin d'utiliser une valeur de caractère réelle pour séparer les entrées - le caractère ASCII nul '"151930920"' pourrait être un bon choix, si cela ne peut pas apparaître comme une valeur valide dans les entrées elles-mêmes.

2
répondu caf 2009-10-25 21:32:51

j'exécute 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 parce que le tampon d'entrée terminal n'était pas vide.

1
répondu sambowry 2009-10-25 22:32:26

, Vous pouvez utiliser le caractère nul ( '"151900920"' ) pour séparer les variables. Divers outils UNIX (par exemple find ) sont capables de séparer leurs articles de sortie de cette façon, ce qui suggère que c'est une méthode assez standard.

un autre avantage de ceci est que vous pouvez lire le flux dans un tampon simple et puis créer un tableau de char* s pour pointer vers les chaînes individuelles, et chaque chaîne sera correctement '" 151900920 "' - terminé sans vous devez changer n'importe quoi dans le tampon manuellement. Cela signifie moins de frais généraux d'allocation de mémoire, ce qui peut faire fonctionner votre programme sensiblement plus rapidement en fonction du nombre de variables que vous lisez. Bien sûr, cela n'est nécessaire que si vous avez besoin de garder toutes les variables en mémoire en même temps - si vous avez affaire à eux un par un, vous n'obtenez pas cet avantage particulier.

0
répondu David 2009-10-25 21:30:51

ce que vous essayez est fondamentalement impossible avec L'EOF.

bien qu'il se comporte comme un à certains égards, 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 ça:

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

quand vous tapez le caractère EOF la première fois, pour terminer la première chaîne, le flux est irrévocablement fermé. Qui est, le statut du ruisseau est qu'il est fermé.

ainsi, le contenu de la seconde boucle while ne s'exécute jamais.

0
répondu Benji XVI 2009-10-25 22:21:41

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

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

EOF est un signal que la saisie terminée. Vous êtes presque sûr que toutes les entrées de l'utilisateur se terminent par '\n': c'est la dernière touche que l'utilisateur tape!!!


Edit: 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)
]
$
0
répondu pmg 2009-10-25 22:23:25

comment inscrire null dans le programme?

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

putchar(0);

ceci imprimera un caractère ASCII nul '\0' à sdtout.

0
répondu hansu 2009-10-26 07:01:01