IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Nombres premiers/Mon premier programme/cherche conseils


Sujet :

C

  1. #1
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut Nombres premiers/Mon premier programme/cherche conseils
    Salut,
    J'apprends le C grâce au livre open source "Le C en 20h" que je trouve génial. Je me suis un peu trop prise au jeu pour un programme qui n'a pas vraiment de correction prévue.
    Avez vous des idées pour améliorer ce programme ? La fonction getchar() en particulier me pose quelques soucis. Merci d'avance.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    #include <stdio.h>
    #include <math.h>
    #include <ctype.h>
     
    int main () {
    	printf("\nNombres premiers.\n\n");
    	char sortie=' ';
     
     
    	while (sortie!='S'){
    		int nombre = 1;
    		printf ("\nEntrez un nombre.\n\n");
    		scanf ("%d", & nombre);
     
     
    		int diviseur =2;
    		int modulo =1;
     
    		while (diviseur >1&& modulo !=0) {
    			//Pour eviter une erreur avec 1,2,3.
    			if (nombre<4){
    				diviseur=1;
    				modulo=1;
    			}
     
    			else	{
                                    //Pour eviter une perte de temps en calculs.
    				diviseur = nombre/2;
    				while (diviseur >1&& modulo !=0) {
    					nombre/diviseur;
    					modulo = nombre%diviseur;
    					printf("\n%d : %d = %d reste %d\n",nombre,diviseur,nombre/diviseur, nombre%diviseur);
    					diviseur--;
     
    				}
    			}
     
    		}
     
     
    		if (modulo == 0){
    			printf("\n%d n'est pas premier.\n", nombre);
    		}
     
    		else {
    			printf ("\n%d est premier.\n", nombre);
    		}
     
    		printf("\nTapez S pour sortir.\n\n");
    		sortie = getchar () ;
    		sortie = toupper (sortie);
     
     
    	}
     
    	printf ("\nMerci d'avoir joue.\n\n");
     
    	return 0;
    }

  2. #2
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Voici quelques idées pour améliorer ton programme :

    • la ligne nombre/diviseur; ne fait rien, supprime-la et compile avec les avertissements (-pedantic -Wall -Wextra) ;
    • la notion de nombre premier n'a de sens qu'au sein de l'ensemble des entiers naturels : utilise donc des entiers non signés ;
    • oublie l'interactivité en ligne de commande.. c'est complexe, fastidieux et peu portable : lis plutôt tes paramètres depuis argv, effectue les calculs que ton programme est sensé réaliser puis termine, confie l'interactivité (si elle est indispensable) à un script shell ;
    • détecte les overflows (dépassements de capacité) lorsque l'on fournit des nombres trop grands au programme : utilise strtoul pour la conversion ;
    • ne fais pas d'entrée-sortie (surtout non bufferisée ou avec '\n') dans la boucle de calcul, c'est très lent : pour en avoir une idée, compile ton programme avec les optimisations (-O2) et teste-le avec et sans le printf central, tu vas être étonnée (si tu dois afficher une information de progrès, ne le fais pas à chaque tour de boucle).


    C'est un début très correct.

  3. #3
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Merci pour ta réponse détaillée.

    Je suis pas sûre de tout comprendre alors je vais tenter de reformuler :

    1 quand je compile je dois utiliser la commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -o programme1 programme1.c -lm -pedantic -Wall -Wextra
    2 pour utiliser des nombres non signés, je rajoute une ligne type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if (nombre <=0)
        printf ("message d'erreur");
    et je corrige au passage pour le nombre 1 qui n'est pas premier...

    3 a l'air d'être une fonction ou un argument ?. Il faut que je me renseigne dessus.
    Un shell serait mieux pour recueillir des info de l'utilisateur. C'est un fichier avec du code qui n'a pas besoin d'être compilé. Type Python ?
    Est-ce que c'est utilisé sur Arduino ou est-ce surtout utile pour des programmes type jeux, logiciels... ?

    4 est un pointeur ? Qui sert à définir des intervalles pour un fonctionnement correcte du programme si j'ai bien compris ?
    Ça veut dire string tool ? Je garde ça en tête pour plus tard.

    5 tous les affichages en cours de calcul ralentissent le calcul. A éviter surtout quand ils ne sont pas nécessaires comme ici.
    Je peux utiliser la commande de compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -o programme1 programme1.c -lm -02
    pour que les calculs s'effectuent en mémoire tampon. Sûrement pour accélérer le processus.


    J'ai l'impression d'essayer de courir sans savoir déjà marcher.

    N'hésitez pas à corriger mes erreurs de compréhension et autres merci d'avance.

    Si un modérateur passe dans le coin : merci de déplacer mon sujet dans la section débutant.. j'ai posté trop vite. désolée.

  4. #4
    Membre confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2015
    Messages : 294
    Points : 558
    Points
    558
    Par défaut
    bonjour
    2)les nombres non signés sont de type unsigned int
    3) la declaration de main est: int main(int argc,char * argv[])
    donc argv est un tableau de char *,c'est les differents arguments en parametre de ta ligne de commande,argv[0] est le programme lui meme et argv[1] le premier argument en parametre s'il y en a un.
    4)strtol est une fonction qui convertit une chaine de caractères char * en long (regarde sur google.fr ou qwant.com,ton moteur de recherche)

  5. #5
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Salut,

    2 J'ai l'impression que j’aurai gagné du temps avec unsigned int Le point positif c'est qu'en faisant pleins d'erreurs je vais apprendre pleins de choses !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    #include <stdio.h>
    #include <ctype.h>
     
    int main () {
    	printf("\nNombres premiers.\n\n");
    	char sortie=' ';
     
     
    	while (sortie!='S'){
    		int nombre = 1;
    		printf ("\nEntrez un nombre.\n\n");
    		scanf ("%d", & nombre);
     
     
    		int diviseur =2;
    		int modulo =1;
     
    		while (diviseur <nombre/2 && modulo !=0) {
    			if (nombre<5){
    				//Pour eviter des erreurs avec 0,1,2,3,4 et negatifs.
    				modulo=0;
     
     
    			}
     
    			else	{
    				//Pour eviter une perte de temps en calculs.
    				while (diviseur <nombre/2 && modulo !=0) {
    					modulo = nombre%diviseur;
    					diviseur++;
     
    				}
    			}
     
    		}
     
     
    		if (modulo == 0 || nombre<=1 || nombre ==4){
     
    			if (nombre<0)
    				//negatifs.
    				printf("\nVous ne pouvez pas entrer un nombre negatif.\n\n");
     
    			else
    				if (nombre <=1)
    					//1 et 0.
    					printf("\n%d n'est ni un nombre premier ni un nombre compose.\n", nombre);
    				else 
    					//Nombres composés.
    					printf("\n%d est un nombre compose.\n\n", nombre);
    		}
     
    		else 
    			//nombres premiers
    			printf ("\n%d est un nombre premier.\n", nombre);
     
     
    		printf("\nTapez S pour sortir.\n\n");
    		sortie = getchar () ;
    		sortie = toupper (sortie);
     
     
    	}
     
    	printf ("\nA bientot.\n\n");
     
    	return 0;
    }
    3 Quand on déclare main on peut (doit ?) déclarer des arguments. C'est pour retourner ces mêmes arguments en sortie ?
    J'irai checker sur mon moteur de recherche (Duck duck go ) avec 4 strtol.

    Merci.

  6. #6
    Membre confirmé

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2015
    Messages
    294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mars 2015
    Messages : 294
    Points : 558
    Points
    558
    Par défaut
    3) c'est au cas où tu veuilles utiliser des arguments en parametres de ton programme ce qui t'etait suggéré et c'est d'ailleurs la signature preferable de main il me semble

  7. #7
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Oui, Je vais étudier tout ça et corriger ce programme pour qu'il soit efficace et élégant. Merci.

  8. #8
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Citation Envoyé par Jaenne Voir le message
    1 quand je compile je dois utiliser la commande :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -o programme1 programme1.c -lm -pedantic -Wall -Wextra
    Ton programme ne fait pas usage de la libmath, tu peux supprimer -lm et l'en-tête correspondant. Ajoute -std=c11 pour activer les vérifications de conformité à la dernière norme ISO (C11) tant que tu y es.


    Citation Envoyé par Jaenne Voir le message
    2 J'ai l'impression que j’aurai gagné du temps avec unsigned int Le point positif c'est qu'en faisant pleins d'erreurs je vais apprendre pleins de choses !
    Il est préférable de toujours utiliser des entiers non signés par défaut et de ne recourir aux entiers signés que lorsque l'on a besoin de représenter des nombres strictement négatifs. Bon, ça c'est mon opinion mais il existe une querelle de clocher à ce sujet.


    Citation Envoyé par Jaenne Voir le message
    3 a l'air d'être une fonction ou un argument ?. Il faut que je me renseigne dessus.
    argv est une variable qui contient les arguments entrés depuis la ligne de commande lors de l'invocation du programme. Tu trouveras tous les détails dans le cours C.


    Citation Envoyé par Jaenne Voir le message
    Un shell serait mieux pour recueillir des info de l'utilisateur. C'est un fichier avec du code qui n'a pas besoin d'être compilé. Type Python ?
    Est-ce que c'est utilisé sur Arduino ou est-ce surtout utile pour des programmes type jeux, logiciels... ?
    Attention : un script, lui-même interprêté par un shell. Python est effectivement un langage de script.. et même un peu plus, mais je pensais plutôt à du langage shell tout bête.

    L'idée est surtout de te montrer qu'on peut scinder les responsabilités : ton programme détermine si oui ou non un nombre est premier, point barre. Si tu commences à faire de la saisie et validation d'entrée utilisateur, l'interface va représenter 95% du code, limiter les possibilités d'application du programme et te détourner du but initial. Si je dispose d'un processeur multi-cœurs et que je veux lancer X vérifications de nombres premiers en parallèle sur autant de processus, alors je peux le faire si ton programme n'a pas d'interface.

    Tu peux choisir de faire autrement bien entendu, c'est encore mon avis (philosophie plutôt UNIX).


    Citation Envoyé par Jaenne Voir le message
    4 est un pointeur ?
    Il s'agit d'une fonction d'analyse lexicale qui extrait une valeur numérique entière à partir d'une chaîne de caractères.

    Les liens ne sont pas très visibles avec le thème graphique par défaut du forum : il y en a un sur le nom de la fonction dans mon message qui te mènera vers cppreference.com, un site collaboratif de très bonne qualité qui propose à la consultation les pages de manuel des bibliothèques standards C et C++, du point de vue de la norme. Garde-le sous le coude.


    Citation Envoyé par Jaenne Voir le message
    5 tous les affichages en cours de calcul ralentissent le calcul. A éviter surtout quand ils ne sont pas nécessaires comme ici.
    Je peux utiliser la commande de compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -o programme1 programme1.c -lm -02
    pour que les calculs s'effectuent en mémoire tampon. Sûrement pour accélérer le processus.
    Je te proposais simplement de tester ton programme (compilé avec les optimisations activées) sur des grands nombres premiers et non premiers (par exemple (1u << 31) - 1u et (1u << 31) respectivement) avec puis sans l'appel à printf au sein de la boucle interne, afin de te rendre compte de la gigantesque différence de performance. Lorsque ton programme demande l'affichage d'une chaîne sur la sortie standard, il réalise un appel système auprès du système d'exploitation. C'est incomparablement plus lent qu'une opération arithmétique entière et freine toute l'exécution.


    Citation Envoyé par Jaenne Voir le message
    J'ai l'impression d'essayer de courir sans savoir déjà marcher.
    C'est normal, ça viendra.


    Citation Envoyé par Jaenne Voir le message
    3 Quand on déclare main on peut (doit ?) déclarer des arguments.
    Pas forcément, tu peux déclarer int main(int argc, char *argv[]) ou à la rigueur int main().


    Citation Envoyé par Jaenne Voir le message
    C'est pour retourner ces mêmes arguments en sortie ?
    Je n'ai pas saisi la question, tu envoies ce que tu veux en sortie.

  9. #9
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Ok, je note. Merci pour toutes ces pistes que je vais étudier !

    C'est vrai que ça tourne super vite maintenant.

    Je compile donc avec :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    gcc -o programme1 programme1.c -std=c11 -pedantic -Wall -Wextra
    Je viens d'éditer mon programme mais il va encore changer.

  10. #10
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Salut,

    1 J'ai essayé de déclarer mes variables en unsigned int. J'ai trouvé que pour les réutiliser il faut écrire %u.

    Malheureusement, mon programme retourne :

    Tapez S pour sortir ou Entrez un nombre.

    -1
    18446744073709551615 est un nombre compose.



    Tapez S pour sortir ou Entrez un nombre.




    Edit :
    unsigned long int : %lu
    unsigned long long int : %llu

    Je me renseigne sur stroul, j'ai l'impression que c'est la clef mais pour l'instant je pige pas grand chose.


    Je vous joints le code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    #include <stdio.h>
    #include <ctype.h>
     
     
    unsigned int testPremier ( unsigned long long int nombre) {
    	unsigned int diviseur =2;
    	unsigned int modulo= 1 ;
    	//Pour eviter une perte de temps en calculs.
    	while (diviseur <= nombre/2 && modulo !=0) {
    		modulo = nombre%diviseur;
    		diviseur++;
    	}
    	return (modulo!=0);
    }
     int main (void) {
    	printf("\nNombres premiers.\n\n");
    	char sortie=' ';
     
     
    	while (sortie!='S'){
    		unsigned long long int nombre = 1;
    		printf ("Entrez un nombre.\n\n");
    		scanf ("%llu", & nombre);
     
     		if (nombre>4){
    			if (testPremier(nombre)==1)
    				//nombres premiers
    				printf ("%llu est un nombre premier.\n", nombre);
    			else
    				//Nombres composés.
    				printf("%llu est un nombre compose.\n", nombre);
    		}		
     
     
    		else{
     
     
    			if (nombre <=1)
    				//1 et 0.
    				printf("%llu n'est ni un nombre premier ni un nombre compose.\n", nombre);
    			else{
    				if (nombre<=3)
                                    //2 et 3.
    				printf ("%llu est un nombre premier.\n", nombre);
     
    				else
    				//4.
    				printf("%llu est un nombre compose.\n", nombre);
    			}
    		}
     
     
     
     
    		printf("\n\n\nTapez S pour sortir ou ");
    		sortie = getchar () ;
    		sortie = toupper (sortie);
     
     
    	}
     
    	printf ("...\n\n");
     
    	return 0;
    }
    Merci d'avance pour vos lumières.

  11. #11
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Quel est précisément le souci ?

    Si tu tentes de stocker -1 dans une variable entière non signée, ça ne risque pas de produire le résultat escompté !

  12. #12
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Tada ! J'ai trouvé =)

    On rentre la donnée en long long int puis elle est éventuellement multipliée par -1 et enfin convertie en long long unsigned int.
    Peut être que je devrais faire pareil pour les float ?

    Le nombre serait entré en long double float modifié pour devenir un long long int puis transformé en long long unsigned int. Il faut que je trouve un tableau de correspondance type de variable/flag-joker.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #include <stdio.h>
    #include <ctype.h>
     
    unsigned int testPremier ( unsigned long long int nombre) {
    	unsigned int diviseur =2;
    	unsigned int modulo= 1 ;
    	//Pour eviter une perte de temps en calculs.
    	while (diviseur <= nombre/2 && modulo !=0) {
    		modulo = nombre%diviseur;
    		diviseur++;
    	}
    	return (modulo!=0);
    }
     int main (void) {
    	printf("\nNombres premiers.\n\n");
    	unsigned char sortie=' ';
    	long long int nombre = 0;
     
    	while (sortie!='S'){
     
    		printf ("Entrez un nombre. ");
    		scanf ("%lld", & nombre);
    		if (nombre<0) 
    			nombre*= -1 ;
    		 nombre = (unsigned long long int )nombre;
     
     		if (nombre>4){
    			if (testPremier(nombre)==1)
    				//nombres premiers
    				printf ("%llu est un nombre premier.\n", nombre);
    			else
    				//Nombres composés.
    				printf("%llu est un nombre compose.\n", nombre);
    		}		
    		else{
     			if (nombre <=1)
    				//1 et 0.
    				printf("%llu n'est ni un nombre premier ni un nombre compose.\n", nombre);
    			else	if (nombre<=3)
    				//2 et 3.
    				printf ("%llu est un nombre premier.\n", nombre);
    			else
    			//4.
    			printf("%llu est un nombre compose.\n", nombre);
    		}
    		printf("\n\n\nTapez S pour sortir ou ");
    		sortie = getchar () ;
    		sortie = toupper (sortie);
    	}
     	printf ("...\n\n");
     	return 0;

  13. #13
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Je n'ai absolument pas saisi ce que tu essaies de faire.

  14. #14
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Le cas des nombre négatifs :

    Dans la version précédente, je testais si le nombre saisit était négatif. Dans ce cas, le programme renvoyait un message d'erreur. Maintenant si l'utilisateur entre -1 le programme répond 1 n'est ni premier ni composé.

    Le cas des flottants :

    Dans la version actuelle, si l'utilisateur entre 7.28 le programme répond 28 est un nombre composé. J'aimerai que le programme récupère la partie entière de 7.28 plutôt que la partie décimale.

    Le programme :

    Donc il faut que :
    1) le programme récupère le nombre saisit dans une variable de type long long float. Peut être %llf ou %llg ?
    2) la variable soit convertie en long long int : %lld
    3) tester si le nombre est négatif.
    si oui, multiplier le nombre par -1
    4) convertir la variable en long long unsigned int : %llu

    J'imagine qu'il y a plus beaucoup simple mais du haut de mes pauvres connaissances en programmation, c'est le seul moyen que je vois.
    En tous cas, ce programme est un bon exercice pour apprendre.

    Edit :
    Le programme ne réagit plus pareil. Maintenant si on entre 456.2, il répond "456 est composé" et sur une autre ligne "2 est premier".

  15. #15
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Edit : Je n'ai ce message d'erreur que si je lance le programme avec "&" à la fin.

    J'ai détraqué ma console en cherchant les limites de mon programme.
    En tapant un nombre de 12 chiffres, j'ai eu un message d'erreur nouveau dans la console.

    Peut être que ça n'a rien à voir mais j'ai aussi essayé de passer Scite en utf-8 par defaut en suivant les consignes du manuel. Sans succès.

    Aucun programme, même le plus simple ne s'exécute normalement maintenant.
    Je suis embêtée car je ne vois pas quoi faire pour régler ça.

    Pour info :

    OS : Linux
    Ligne de commande pour compiler : gcc -o programme programme.c -std=c11 -pedantic -Wall -Wextra
    Editeur de texte : Scite mais testé aussi avec Gedit.

    Deux screenshot :

    https://ncloud.zaclys.com/index.php/s/9lpZ74eps3DaZod

    https://ncloud.zaclys.com/index.php/s/B2fEHoo8il9Ih0A

    Le code buggé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    #include <stdio.h>
     
    unsigned int testPremier ( unsigned long long int debut) {
    	unsigned long long int diviseur =2;
    	unsigned long long int modulo= 1 ;
    	//Pour eviter une perte de temps en calculs.
    	while (diviseur <= debut/2 && modulo !=0) {
    		modulo = debut%diviseur;
    		diviseur++;
    	}
    	return (modulo!=0);
    }
    int main (void) {
    	long long int debut= 0;
    	long long int fin=100;
    	long long unsigned int i =0;
    	long long int memoireDebut =0;
    	printf("\nNombres premiers.\n\n");
    	printf ("Entrez un nombre de depart. ");
    	scanf ("%lld", & debut);
    	printf ("Entrez un nombre de fin. ");
    	scanf ("%lld", & fin);
    	if (debut<0) 
    		debut*= -1 ;
     
    	memoireDebut = debut= (unsigned long long int )debut;
    	if (fin<0) 
    		fin*= -1 ;
    	fin = (unsigned long long int) fin;
    	if (fin<debut)
    		fin=debut;
     
    	while(debut<=fin){
    		if (debut>4){
    			if (testPremier(debut)==1){
    				//nombres premiers
    				i++;
    				printf (" %llu ", debut);
    			}
    		}		
    		else{
     			if (debut >1&&debut<=3){
    				//2 et 3.
    				i++;
    				printf (" %llu ", debut);
    			}
    		}
    		debut++;
    	}
    	printf ("\n\nEntre %lld et %llu, %llu nombres premiers trouves.\n\n",memoireDebut,fin, i);
     	return 0;
    }
    Merci d'avance.

  16. #16
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Lorsque tu demandes au shell de démarrer ton programme avec &, le processus est exécuté en arrière-plan et l'invite de commandes récupère immédiatement la main. Le comportement décrit est donc celui attendu.

    La validation de l'entier passé en paramètre de ton programme doit se faire via strtoul(l). Lis attentivement la page de man ainsi que les exemples. Je détaille également ici (clic !) la combinaison de conditions qui permet de détecter une erreur de conversion.

  17. #17
    Futur Membre du Club Avatar de Jaenne
    Femme Profil pro
    AVS
    Inscrit en
    Décembre 2008
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 41
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : AVS

    Informations forums :
    Inscription : Décembre 2008
    Messages : 15
    Points : 7
    Points
    7
    Par défaut
    Salut,

    Merci pour ces info. C'est dommage de ne pas pouvoir faire tourner mon programme en arrière plan. C'est super long avec des nombres de 17 chiffres.
    Je ne savais pas que je pouvais taper "man commande" pour une commande en C Je vais l'étudier de près et revenir avec pleins de questions.
    Pour l'instant la discussion ou mène ton lien me paraît bien difficile à comprendre mais je vais m'accrocher et je ne doute pas que ça ira mieux très vite !
    ça me permettra de gérer correctement les nombres à virgules. Ça semble important pour la suite de mes projets.

    Je viens juste d'apprendre les pointeurs et à gérer mes fonctions dans différents fichiers. Prochaine étape : les tableaux.
    J'espère que je saurai bientôt enregistrer les résultats de ce programme dans un fichier.

    Quelles autres pistes dois-je explorer pour :

    - passer mes paramètres directement dans la commande au lancement du programme ?
    Dans ma tête ça ressemble à ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #include <stdio.h>
    #include "premiersCalcul.h"
     
    int main (void) {
    	long long int nombreTeste , fin= 0;
    	long long unsigned int debut, i =0;
    	printf("\nNombres premiers.\n\n");
    	nombreTeste = debut = saisiConv ("depart");
    	fin = saisiConv ("fin");
    	if (fin<nombreTeste)
    		fin=nombreTeste;
    	printf("\nJe vais afficher les nombres premiers compris entre, %llu et %llu.\nCela peut prendre quelques secondes ou plusieurs heures.\n\n",debut,fin);
    	while(nombreTeste<=fin){
    		if (nombreTeste>4){
    			if (testPremier(nombreTeste)==1){
    				//nombres premiers
    				i++;
    				printf (" %llu ", nombreTeste);
    			}
    		}		
    		else{
     			if (nombreTeste>1 && nombreTeste<=3){
    				//2 et 3.
    				i++;
    				printf (" %llu ", nombreTeste);
    			}
    		}
    		nombreTeste++;
    	}
    	printf ("\n\nEntre %lld et %llu, %llu nombres premiers trouves.\n\n",debut,fin, i);
     	return 0;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <stdio.h>
     
    unsigned int testPremier ( unsigned long long int nombre) {
    	unsigned long long int diviseur =2;
    	unsigned long long int modulo= 1 ;
    	//Pour eviter une perte de temps en calculs.
    	while (diviseur <= nombre/2 && modulo !=0) {
    		modulo = nombre%diviseur;
    		diviseur++;
    	}
    	return (modulo!=0);
    }
     
     
    unsigned long long int saisiConv(unsigned char chaine []){
    	long long int nombre = 0;
    	printf ("Entrez un nombre de %s. ",chaine);
    	scanf ("%lld", &nombre);
    	if (nombre<0) 
    		nombre*= -1 ;
    	nombre= (unsigned long long int )nombre;
    	return nombre;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    #ifndef PREMIERSCALCUL_H
    #define PREMIERSCALCUL_H
     
    	unsigned int testPremier ( unsigned long long int nombre);
     
    	long long unsigned int saisiConv(char chaine []);
     
    #endif

  18. #18
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Citation Envoyé par Jaenne Voir le message
    Salut,

    Merci pour ces info. C'est dommage de ne pas pouvoir faire tourner mon programme en arrière plan. C'est super long avec des nombres de 17 chiffres.
    ...
    C'est pas ton programme qui est lent, c'est ton algo. Si tu veux améliorer les perfs change d'algo.

    Quand tu as besoin de connaître la magnitude des entiers que tu manipules, tu peux utiliser les type de stdint.h → uint64_t te donne un entier non signé sur 64 bits, car les types «classiques» peuvent différer d'une plateforme à l'autre.

  19. #19
    Expert confirmé
    Inscrit en
    Mars 2005
    Messages
    1 431
    Détails du profil
    Informations forums :
    Inscription : Mars 2005
    Messages : 1 431
    Points : 4 182
    Points
    4 182
    Par défaut
    Le souci avec les types entiers de taille fixe, c'est que la bibliothèque standard n'offre pas de fonctions qui les manipule nativement. Si on veut récupérer un uint64_t depuis une chaîne par exemple, on doit de toute manière passer par strtoul et macro-tester les paramètres. C'est ce que je ferais effectivement, mais c'est peut-être un peu avancé pour l'OP.

    @ l'OP : pour récupérer les arguments de la ligne de commande, il faut utiliser une signature spécifique pour main : int main(int, char **) . Il faut toutefois avoir au moins la notion de ce qu'est une chaîne de caractères C. Tout est expliqué dans le cours de base.

    Globalement tu sembles avoir une bonne méthodologie : découper les responsabilités et sous-problèmes en fonctions au sein de ton programme, commencer à faire des modules. Continue comme cela.

  20. #20
    Membre émérite
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Points : 2 601
    Points
    2 601
    Par défaut
    Citation Envoyé par Matt_Houston Voir le message
    Le souci avec les types entiers de taille fixe, c'est que la bibliothèque standard n'offre pas de fonctions qui les manipule nativement. Si on veut récupérer un uint64_t depuis une chaîne par exemple, on doit de toute manière passer par strtoul et macro-tester les paramètres. C'est ce que je ferais effectivement, mais c'est peut-être un peu avancé pour l'OP..
    La standard incite à passer par un scanf et pour ça il y a la macro SCNu64, il y a aussi des macros pour printf, pour initialiser les constantes (qui rajoute le bon suffixe), etc ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    uint64_t u64 = UINT64_C(3825123056546413050);
    printf("u64 = %" PRIu64 "\n", u64);
    scanf("%"SCNu64, &u64);

Discussions similaires

  1. [Conseils/Aide] Structure de mon premier programme
    Par Invité2 dans le forum Débuter
    Réponses: 44
    Dernier message: 13/09/2008, 14h08
  2. mon premier programme j2me
    Par adilo dans le forum Java ME
    Réponses: 1
    Dernier message: 14/09/2006, 08h43
  3. [JDOM] Mon premier programme java-xml
    Par adilo dans le forum Format d'échange (XML, JSON...)
    Réponses: 3
    Dernier message: 12/07/2006, 13h12
  4. [Language] Aide sur mon premier programme Java?
    Par hash2zo dans le forum Langage
    Réponses: 15
    Dernier message: 27/09/2005, 19h26
  5. [Débutant] Mon premier programme: rien ne va...
    Par vincent0 dans le forum OpenGL
    Réponses: 10
    Dernier message: 02/08/2005, 13h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo