Contenu | Rechercher | Menus

Annonce

DVD, clés USB et t-shirts Ubuntu-fr disponibles sur la boutique En Vente Libre

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 02/12/2014, à 18:33

Yberamos

[Résolu] Vider le buffer en C (bis)

Alors voila, j'étais déja venu sur ce forum pour ce probleme. Pensant qu'on m'avait bien expliquer l'erreur, j'avais marquer comme [Résolu] le sujet, mais....
J'ai toujours ce f**** problème. C'est-à-dire, vider le buffer d'entrée en C. Voici un code pour exemplifier mon problème:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef _WIN32			
#include <conio.h>		
#define CLEAR "cls"		
#else					
#include <curses.h>
#define CLEAR "clear"
#endif

#define MINSHORT -32768
#define MAXSHORT 32767

void flush();
short LireShort (short,short);

int main()
{
    short continuer,a,b;
    float prec,xp,x,fa,fb;
    do
	{
		printf("Entre a: ");
		a=LireShort(MINSHORT,MAXSHORT);
		printf("Entre b: ");
		b=LireShort(MINSHORT,MAXSHORT);
		fa=2*a*a+a-1;
		fb=2*b*b+b-1;
		if(fa*fb<=0)
		{
			do
			{
				printf("Entrer la precision: ");
				scanf("%f",&prec);
			}while(prec<0);
			printf("Entrer x0: ");
			scanf("%f",&x);
			do
			{
				xp=x;
				x=x-((2*x*x+x-1)/(4*x+1));
			}while(fabs(xp-x)>=prec);
			printf("Votre racine vaut: %.3f",x);
			
			
		}
		printf("\nVoulez-vous recommencer? (0=NON, 1=OUI)");
		scanf("%hd",&continuer);
		//continuer=LireShort(0,1);
		//system(CLEAR);
	}while(continuer!=0);

return 0;
}

/*Fonction*/


/*
 * INPUT: /
 *PROCESS: prend le contenu du buffer jusqu'à atteindre la fin du fichier ou le carractère de retour a la ligne.
 * OUTPUT: /
 */
void flush()
{
	int c;
	do
	{
		c=getch();
	}while(c!='\n'&&c!=EOF);
}

/*
 *INPUT: Le minimum et le maximum possible pour la variable.                    
 *PROCESS: Lit avec un getchar un nombre entré au clavier. Transforme           
 *         la chaine de caractère en nombre. La fonction vérifie ensuite que	   
 *		  cette valeur ce trouve bien dans l'intervalle passé comme paramètre. 
 *		  Si non, boucle													   
 *OUTPUT:La valeur de la variable.			           					       
 */
short LireShort (short nmin,short nmax)
{
    char c;
    short signe=1, i;
    int temp=0;

    do
	{
		flush();
		c = getchar();
		temp=0;

		/*Vérifie le signe avant le nombre*/

		if (c=='-')
		{
			signe=-1;
			c=getchar();
		}
		else
		{
			if(c=='+')
			{
				c=getchar();
			}
		}

		/*Boucle qui transforme les chiffres après les signes en nombre*/

		for(i=0;(c>='0' && c<='9') && i<=/*Renvois du short /!\ casting*/5; i++)
		{
			temp=temp*10+(c-48);
			c=getchar();
		}

		/*Mise du signe devant le calcul*/

		temp=temp*signe;


		
		if(temp<nmin||temp>nmax|| c!='\n')
		{
			printf("Valeur entree incorrect. Veuillez entrer une valeur entre %hd et %hd.\n",nmin,nmax);
		}
	}while(temp<nmin||temp>nmax);

	/*Renvois du short /!\ casting*/
    return((short)temp);

}

(Ce code est un exercice toujours en cour de dévélopement)
A la fin de mon main j'ai "
scanf("%hd",&continuer);
//continuer=LireShort(0,1);
"

Le code comme cela fonctionne très bien, mais si on commente la ligne avec le scanf et qu'on dé-commente la ligne suivante, le programme va s'éxecuter normalement mais lorsqu'il doit m'afficher"Voulez-vous recommencer? (0=NON, 1=OUI)", il ne va pas me demander d'entrer quelque chose et vider l'écran ensuite il m'affiche le printd et termine tout de suite l'execution...

