Passage difficile d,une boucle

Résolu/Fermé
Leer0r Messages postés 41 Date d'inscription vendredi 22 décembre 2017 Statut Membre Dernière intervention 16 avril 2020 - 8 mai 2018 à 14:05
Leer0r Messages postés 41 Date d'inscription vendredi 22 décembre 2017 Statut Membre Dernière intervention 16 avril 2020 - 26 mai 2018 à 00:55
Bonjour,
Dans le cadre de mon projet en ISN, je dois réaliser un distributeur de boisson chaude. Pour rendre le tout plus réaliste, j,ai créé un texte défilant au début, le problème étant de passer de ce dernier au menu principal. Le texte défilant étant dans une boucle, je ne sais pas comment faire pour passer a la boucle suivante juste avec un appuis sur une touche.

Merci d,avance

4 réponses

aure2015 Messages postés 93 Date d'inscription dimanche 11 janvier 2009 Statut Membre Dernière intervention 30 mai 2020 5
8 mai 2018 à 15:22
Salut!

Donc tu veux attendre après ta boucle que l'utilisateur puisse lire le texte défilant avant de passer au menu principal, c'est bien ça?

Simplement avec getchar si j'ai bien compris ce que tu voulais!


while(!QUITTER)
{
	//Menu principal
	
	while(...) //Fin menu défilant
	{
	
	}
	
	printf("Appuyer sur une touche pour continuer");
	fflush(stdin); //On vide le buffer!
	getchar(); // On attend que l'utilisateur appuye sur une touche!
}


1
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
9 mai 2018 à 10:30
voulais-tu écrire
fflush(stdout);
?
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 9 mai 2018 à 09:44
1
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 9 mai 2018 à 11:02
avec ncurses, on utiliserait getch() en mode no-delay pour détecter la pression d'une touche sans bloquer le programme

https://invisible-island.net/ncurses/man/curs_inopts.3x.html
https://invisible-island.net/ncurses/man/curs_getch.3x.html
0
Leer0r Messages postés 41 Date d'inscription vendredi 22 décembre 2017 Statut Membre Dernière intervention 16 avril 2020 1
8 mai 2018 à 15:39
oui c,est cette boucle qui continu a l,infini ^^" je dois donc mettre le getchar() a la fin de cette dernière ?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined WIN32 || defined WIN64
#        include <windows.h>
#        define sleep(x) Sleep(1000 * (x))
#else
#        include <unistd.h>
#endif
static void
scroll(char const *s)
{
    char const *p;
    for (p = s + strlen(s); p != s; p--) {
        char const *q;
        for (q = p; *q != '\0'; q++)
            putchar(*q);
        for (q = s; q != p; q++)
            putchar(*q);
        putchar('\r');
        fflush(stdout);
        sleep(0.1);
    }
}
int
main(void)
{
    char const *s = "           BIENVENU AU DISTRIBUTEUR DE BOISSON CHAUDE !                        ";
    while (1)
        scroll(s);
    return EXIT_SUCCESS;
}
0
aure2015 Messages postés 93 Date d'inscription dimanche 11 janvier 2009 Statut Membre Dernière intervention 30 mai 2020 5
8 mai 2018 à 16:08
Ah je comprends!

Non si tu mets un getchar() après ta boucle ça va devoir attendre que l'utilisateur encode une touche bien sûr!

Tu connais un peu les threads?
0
aure2015 Messages postés 93 Date d'inscription dimanche 11 janvier 2009 Statut Membre Dernière intervention 30 mai 2020 5
Modifié le 8 mai 2018 à 18:41
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>

#define QUITTER -1

void fctBoucleTexte (void *p);
pthread_t threadBoucleTxt;

int main()
{
    int choix;
    pthread_create(&threadBoucleTxt, NULL,(void*(*)(void*)) fctBoucleTexte, &NULL);
 
 while(!QUITTER)
 {
  //Menu
  
  choix=BouttonAppuye();
  
  switch(choix)
  {
   case choix1: //Choix 1
     break;
   case choix2: //Choix 2
     break;
   case choix3: //Choix 3
     break;
   //etc
  }
 }
 
 exit(0);
    
}


