7
votes

Utiliser Scanf et Fgets dans le même programme?

Je dois faire quelque chose comme le problème suivant:

int main(void) {
char a,b,cstring;

printf("please enter something");
scanf("%c %c",&a,&b);
prinf("thanks, now some more");
fgets(cstring,35,stdin);

}


0 commentaires

4 Réponses :


1
votes

C'est un comportement indéfini. Votre variable cstring , malgré son nom, est un seul caractère, et vous essayez de lire jusqu'à 35 caractères dans la valeur actuelle points sur . En d'autres termes, le caractère actuel dans cstring sera converti en pointeur et tentera d'écrire votre entrée là-bas. Cela va être un lieu de mémoire (très probablement) entre 0 et 255 inclus.

C'est ce qui cause la violation de votre segmentation. Commencez avec quelque chose comme ça à la place: xxx

ou, éventuellement mieux: xxx

ou, si vous voulez un plus robuste Solution pour l'entrée utilisateur, voir ici . C'est une méthode éprouvée avec une très bonne vérification des erreurs.


7 commentaires

Ah, donc il devrait être un type de chaîne?


Ou devrais-je le définir comme char cstring [35]?


@Wes: Oui, voir la mise à jour, vous devez essentiellement créer un tableau assez grand pour contenir les données que vous essayez d'entrer.


@Wes, il n'y a pas de type de chaîne en C, une chaîne C est simplement un tableau de caractères terminé par NULL


HRM, ce code exact saute à la fin du programme après Scanf ()


C'est parce que votre scanf obtient deux caractères mais la nouvelle ligne est toujours dans le tampon. Ce qui signifie que les fgets l'obtiendront. Vous pouvez utiliser un getChar après la suppression de Scanf pour le supprimer, mais vous serez toujours pris au piège par des cas de bord. Sérieusement, suivez le lien et utilisez une fonction d'entrée décente.


Merci beaucoup pour votre aide - avoir du sens maintenant



8
votes

Le premier problème est que le scanf () code> lit deux caractères, mais pas la nouvelle ligne ensuite.

Cela signifie que votre fgets () code> lit la nouvelle ligne et les finitions . P>

Vous avez de la chance que votre programme ne se plante pas. Vous indiquez fgets () code> qu'il s'agit d'une matrice de 35 caractères, mais plutôt que de passer un tableau, vous passez le caractère (pas l'adresse d'un personnage, même). Cela nous dit également que vous n'êtes pas y compris #include code> (vous ne pouvez pas utiliser scanf () code> de manière fiable en fonction de la norme C sans prototype sans prototype sans prototype pour scanf () code> dans la portée), et vous n'êtes pas s> compiler avec suffisamment d'avertissements activés ou ne payez pas assez d'attention à ce que votre compilateur vous dit. P>

vous devrait recevoir des avertissements du compilateur. Par exemple, GCC 4.6.0 dit: P>

#include <stdio.h>
int main(void)
{
    char a,b,cstring[35];
    int c;

    printf("please enter something");
    scanf("%c %c", &a, &b);
    while ((c = getchar()) != EOF && c != '\n')
        ;
    printf("thanks, now some more");
    fgets(cstring, 35, stdin);
    printf("OK: I got %c and %c and <<%s>>\n", a, b, cstring);
    return 0;
}


3 commentaires

Désolé je compile avec Stdio. Comment puis-je l'arrêter de lire la nouvelle ligne après cela?


Ohhh je comprends. Merci beaucoup d'avoir pris le temps d'expliquer cela.


@Wes: Notez que mon code ne vérifie pas que scanf () lit avec succès deux caractères; cela devrait. Il devrait également vérifier que fgets () a été entré également. Cependant, cela encombrerait légèrement la réponse, ce qui le rendrait légèrement plus difficile pour que vous voyiez le bois pour les arbres.



0
votes

Le problème est lorsque le flux atteint les fgets (), cette API examine d'abord STDIN pour une entrée et il trouve une égarée '\ n' là-bas. En ce qui concerne les fgets () qui a déclaré que cette API revient lorsqu'elle rencontre EOF ou '\ N', puisque les Fgets () ont "\ n" de STDIN, donc il est exécuté sans attendre que l'utilisateur entrait quelque chose que les conditions de retour des API se sont rencontrées. solution au problème est que vous utilisez getchar (); Après Scanf et ignorer les caractères supplémentaires laissés par scanf (). E.g: P>

#include <stdio.h>
int main() {
int j;char t[200];
fgets(t,200,stdin);
sscanf(t,"%d",&j);
}


0 commentaires