Je ne sais pas si mon problem viens de ma fonction LireShort (que j'ai utiliser sans probleme pendant 1 an sous windows), de ma fonction flush (que j'ai prise sur le net, ou de mon main, mais en tous je tourne en rond depuis des mois sur ce problème...

Je remercie d'avance toute personne qui voudra bien m'aider ^^.

EDIT: Rajouter un "#" qui manquait au début

Dernière modification par Yberamos (Le 04/12/2014, à 11:58)

Hors ligne

#2 Le 02/12/2014, à 19:35

pingouinux

Re : [Résolu] Vider le buffer en C (bis)

Bonsoir,
Il manque le # en tête de la 1ère ligne (erreur de copie, sans doute).
Dans la fonction flush, es-tu sûr que ce soit getch, et pas getchar ?

En ligne

#3 Le 02/12/2014, à 19:52

Yberamos

Re : [Résolu] Vider le buffer en C (bis)

Pour le #, c'était bien une erreur de copie. Pour le getchar, cela fonctionne, mais losqu'il me demande a et b je dois entrer deux nombre et il ne prend en compte que le second. (je supose que je n'ai pas ce probleme pour le continuer a cause du scanf qu'il y a toujours au milieu du code). Une idée d'où ça vient? Merci^^

Dernière modification par Yberamos (Le 03/12/2014, à 00:16)

Hors ligne

#4 Le 03/12/2014, à 15:39

claudius01

Re : [Résolu] Vider le buffer en C (bis)

Un seul conseil, bannir scanf() et consorts qui ont des comportements trop sujets aux saisies de chaînes de caractères qui plus est venant d'humains ;-)
cf. Les dangers de scanf pour s'en convaincre...

Hors ligne

#5 Le 03/12/2014, à 17:45

Yberamos

Re : [Résolu] Vider le buffer en C (bis)

On est bien d'accord! Mais je dois faire comme la prof le veux.^^ Pour les short je dois développer une autre fonction, mais pour les autres types, je dois continuer à utiliser le scanf. Et donc j'essaye de faire fonctionner ma fonction de remplacement du scanf pour les short, mais cela plante...

Hors ligne

#6 Le 04/12/2014, à 07:54

pingouinux

Re : [Résolu] Vider le buffer en C (bis)

Tu peux essayer ceci

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#ifdef _WIN32			
#include <conio.h>		
#define CLEAR "cls"		
#else					
#include <curses.h>
#define CLEAR "clear"
#endif
#define MINSHORT -32768
#define MAXSHORT 32767
void flush();
short LireShort (short,short);
int main()
{
    short continuer,a,b;
    float prec,xp,x,fa,fb;
    do
	{
		printf("Entre a: ");
		a=LireShort(MINSHORT,MAXSHORT);
		printf("Entre b: ");
		b=LireShort(MINSHORT,MAXSHORT);
		fa=2*a*a+a-1;
		fb=2*b*b+b-1;
		if(fa*fb<=0)
		{
			do
			{
				printf("Entrer la precision: ");
				scanf("%f",&prec);
			}while(prec<0);
			printf("Entrer x0: ");
			scanf("%f",&x);
			do
			{
				xp=x;
				x=x-((2*x*x+x-1)/(4*x+1));
			}while(fabs(xp-x)>=prec);
			printf("Votre racine vaut: %.3f",x);
			
			
		}
		printf("\nVoulez-vous recommencer? (0=NON, 1=OUI)");
		//scanf("%hd",&continuer);
		continuer=LireShort(0,1);
		//system(CLEAR);
	}while(continuer!=0);
return 0;
}
/*Fonction*/
/*
 * INPUT: /
 *PROCESS: prend le contenu du buffer jusqu'à atteindre la fin du fichier ou le carractère de retour a la ligne.
 * OUTPUT: /
 */
void flush()
{
	char c; // Modif
	do
	{
		c=getchar(); // Modif
        }while((c=='\n'||c==' ')&&c!=EOF); // Modif
        if(c!=EOF) ungetc(c,stdin); // Modif
}
/*
 *INPUT: Le minimum et le maximum possible pour la variable.                    
 *PROCESS: Lit avec un getchar un nombre entré au clavier. Transforme           
 *         la chaine de caractère en nombre. La fonction vérifie ensuite que	   
 *		  cette valeur ce trouve bien dans l'intervalle passé comme paramètre. 
 *		  Si non, boucle						   
 *OUTPUT:La valeur de la variable.			           		       
 */
short LireShort (short nmin,short nmax)
{
    char c;
    short signe=1, i;
    int temp=0;
    do
	{
		flush();
		c = getchar();
		temp=0;
		/*Vérifie le signe avant le nombre*/
		if (c=='-')
		{
			signe=-1;
			c=getchar();
		}
		else
		{
			if(c=='+')
			{
				c=getchar();
			}
                else {  temp=temp*10+(c-48); c=getchar(); } // Modif
		}
		/*Boucle qui transforme les chiffres après les signes en nombre*/
		for(i=0;(c>='0' && c<='9') && i<=/*Renvois du short /!\ casting*/5; i++)
		{
			temp=temp*10+(c-48);
			c=getchar();
		}
		/*Mise du signe devant le calcul*/
		temp=temp*signe;
		if(temp<nmin||temp>nmax|| c!='\n')
		{
			printf("Valeur entree incorrect. Veuillez entrer une valeur entre %hd et %hd.\n",nmin,nmax);
		}
	}while(temp<nmin||temp>nmax);
	/*Renvois du short /!\ casting*/
    return((short)temp);
}

J'ai ajouté le commentaire // Modif après chaque ligne que j'ai modifiée.
Est-ce bien l'équation 2*x*x+x-1 = 0 que tu essayes de résoudre ?

En ligne

#7 Le 04/12/2014, à 09:47

Yberamos

Re : [Résolu] Vider le buffer en C (bis)

C'est bien cette équation^^.
Premièrement ca a l'aire de fonctionner impec! Merci beaucoup!

Mais j'avais des questions sur les modif:
1)Dans la fonction flush, pourquoi avoir changer le type de c en char? Dans le K&R ils disent "On ne peut pas se servir de char puisque c doit pouvoir recevoir EOF en plus de toutes les valeurs possibles de char. Voila pourquoi nous avons pris un int." (ils parlent d'un exemple au-dessus, mais la logique est la meme pour le type de c ici, non?). Ect-ce pour le ungetc?

2)Et enfin, dans la fonction LireShort, pourquoi avoir rajouter : "else {  temp=temp*10+(c-48); c=getchar(); }"?