void fctBoucleTexte (void * p)
{
    while (1)
        scroll(s);
}

0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 9 mai 2018 à 14:42
@LeerOr: sous Linux/Unix, le prototype de
sleep()
est
unsigned int sleep(unsigned int seconds);
, et la fonction ne peut donc pas prendre en paramètre un nombre à virgule. Du coup, C passera 0 à sleep() sous Unix, du fait de la promotion de type opérée, et tout se passera comme si tu n'avais pas définit de temporisation entre chaque itération.

Une fonction POSIX avec une résolution plus fine est nanosleep

https://man7.org/linux/man-pages/man2/nanosleep.2.html

@aure2015: les threads sont une bonne idée si le but est que le défilement continue pendant l'exécution du programme (et pas uniquement jusqu'à la pression d'une touche avant l'affichage du menu). A mon sens, alors, des fonctions additionnelles de gestion de la console permettant l'affichage du texte défilant à une position donnée de l'écran (du type
gotoxy()
) deviendraient aussi nécessaires, sinon, on va se trimbaler les affichages gênants sur tout l'écran à chaque mouvement du curseur :-)

du coup, l'usage de ncurses se justifierait aussi, pour éviter d'avoir à bricoler avec les séquences d'échappement POSIX.

pthread est POSIX, ils sont portés sous Windows https://sourceware.org/pthreads-win32/ ou, alors, il y a, bien sûr, les threads Windows https://docs.microsoft.com/en-us/windows/win32/procthread/creating-threads?redirectedfrom=MSDN qui ne sont pas forcément évidents.

puisque Leer0r a l'air de vouloir faire un programme portable, il y a des choix à faire, cela dit, cela commence à faire beaucoup pour un projet ISN, et une complexité qui ne se justifie peut-être pas juste pour faire un truc qui défile :-)
0
Leer0r Messages postés 41 Date d'inscription vendredi 22 décembre 2017 Statut Membre Dernière intervention 16 avril 2020 1
17 mai 2018 à 12:20
Merci beaucoup pour vos réponses et désolée du retard de celle là, assimiler tout ça n'a pas été facile ^^"" donc oui mon but est de faire une boucle avec le texte défilant qui continue tant que l'utilisateur n'appuie pas sur une touche ^^

@[Dal] tu disais que le
_kbhint
servait à tester si une touche avait été appuillée mais elle n'est pas utile si je veut que l'utilisateur passe au menu principal en appuyant sur n'importe quelle touche non ?

Du coup
getch ()
est utile pour ce problème ?

Je n'ai pas encore pu regarder pour POSIX @[Dal] mais je ne comprends pas vraiment son utilité^^""
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 17 mai 2018 à 15:28
Salut Leer0r,

Merci beaucoup pour vos réponses et désolée du retard de celle là, assimiler tout ça n'a pas été facile ^^"" donc oui mon but est de faire une boucle avec le texte défilant qui continue tant que l'utilisateur n'appuie pas sur une touche ^^

Et, donc, lorsque l'on appuie sur une touche, le texte s'arrête de défiler et le menu s'affiche. Dans ce cas, les threads proposés par aure2015 ne sont pas nécessaires.

@[Dal] tu disais que le _kbhint servait à tester si une touche avait été appuillée mais elle n'est pas utile si je veut que l'utilisateur passe au menu principal en appuyant sur n'importe quelle touche non ?

c'est
_kbhit()
("hit" comme frappe, pas "hint" comme indice), accessible par l'entête
conio.h
, sous Windows seulement.

et oui, tu peux t'en servir sous Windows pour cela.

par exemple dans ta fonction scroll, en mettant son code dans une boucle infinie, qui s'arrête lors de la pression d'une touche quelconque :

#include <windows.h>
#include <conio.h>  
#include <stdio.h>  

