Forum Clubic

Question de base sur les chaines en C

Salut,

Est-ce que quelqu’un peut me corriger le programme suivant, s’il vous plait ?


#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{	char *chaine=(char *) malloc(40 * sizeof(char));
	do
	{	printf("Entrez un mot ou tapez sur 'ENTREE' pour quitter : ");
		scanf("%s", chaine);
	}
	while (chaine != '\n');
}

La difficulté, c’est que quand on appuie ENTREE, que le programme attend toujours un réponse, alors que je voudrais que suite à cela, que le programme s’arrête.
Actuellement, ce programme est une boucle sans fin.
Edité le 11/04/2010 à 20:00

Heu plusieurs choses :

  1. Si tu n’as pas besoin d’allouer sur le tas, utilise la pile, ça t’évitera des fuites mémoires dans la plupart des cas, et le compilateur ne bronchera pas…
  2. Corolaire au 1 : dans ce cas précis, si ce n’est que pour lire une chaine, tu peux utiliser une variable static
  3. vu que tu fais un do … while, le programme ne s’arrêtera jamais, d’autant que ta condition porte sur la nullité de la variable chaine… sauf que si chaine vaut NULL alors scanf plantera hein :slight_smile:

ie:

int main(void) {
  static char chaine[41]; // 41 = 40 caractères + '\0'
  printf("Entrez un mot ou tapez sur 'ENTREE' pour quitter : ");
  if (1 != scanf("%40s", chaine)) { // 40s = indique la taille max (de souvenir)
    while (getc() != '\n') continue;	// au cas où tu veux réutiliser scanf, vu que ça peut bloquer à la lecture
  }
}

Edité le 11/04/2010 à 11:55

Pour savoir si ce code résout le problème, il suffit évidement de le compiler, mais, selon mon compilateur gcc, y’a une erreur à la ligne du while ;
erreur: too few arguments to function ‘_IO_getc’ :yeux2:

Je pense que la bonne chose à faire maintenant serait de débugger ce code, avant d’aller plus loin.
Est-ce qu’il manque un argument à la fonction getc() ?
Est-ce qu’il faut ajouter un nouveau #include à ceux que j’ai énoncé au début ?
Edité le 11/04/2010 à 19:51

ben pour getc() le man est ton ami hein :slight_smile:

J’ai fait de mon mieux pour signaler cette erreur dans ton code , sans pour autant te froisser. Je te respecte toujours, malgré cette erreur.
Selon man, getc() est sensé recevoir en paramètre une variable de type ‘pointeur sur fichier’. Or dans ton code, il n’y a aucune trace de fichier, aucune trace de fopen…
Je te pose la question à laquelle man ne peut pas répondre ; est-ce que pour fonctionner, ton programme est sensé utiliser un fichier à un moment ?

Nice :slight_smile:

essaie avec la fonction getchar()

Ouais… ou passe stdin … :slight_smile:

getchar() est une fonction qui renvoi un entier, donc ‘\n’ ne peut être comparé à un entier ; le test (getchar() != ‘\n’) est impossible.
Parcontre, effectivement, le test (getc(stdin) != ‘\n’) est possible !
Ainsi, pour que ton code soit compilable, voici le changement qu’il fait faire ;
while (getc(stdin) != ‘\n’) continue;

