Question

J'ai eu beaucoup de difficultés à essayer de comprendre comment utiliser scanf () . Cela semble fonctionner correctement avec les entiers, il est assez simple scanf ("% d", & amp; i) .

Là où je rencontre des problèmes, je me sers de scanf () dans les boucles qui tentent de lire les entrées. Par exemple:

do {
  printf("counter: %d: ", counter);
  scanf("%c %c%d", &command, &prefix, &input);
} while (command != 'q');
  1. Lorsque je saisis une entrée à structure valide telle que c P101 , il semble que la boucle se répète avant de me le signaler. Cela semble se produire même avec un single:

    scanf("%c", &c) 
    

    dans une boucle while. Ça va faire la boucle deux fois avant de me demander à nouveau. Qu'est-ce qui la fait boucler deux fois et comment puis-je l'arrêter?

  2. Lorsque j'entre moins de données que celles programmées, elles n'auraient pas d'autre caractère ou numéro tel que q , appuyer sur Entrée semble m'inviter à saisir plus d'informations. Comment faire en sorte que scanf () traite les entrées de caractères simples et doubles?

Était-ce utile?

La solution

Lorsque vous entrez " c P101 " le programme reçoit en réalité " c P101 \ n ". La plupart des spécificateurs de conversion ignorent les espaces, y compris les nouvelles lignes, mais pas % c . La première fois, tout va jusqu’à la " \ n " est lu, la deuxième fois autour de la " \ n " est lu dans la commande , " c " est lu dans préfixe , et " P " il ne reste plus qu'un nombre, de sorte que la conversion échoue et " P101 \ n ". est laissé sur le flux. La prochaine fois " P " est stocké dans la commande, " 1 ". est stocké dans le préfixe et 1 (à partir du " 01 "restant) est stocké en entrée avec le code " \ n " toujours sur le flux pour la prochaine fois. Vous pouvez résoudre ce problème en plaçant un espace au début de la chaîne de format afin d'éviter tout espace majuscule, y compris les nouvelles lignes.

Une situation similaire se produit dans le second cas, lorsque vous entrez " q ", " q \ n ". est entré dans le flux, la première fois autour du " q " est lu, la deuxième fois, le " \ n " est lu, seulement le troisième appel est le deuxième " q " lu, vous pouvez à nouveau éviter le problème en ajoutant un espace au début de la chaîne de formatage.

Une meilleure méthode consiste à utiliser quelque chose comme fgets () pour traiter une ligne à la fois, puis à utiliser sscanf () pour analyser.

Autres conseils

C'est vraiment cassé! Je ne le savais pas

#include <stdio.h>

int main(void)
{
    int counter = 1;
    char command, prefix;
    int input;

    do 
    {
        printf("counter: %d: ", counter);
        scanf("%c %c%d", &command, &prefix, &input);
        printf("---%c %c%d---\n", command, prefix, input);
        counter++;
    } while (command != 'q');
}
counter: 1: a b1
---a b1---
counter: 2: c d2
---
 c1---
counter: 3: e f3
---d 21---
counter: 4: ---e f3---
counter: 5: g h4
---
 g3---

La sortie semble correspondre à la réponse de Robert.

Une fois que vous avez la chaîne qui contient la ligne. "C P101", vous pouvez utiliser les capacités d'analyse de sscanf.

Voir: http://www.cplusplus.com/reference/clibrary/cstdio/sscanf. html

Pour la question 1, je soupçonne que votre printf () pose un problème, car il n'y a pas de terminaison "& n; \ n".

.

Le comportement par défaut de printf consiste à mettre en tampon la sortie jusqu'à ce que la ligne soit complète. C’est-à-dire sauf si vous modifiez explicitement la mise en mémoire tampon sur stdout .

Pour la question 2, vous venez de frapper l'un des plus gros problèmes de scanf () . À moins que votre entrée ne corresponde exactement à la chaîne d'analyse que vous avez spécifiée, vos résultats ne correspondront en rien à ce que vous attendez.

Si vous avez une option, vous obtiendrez de meilleurs résultats (et moins de problèmes de sécurité) en ignorant scanf () et en effectuant votre propre analyse. Par exemple, utilisez fgets () pour lire une ligne entière dans une chaîne, puis traitez les champs individuels de la chaîne - peut-être même en utilisant sscanf () .

Peut-être utiliser une boucle while, pas une boucle do ... while aidera. De cette façon, la condition est testée avant l'exécution du code. Essayez l'extrait de code suivant:

 while(command != 'q')
    {
        //statements
    }

En outre, si vous connaissez la longueur de chaîne à l'avance, les boucles "for" peuvent être beaucoup plus faciles à utiliser que les boucles "while". Il existe également des méthodes plus délicates pour déterminer dynamiquement la longueur.

En guise de dernier coup de gueule: scanf () ne "suce pas". Il fait ce qu'il fait et c'est tout. fgets () est très dangereux (bien que pratique pour les applications sans risque), car il ne vérifie pas de manière native l'entrée. Il est TRÈS communément appelé point d’exploitation, en particulier les attaques par débordement de tampon, écrasant l’espace disponible dans les registres non alloués à cette variable. Par conséquent, si vous choisissez de l'utiliser, passez un peu de temps à mettre en place une vérification / correction d'erreur solide.

J'espère que cela aidera quelqu'un dans le futur puisque je suppose que vous l'avez déjà traité! ;)

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