web-dev-qa-db-fra.com

Comment lisez-vous scanf jusqu'à EOF en C?

J'ai ceci mais une fois qu'il atteint le supposé EOF il répète simplement la boucle et scanf à nouveau.

int main(void)
{
        char words[16];

        while(scanf("%15s", words) == 1)
           printf("%s\n", words);

        return 0;
}
30
JJRhythm

Essayer:

while(scanf("%15s", words) != EOF)

Vous devez comparer scanf sortie avec EOF

Puisque vous spécifiez une largeur de 15 dans la chaîne de format, vous lirez au plus 15 caractères. Ainsi, le tableau de caractères doit être de taille 16 (15 +1 pour null char). Alors déclarez-le comme:

char words[16];
20
codaddict

Scanf est à peu près toujours plus de problèmes qu'il n'en vaut la peine. Voici deux meilleures façons de faire ce que vous essayez de faire. Cette première est une traduction plus ou moins directe de votre code. C'est plus long, mais vous pouvez le regarder et voir clairement ce qu'il fait, contrairement à scanf.

#include <stdio.h>
#include <ctype.h>
int main(void)
{
    char buf[1024], *p, *q;
    while (fgets(buf, 1024, stdin))
    {
        p = buf;
        while (*p)
        {
            while (*p && isspace(*p)) p++;
            q = p;
            while (*q && !isspace(*q)) q++;
            *q = '\0';
            if (p != q)
                puts(p);
            p = q;
        }
    }
    return 0;
}

Et voici une autre version. C'est un peu plus difficile de voir ce que cela fait par inspection, mais cela ne casse pas si une ligne est plus longue que 1024 caractères, c'est donc le code que j'utiliserais en production. (Eh bien, vraiment ce que j'utiliserais en production est tr -s '[:space:]' '\n', mais voici comment vous implémentez quelque chose comme ça.)

#include <stdio.h>
#include <ctype.h>
int main(void)
{
    int ch, lastch = '\0';
    while ((ch = getchar()) != EOF)
    {
        if (!isspace(ch))
            putchar(ch);
        if (!isspace(lastch))
            putchar('\n');
        lastch = ch;
    }
    if (lastch != '\0' && !isspace(lastch))
        putchar('\n');
    return 0;
}
4
zwol

Votre code boucle jusqu'à ce qu'il lit un seul mot, puis se ferme. Donc, si vous lui donnez plusieurs mots, il lira le premier et quittera, tandis que si vous lui donnez une entrée vide, il bouclera pour toujours. Dans tous les cas, il n'imprimera que les déchets aléatoires à partir de la mémoire non initialisée. Ce n'est apparemment pas ce que vous voulez, mais que voulez-vous? Si vous souhaitez simplement lire et imprimer le premier mot (s'il existe), utilisez si:

if (scanf("%15s", Word) == 1)
    printf("%s\n", Word);

Si vous voulez faire une boucle aussi longtemps que vous pouvez lire un Word, utilisez while:

while (scanf("%15s", Word) == 1)
    printf("%s\n", Word);

En outre, comme d'autres l'ont noté, vous devez donner au tableau Word une taille suffisamment grande pour votre scanf:

char Word[16];

D'autres ont suggéré de tester pour EOF au lieu de vérifier le nombre d'éléments correspondant à scanf. cas (comme essayer de lire des entiers), où scanf peut ne rien correspondre sans atteindre EOF (si l'entrée n'est pas un nombre) et retourner 0.

modifier

On dirait que vous avez modifié votre question pour qu'elle corresponde à mon code, ce qui fonctionne bien lorsque je l'exécute - boucle la lecture des mots jusqu'à ce que EOF soit atteint puis se termine. Donc, quelque chose d'autre se passe avec votre code, peut-être lié à la façon dont vous l'alimentez comme suggéré par David

3
Chris Dodd

Vous devez vérifier la valeur de retour par rapport à EOF, pas à 1.

Notez que dans votre exemple, vous avez également utilisé deux noms de variables différents, words et Word, uniquement déclaré words et n'avez pas déclaré sa longueur, qui doit être comprise entre 16 et ajuster les 15 caractères lus plus un caractère NUL.

0
Brian Campbell