Toutefois, une fois exécuté, le résultat obtenu n’est pas ce qui était attendu, c’est à dire ;
[quote=“Wity” … quand on appuie ENTREE, … le programme attend toujours un réponse, alors que je voudrais que suite à cela, que le programme s’arrête…
[/quote]

Je pensais que c’était quelque chose de facile à faire en C, il semble que c’est un programme que seul un professionnel est capable de faire.

int main(void) 
{
 static char chaine[41]; // 41 = 40 caractères + '\0'

 do
 {
  printf("Entrez un mot ou tapez sur 'ENTREE' pour quitter : ");
  scanf("%40s", chaine)
 }while ( chaine[0] != '\0' );
}

ce code devrait fonctionner, je l’ai repris de l’exemple de Sans Nom.
il doit être possible de remplacer le dernier test par la fonction strcmp.

Précision : comme son nom l’indique la fonction getchar renvoie un char, et non pas un entier.
Edité le 12/04/2010 à 22:59

Ben non plus, chat marche pas, ton code aussi est une boucle sans fin.
Sinon, j’ai résolu le problème :yeux3:

Voici mon explication qui est peut-être vrai à propos de l’instruction suivante (invitation à donner son avis);
scanf("%s", chaine) ; // j’ai fait sauté le 40 pour l’explication plus simple…
On demande à scanf, de scanner, jusqu’à ce qu’il affecte un contenu de type ‘chaines de caractères’ à … la variable ‘chaine’.
Le paramètre %s est ici très important pour notre problème : avec %s, tant qu’on a pas entrer au moins un caractère, scanf s’interdit de continuer l’exécution du programme. Ainsi, avec %s en paramètre, il est donc IMPOSSIBLE d’affecter ‘\0’ à … la variable chaine.

Voici ma solution ;

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main()
{	char *chaine=(char *) malloc(40 * sizeof(char)), *car=(char *) malloc(40 * sizeof(char));
	while (1)
	{	printf("Entrez un mot ou tapez sur 'ENTREE' pour quitter : "); scanf("%c", car);
		if(*car == '\n') break;
		scanf("%s", chaine); strcat (car, chaine);
		printf("mot que vous avez saisie : %s\n", car);
		getchar();		// afin d'absorber l'utilisation précédente de la touche entree
		car[1]='\0';		// espèce de réinitialisation en vue d'une prochaine concaténation
	}
	printf("Sortie effectué\n");
}

Ce programme fait plus que ce qui était demandé au départ ; il est adapté pour mémorisé ce qui a été saisie, au cas où l’utilisateur n’a pas appuyer ENTREE pour sortir.
Oui, ça à l’air compliqué. Mis à part pour les mallocs, j’aurais beaucoup apprécié la personne qui arrive à faire la même chose de manière plus simple !!!

Heu l’utilisation de getchar() (ou getc()) c’était juste pour éviter le problème récurrent de scanf si jamais il lit mal ses paramètres (en particulier avec les entiers).


#include <stdio.h>
#include <stdlib.h>

int main(void) {
  static char chaine[41]; // 41 = 40 caractères + '\0'
  printf("Entrez un mot ou tapez sur 'ENTREE' pour quitter : ");
  if (1 != scanf("%40s", chaine)) { // 40s = indique la taille max (de souvenir)
    while (getchar() != '\n') continue;	// au cas où tu veux réutiliser scanf, vu que ça peut bloquer à la lecture
  }
  return EXIT_SUCCESS;
}

Testé et compilé avec gcc test.c --std=c99 -Wall, ça marche très bien. (et pas besoin de pointeur bordel :confused: tu peux allouer la mémoire sur la pile, ça va pas tuer le programme pour 40 caractères, et pire encore, si c’est que pour en lire qu’un seul, fait un char et passe le par pointeur, ie: char c; scanf("%c", &c); )

:icon_biggrin: Tu as toute à fait raison, absolument, fallait faire comme ça.

J’exécute ton dernier code ci dessus, et puis, en tant qu’utilisateur, j’arrive absolument pas à sortir de ton programme, à moins de faire CTRL-Z (sous Linux Mandriva). J’ai beau appuyer ENTREE, puis aucune sortie :neutre:
Voici ce que j’ai écrit dans la console pour compiler ; gcc test.c --std=c99 -Wall
Voici ce que j’ai écrit dans la console pour lancer ton programme ; ./a.out

Lors de ton test, es-tu arrivé à sortir du programme ? Comment ? En tapant la touche ENTREE ? – suspense –
Edité le 14/04/2010 à 19:11

J’ai tapé quelque chose puis entrée… sinon tu as gets() ( linux.die.net… ) mais je te suggère plutôt fgets().

Dans le message du printf, on propose à un utilisateur les 2 possibilités suivantes ;

  • Entrez un mot ou
  • tapez sur ‘ENTREE’ pour quitter.

Si l’utilisateur veux quitter le programme, on ne lui a jamais demandé (dans le printf) de taper un quoi que ce soit avant d’appuyer ENTREE, on lui a simplement demander de se limiter à appuyer sur ENTREE.
Or, avec ton programme, l’utilisateur doit impérativement taper un mot avant d’appuyer ENTREE pour quitter le programme.
Avec mon programme, pour quitter, l’utilisateur se limite à faire ce qu’on lui demande de faire ; appuyer sur ENTREE.

En passant, il y a moyen de simplifier ton code de manière considérable ;

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
 static char chaine[41]; // 41 = 40 caractères + '\0'
 printf("tapez un mot PUIS tapez sur 'ENTREE' pour quitter : ");
 scanf("%40s", chaine);
 return EXIT_SUCCESS;
}

Excepté pour les mallocs (j’ai déjà compris…), est-t-il possible de simplifier mon code aussi ?
Si j’apprends qu’il y a un programmeur plus balès que moi sur cette Terre, ça me fera plaisir du fond du cœur ! :stuck_out_tongue:
Edité le 15/04/2010 à 01:55

sigh. N’utilise pas scanf alors, utilise gets() ou fait le à la main. (et y a des programmeurs plus balèses, ce même en français !)