Je me demandais quel était le problème avec mon programme. Je ne parviens pas à faire quitter le programme lorsque je tape quit. Voici ce que j'ai:
#include <stdio.h>
#include <string.h>
int main(void) {
char string[200];
printf("Enter a bunch of words: ");
do
{
scanf("%[^\n]c", string);
}while(strcmp(string,"quit")!=0);
return 0;
}
3 Réponses :
Est-ce que quelque chose comme ça est acceptable?
#include <stdio.h>
#include <string.h>
int main(void) {
char string[200] = {0};
printf("Enter a bunch of words: ");
do {
memset(string, 0, 200);
scanf("%s", string);
} while (strcmp(string, "quit") != 0);
return 0;
}
Vous n'avez pas expliqué exactement ce que vous avez l'intention de faire avec une chaîne, il est donc difficile de donner une réponse. Cependant, une chose à noter est que vous devez soit faire quelque chose à string (je viens de le mettre à zéro ici) pour que strcmp reconnaisse "quit", ou scannez les sous-chaînes de string , car si tout est toujours ajouté, votre chaîne sera "(...) quit" que strcmp ne reconnaîtra pas comme "quit".
En remarque, initialisez toujours vos tableaux ou de mauvaises choses pourraient arriver.
Je ne peux pas utiliser memset, je ne l'ai pas encore appris en classe: /. MAIS, j'ai initialisé le tableau comme vous l'avez suggéré et cela a fonctionné sans memset. Merci beaucoup!
@anon Vous pouvez aussi simplement définir chaque index dans string à 0 en utilisant une boucle for , mais la tâche nécessite probablement plus que cela. Heureux que ce soit utile.
@Joshua J'ai toujours eu un faible pour Integer Overflow Man, c'était mon super héros préféré. Il est vrai que cela court ce danger, mais anon n'a pas vraiment spécifié les limites de la tâche qui lui a été confiée, alors j'essayais simplement de donner la proposition la plus simple à quelque chose qui fonctionnerait avec le problème qu'il semblait avoir. La sécurité de la mémoire ne semblait pas faire partie de cela.
Compte tenu des quelques explications que vous avez fournies, le changement le plus simple peut être de modifier votre chaîne de balayage pour avaler le \ n au lieu d'un c théorique, ce qui est en fait impossible :
scanf("%199[^\n]%*[^\n]", string);
scanf("\n");
Pour éviter le débordement de la mémoire tampon, vous devez spécifier la quantité d'espace dont votre tampon dispose pour stocker l'entrée:
scanf("%199[^\n]%*[^\n]\n", string);
C'est sûr si longtemps comme vous le savez, l'entrée ne dépassera jamais 199 caractères. Mais c'est une hypothèse faible à la fois en théorie et en pratique. Les caractères au-delà des 199 enregistrés seront scannés comme votre prochain mot lors de l'itération suivante, ce qui permettrait à votre programme de se fermer de manière inattendue si l'entrée était 199 . s suivis du mot quit code>. Vous avez besoin d'un moyen plus fiable de scanner le reste de la ligne et de le supprimer avant de lire la ligne suivante.
Vous pourriez être tenté d'utiliser un autre % [...] pour capturer les caractères supplémentaires comme ceci:
scanf("%199[^\n]\n", string);
Cependant, cela échouera dans le cas courant où l'entrée est inférieure ou égale à 199 caractères. En effet, scanf échouera si la conversion aboutit à une entrée vide. Ainsi, le \ n restera bloqué dans l'entrée.
Si vous êtes limité à l'utilisation de scanf , vous devrez alors diviser la numérisation en des appels scanf séparés afin que le scan d'erreur et de non-erreur pour le reste de la ligne puisse être traité comme le même résultat, conduisant à un deuxième scanf pour avaler la nouvelle ligne elle-même .
scanf("%[^\n]\n", string);
Vos deux plus gros problèmes sont deux des problèmes les plus courants qui affligent les nouveaux programmeurs C avec leur utilisation de scanf :
- Vous utilisez une chaîne de format incorrect; et
- Vous ne parvenez pas à vérifier le retour de
scanf.
Commençons par les choses:
$ ./bin/scanf_string_quit
Enter a bunch of words ('quit' exits): my dog has fleas and my cat has none.
warning: input exceeds 19 characters.
Enter a bunch of words ('quit' exits): 1234567890123456789
string: 1234567890123456789
Enter a bunch of words ('quit' exits): 12345678901234567890
warning: input exceeds 19 characters.
Enter a bunch of words ('quit' exits): quit
string: quit
Votre chaîne de format "% [^ \ n] c" utilise le caractère-classe spécificateur de format "% [...]" pour lire le texte de string . Il est ensuite suivi de "c" - qui ne correspondra qu'à un littéral 'c' à la fin de votre chaîne d'entrée. Cela ne peut pas se produire tel qu'il est écrit car "% [^ \ n]" lira tous les caractères qui ne sont pas le '\ n' en ne laissant que le '\ n' à lire - qui ne correspond PAS 'c'.
De plus, le "% [... ] " et le spécificateur "% c " ne consomment PAS d'espaces au début (le '\ n' étant des espaces) . Donc, après avoir laissé le '\ n' non lu dans stdin , votre prochain appel à scanf échoue car "% [^ \ n]" ne lira pas le '\ n' et il ne correspond pas à 'c' conduisant à un échec de correspondance , le '\ n' reste non lu dans stdin et les choses deviennent rapidement hors de contrôle.
Pour résoudre tous les problèmes dont vous devez vous souvenir ( 2.) ci-dessus et utilisez également un modificateur field-width pour protéger les limites du tableau de string , et vous devriez alors lire et Enregistrer em> le caractère suivant ceux extraits et mis dans string pour valider une ligne complète d'entrée a été lue - et sinon, c'est votre responsabilité de supprimer tout caractère excédentaire qui reste dans stdin avant de tenter votre prochaine lecture .
Pour commencer, vous pouvez utiliser une chaîne de format correctement limitée qui inclut un espace au début qui obligera scanf à supprimer tous les espaces de début, par exemple
$ ./bin/scanf_string_quit
Enter a bunch of words ('quit' exits): Hello
string: Hello
Enter a bunch of words ('quit' exits): (user canceled input)
Remarque au-dessus du caractère final être enregistré, deux conversions auront lieu, vous aurez donc besoin d'une variable de caractère pour gérer le résultat du spécificateur de conversion final, par exemple
$ ./bin/scanf_string_quit
Enter a bunch of words ('quit' exits): Hello
string: Hello
Enter a bunch of words ('quit' exits): My dog has fleas and my cat has none.
string: My dog has fleas and my cat has none.
Enter a bunch of words ('quit' exits): quit
string: quit
Hou la la! Merci beaucoup, j'apprécie vraiment tous les détails. J'ai suivi les conseils de vous et d'un autre utilisateur et mon programme se ferme une fois que je tape quit. Cependant, cela a conduit à un nouveau problème puisque je n'ai pas décrit le but de mon programme, donc vous avez répondu à ce que vous supposiez que mon programme voulait, je vais publier une nouvelle question qui explique plus en détail ce que je veux faire une fois J'ai arrêté le programme.
Les spécifications d’un exercice que vous faites vous obligent-elles à utiliser
scanf? Sinon, je recommanderais une autre méthode.@GovindParmar ouais, je dois utiliser scanf, nous ne pouvons pas utiliser tout ce que nous n'avons pas encore appris.
@UnholySheep non, ce n'est pas le cas. c'est un format de balayage pour une chaîne qui se compose de tous les caractères en plus de la nouvelle ligne, suivis du littéral
c.Pourquoi utilisez-vous
scanf ("% [^ \ n] c", string);au lieu defgets (string, sizeof string, stdin)? (puisstrncmp (string, "quit", 4);)@ DavidC.Rankin Cela fait partie d'un travail scolaire et je ne peux pas utiliser quoi que ce soit qui n'a pas encore été enseigné, donc je dois utiliser scanf
Alors qu'en est-il de
scanf ("% [^ \ n]% * c", string);? (le'*'étant l ' opérateur de suppression d'affectation permettant au caractère suivant (par exemple% c) d'être lu et ignoré sans affecter le < i> nombre de conversions . (que vous devriez vérifierif (scanf ("% [^ \ n]% * c", string)! = 1) {/ * gérer l'erreur * /} code>)Salut @anon. Vous devez expliquer ce que vous pensez que
"% [^ \ n] c"signifie.@AnttiHaapala: Cela ne veut pas vraiment dire ça. Le
% [^ \ n]laissera le\ ndans le flux d'entrée. Ainsi, le caractère suivant ne peut pas être un littéralc.@ DavidC.Rankin hmmm, j'apprécie vraiment la solution, merci beaucoup mais encore une fois, cette technique ne m'a pas été enseignée, donc je dois le faire de manière plus simple. Y a-t-il un moyen de faire while (1) puis à l'intérieur de la boucle do if (strcmp (string, "quit")! = 0) break; J'ai essayé tellement de permutations que je n'arrive pas à comprendre comment le faire fonctionner.
@jxh bien sûr, il est impossible de faire correspondre le format entier, mais c'est ce que cela signifie.
@jxh permet des espaces entre les mots. Si je ne l'avais pas, cela s'arrêterait au premier espace, je pense.
@anon: Mais que vouliez-vous accomplir avec le
cde fin?