3)Je me demandais aussi pour quoi est-ce que fflush(stdin) ne marche pas sous Linux? Je sais que c'est très mauvais de faire ça car le fflush va avoir un comportement indéfini sur le stdin, mais on nous l'enseigne comme ça. Je pensait que ça ne fonctionnait pas lors de mes premier test car il n'était pas defini sous Linux, mais man stdin me renvoie une page, c'est donc qu'il est bien défini, non? Est-ce que je m'arache les cheveux pour rien depuis des mois? Même si au final, il ne faut pas utiliser fflush de cette manière donc, ce n'est pas grave, mais bon...

Enfin bon, voila^^ Je te remercie déja grandement pour ton aide!

edit: j'ai trouver la reponse à une des mes question donc je l'ai supprimer.

Dernière modification par Yberamos (Le 04/12/2014, à 10:08)

Hors ligne

#8 Le 04/12/2014, à 11:47

pingouinux

Re : [Résolu] Vider le buffer en C (bis)

Yberamos a écrit :

Dans la fonction flush, pourquoi avoir changer le type de c en char?

Tu as raison, ce n'était pas indispensable.

Et enfin, dans la fonction LireShort, pourquoi avoir rajouter : "else {  temp=temp*10+(c-48); c=getchar(); }"?

Effectivement, je pense que tu peux supprimer cette ligne (j'avais essayé différents trucs au cours de mes tests).

Je me demandais aussi pour quoi est-ce que fflush(stdin) ne marche pas sous Linux?

Apparemment, le man fflush n'interdit pas d'utiliser stdin. Tu ne peux pas remplacer flush(); en tête de LireShort par fflush(stdin);, car dans ce cas le buffer d'entrée est complètement vidé, et tu n'as plus rien à lire.

En ligne

#9 Le 04/12/2014, à 11:57

Yberamos

Re : [Résolu] Vider le buffer en C (bis)

Et bien merci beaucoup pour ton aide^^.

Je passe le sujet en [Résolut].

Hors ligne