static void scroll(char const *s) {
    char const *p;

    while (1) {
        for (p = s + strlen(s); p != s; p--) {
            char const *q;
            for (q = p; *q != '\0'; q++)
                putchar(*q);
            for (q = s; q != p; q++)
                putchar(*q);
            putchar('\r');
            fflush(stdout);
            Sleep(DWORD(1000 * (0.1)));
            if (_kbhit())
                return;
        }
    }
}

(code non testé, je suis sous Linux)

Du coup getch () est utile pour ce problème ?

Si tu fais référence à la fonction ncurses que je citais en disant : "on utiliserait getch() en mode no-delay pour détecter la pression d'une touche sans bloquer le programme" oui, cela ferait la même chose sous Windows comme sous Linux, mais cela suppose d'installer la bibliothèque ncurses (et de ne pas utiliser
conio.h
sous Windows, car un
getch()
est présent dans
conio.h
, qui est bloquant).

Je n'ai pas encore pu regarder pour POSIX @[Dal] mais je ne comprends pas vraiment son utilité^^""

Ton code comporte les directives suivantes :

#if defined WIN32 || defined WIN64
#        include <windows.h>
#        define sleep(x) Sleep(1000 * (x))
#else
#        include <unistd.h>
#endif

qui laissent penser que tu programmes non seulement pour que ton code compile sous Windows, mais aussi sous des systèmes de type Unix, comme Linux, régis par la norme POSIX (un standard pour les systèmes de type Unix),
<unistd.h>
étant un entête qui n'existe, normalement, que sur les systèmes POSIX.

Si tu ne dois réaliser qu'un code compilant sous Windows, tu n'as pas besoin de cela et, à la place, tu feras juste
#include <windows.h>
et tu utiliseras
Sleep(DWORD(1000 * 0.1));
dans ton code pour dormir un dixième de seconde.

Si tu dois réaliser un code qui compile sous Linux ou autres systèmes POSIX, en plus de Windows, cette complexité est effectivement nécessaire, et même plus, puisque
sleep()
accessible par
<unistd.h>
ne marchera pas avec des nombres à virgule sous les systèmes POSIX comme je te l'ai indiqué précédemment, et que tu devrais utiliser
nanosleep()
pour avoir une définition inférieure à la seconde, qui est un peu plus complexe à utiliser.

Pareil pour
_kbhit()
, que tu ne trouveras pas sous Linux ou autres systèmes POSIX.

Ces différentes fonctions ne font pas partie du standard du C.

Si ton programme doit être en C standard, tu devrais t'abstenir d'utiliser
Sleep()
,
sleep()
,
nanosleep()
,
_kbhit()
et
getch()
et te limiter aux fonctions standard du C : https://en.cppreference.com/w/c/header

Dal
0
Leer0r Messages postés 41 Date d'inscription vendredi 22 décembre 2017 Statut Membre Dernière intervention 16 avril 2020 1
22 mai 2018 à 20:27
@[Dal]
j,ai essayer le code que tu m,a donné et lorsque j,appuis sur une touche ça bloque juste le texte défilant ^^"""
J,ai maintenant le code complet que voici :
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include "chose a int.h" //dans un fichier d,en tête j,ai mis tout les trucs a int pour plus de lisibilitée 
#if defined WIN32 || defined WIN64
#        include <windows.h>
#        define sleep(x) Sleep(1000 * (x))
#else
#        include <unistd.h>
#endif


static void scroll(char const *s) {
	char const *p;

	while (1) {
		for (p = s + strlen(s); p != s; p--) {
			char const *q;
			for (q = p; *q != '\0'; q++)
				putchar(*q);
			for (q = s; q != p; q++)
				putchar(*q);
			putchar('\r');
			fflush(stdout);
			if (_kbhit())
				return ;
			Sleep(DWORD(1000 * (0.1)));
			
		}
	}
}
 

int
main(void)
{
	char const *s = "           BIENVENU AU DISTRIBUTEUR DE BOISSONS CHAUDES !                        ";

	while (1) 
	{
		scroll(s);
	}

	return 0;
}

int main(void)
	{
		while (i != 'q')
		{
			printf(" \t -----------------------Menu Principal-----------------------\n");
			printf("\t\t\t  | Nous vous proposons :\n");
			printf("\n\t\t\t| - CAFE NOIR          <N>|");
			printf("\n\t\t\t| - CAFE AU LAIT       <L>|");
			printf("\n\t\t\t| - THE CHAUD          <T>|");
			printf("\n\t\t\t| - CHOCOLAT au LAIT   <C>|");
			printf("\n\t\t\t| - SOUPE CHAUDE       <S>|");
			printf("\n\t\t\t| - LAIT CHAUD         <B>|\n");
			printf("\t ------------------------------------------------------------\n");
			i = getch();
			switch (i)
			{
			case'N':
			case'n': printf("\nVous avez choisis du CAFE NOIR !\n");
				break;
			case'L':
			case'l': printf("\nVous avez choisis du CAFE AU LAIT !\n");
				break;
			case'T':
			case't': printf("\nVous avez choisis du THE CHAUD !\n");
				break;
			case'C':
			case'c': printf("\nVous avez choisis du CHOCOLAT au LAIT !\n");
				break;
			case'S':
			case's': printf("\nVous avez choisis de la SOUPE CHAUDE !\n");
				break;
			case'B':
			case'b': printf("\nVous avez choisis du LAID CHAUD !\n");
				break;

			}
			if (i != 'q')
			{
				printf("PRIX=1EURO (2e:[z] 1e:[e] | 0.5e:[r] | 0.2e:[t] | 0.1e:[y] )\n");
				while ((prix<1) && (i != 'q'))
				{
					i = getch();
					switch (i)
					{
					case'z': prix = prix + 2;
						break;
					case'e': prix = prix + 1;
						break;
					case'r': prix = prix + 0.5;
						break;
					case't': prix = prix + 0.2;
						break;
					case'y': prix = prix + 0.1;
					}
				}
			}

			if (prix>1)
			{
				rendu = prix - 1;
			}

			if (i != 'q')
			{
				prix = 0;
				printf("\n paiement accepte \n");
				sleep(2);
				printf("\n debut de la preparation de la boisson\n \n");
				sleep(1.5);
				while (n>0)
				{
					n--;
					printf("il reste %d seconde", n);
					sleep(1);
					printf("\x0d");

				}

				rendu = prix;
				printf("\nRendu %feuro\n", rendu);
				printf("\nVeuillez prendre votre boisson!\n\n");
			}

			sleep(6);
			system("cls");
		}
	}

ai-je une erreur qui traîne car maintenant le texte défilant ne s,affiche même plus et le programme commence directement au menu principal ^^""
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
Modifié le 23 mai 2018 à 12:37
comme ta boucle infinie gérant le défilement est désormais dans scroll(), tu peux la retirer de main() où tu fais juste, par exemple :

int main(void)
{
 char const *s = "           BIENVENUE AU DISTRIBUTEUR DE BOISSONS CHAUDES !                        ";
 scroll(s);
 int i = '\0';
 while (i != 'q') {
  printf(" \t -----------------------Menu Principal-----------------------\n");
  (...)

Note que dans un programme C tu ne peux avoir qu'une seule fonction main(), qui est le point d'entrée de l'exécution de ton programme (là tu en as deux, dont une qui contient la suite de ton code, et qui ne se termine pas par
return 0;
).

Je n'ai pas pu tester ton programme, étant sous Linux.

Comme tu utilises des fonctions conio.h comme getch(), qui ne sont pas présentes dans <unistd.h> et des
system("cls");
qui ne donneront un résultat que sous Windows, tu sembles finalement décider de faire un programme pour Windows seulement. Si oui, conserver ces directives de compilation :

#if defined WIN32 || defined WIN64
#        include <windows.h>
#        define sleep(x) Sleep(1000 * (x))
#else
#        include <unistd.h>
#endif

n'a pas trop de sens, et tu ne devrais mettre que
#include <windows.h>
à la place et faire tes appels à la fonction
Sleep()
et non
sleep()
dans ton code.

Ou garde
#include <windows.h>
et
#define sleep(x) Sleep(1000 * (x))
si tu veux et tes appels à
sleep()
pour t'éviter de taper des microsecondes ou le calcul des microsecondes à chaque appel.

il y a aussi "LAID" au lieu de "LAIT" :-D

Le code que tu postes ne contient pas les déclarations et initialisations de certaines variables qu'il utilise (i, n, prix etc.). Comme tu inclues
#include "chose a int.h" //dans un fichier d,en tête j,ai mis tout les trucs a int pour plus de lisibilitée
je suppose que c'est là que tu le fais.

Ce n'est pas exactement l'usage recommandé d'un fichier d'entête (vois http://umich.edu/~eecs381/handouts/CHeaderFileGuidelines.pdf pour de bonnes explications sur ce qui devrait figurer dans un .h et ce qui ne le devrait pas).

Le reste de ton code n'est pas clair, tu n'affectes pas un prix en fonction de la boisson choisie, tu utilises la variable prix pour compter le montant payé en pièces, tu calcule rendu, mais tu écrases sa valeur,... il faudra déboguer et peaufiner tout cela :-)

Dal
0
Leer0r Messages postés 41 Date d'inscription vendredi 22 décembre 2017 Statut Membre Dernière intervention 16 avril 2020 1
25 mai 2018 à 20:14
Effectivement @[Dal]
void scroll(char const *s)
{

	{
		char const *p;

		for (p = s + strlen(s); p != s; p--) {
			char const *q;

			/* affiche ce qu'il y a à droite de p */
			for (q = p; *q != '\0'; q++)
				putchar(*q);

			/* affiche ce qu'il y a à gauche de p */
			for (q = s; q != p; q++)
				putchar(*q);

			putchar('\r');
			fflush(stdout);
			if (_kbhit())
				return;
			sleep(0.1);

		}
	}
}


	int main(void)
	{
		
		int i = '\0';
		while (i != 'q')
		{
			char const *s = "           BIENVENU AU DISTRIBUTEUR DE BOISSON CHAUDE !                        ";
			scroll(s);


ça marche enfin ^^ j,arrive a passer a la boucle suivante ^^ c,est vrai que c,etait un peu con mais merci beaucoup ^^

Comme tu utilises des fonctions conio.h comme getch(), qui ne sont pas présentes dans <unistd.h> et des system("cls"); qui ne donneront un résultat que sous Windows, tu sembles finalement décider de faire un programme pour Windows seulement
il est vrai ^^ j,ai raccourcis le code ^^

il y a aussi "LAID" au lieu de "LAIT" :-D
Oups oui ^^""

Le code que tu postes ne contient pas les déclarations et initialisations de certaines variables qu'il utilise (i, n, prix etc.). Comme tu inclues #include "chose a int.h" //dans un fichier d,en tête j,ai mis tout les trucs a int pour plus de lisibilitée je suppose que c'est là que tu le fais.

Ce n'est pas exactement l'usage recommandé d'un fichier d'entête

Notre prof nous a utilisée a introduire les variables dans un fichier d,en tête pour ce projet ^^ il est vrai qu,il peut être mieux utiliser mais bon on fait avec ce que l,on a ^^""

tu utilises la variable prix pour compter le montant payé en pièces, tu calcule rendu, mais tu écrases sa valeur,... il faudra déboguer et peaufiner tout cela :-)
oui j,ai régler ça j,avais complètement oublier de le faire désolé ^^"" mais j,ai un autre petit soucis qui se trouve être que lord de la réinitialisation du programme il me remet non pas au message défilant mais comme si j,avais déjà payer ma boisson ^^"" Cela devrait être la dernière chose qui pose soucis ^^""" est ce a cause de mes variables ?

Leer0r
0
[Dal] Messages postés 6174 Date d'inscription mercredi 15 septembre 2004 Statut Contributeur Dernière intervention 2 février 2024 1 083
25 mai 2018 à 21:05
au sujet de ton dernier problème, poste ton code corrigé pour qu'on y voit plus clair.
0