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 :

Erreur de Segmentation non localisée


Sujet :

C

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    novembre 2018
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : novembre 2018
    Messages : 8
    Points : 5
    Points
    5
    Par défaut Erreur de Segmentation non localisée
    Bonjour,
    j'essaye d'écrire un code qui puisse replacer les occurrences d'un texte par un autre en utilisant les primitives système posix mais j'ai une erreur de segmentation dans mon code que je n'arrive pas à localiser (j'ai essayé gdb mais en vain) si quelqu'un arriverait à cibler l'erreur, je vous remercie.

    Code C : 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
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    #include <stdio.h> 
    #include <string.h> 
    #include <stdlib.h> 
    #include <sys/stat.h> /* open */
    #include <unistd.h> /*read*/
    #include <fcntl.h>  /* open */
    #include <stdio.h>  /* printf */
    #include <string.h> /* strerror() */
    #include <errno.h>  /* errno */
    
    
    #define READ_LEN 1024
    
    /**
     * \brief source file copied into destination file
     * \param source file name
     * \param source file destination 
     * \return 1 succes, -1 if fail
     */
     
    
    int replaceWord(char * s, char *oldW, char * newW,char *result) 
    { 
        //char result[1024]; 
        int i, cnt, longueur = 0; 
        int newWlen = strlen(newW); 
        int oldWlen = strlen(oldW); 
        int long_s = READ_LEN;
        // Counting the number of times old word 
        // occur in the string 
        for (i = 0; i < READ_LEN ; i++) 
        { 
            if (strstr(s[i], oldW) == s[i]) 
            { 
                cnt++; 
      
                // Jumping to index after the old word. 
                i += oldWlen - 1; 
            } 
        } 
      
        // Making new string of enough length 
        longueur = i + cnt * (newWlen - oldWlen) + 1; 
      
        i = 0, cnt = 0;
         
        while (cnt < READ_LEN) 
        { 
            // compare the substring with the result 
            if (strstr(s, oldW) == s) 
            { 
                strcpy(&result[i], newW); 
                i += newWlen; 
                cnt += oldWlen; 
            } 
            else
                result[i++] = s[cnt++]; 
        } 
      
        
        return longueur; 
    } 
    
    
    int main(int argc, char *argv[]){
    
    
    
    // Traitement du texte du fichier (sed)
    
      
        char result[2048];
        
    
    	/* OUVERTURE */
        printf("%s %s %s %s\n",argv[0],argv[1],argv[2],argv[3]);
    	int descripteur1= open(argv[3],O_RDONLY,0666);
    	if(descripteur1 ==-1) {
    		perror("Ouverture du fichier source echouee"); 
    		return -1;
    		}
    
    	int descripteur2= open(argv[4],O_WRONLY | O_CREAT , 0666);
    	if(descripteur2 ==-1) {
    		perror("Ouverture du fichier destination echouee");
    		return -1;
    		}
    
    	char buf[READ_LEN];
    	ssize_t nb_lus=0,nb_ecris=0;
        int longueur;
        
    	/* COPIE */
    
    	while((nb_lus = read(descripteur1,buf,1024))>0) {	
            longueur = replaceWord(buf, argv[1], argv[2], result); 			
    		nb_ecris=write(descripteur2, result, longueur);
    		if (nb_ecris==-1) return -1;
    		//nb_lus= read( descripteur1,&buf, 1);
    	
    	}
    
    	printf("copie terminee \n");
    
    	/*FERMETURE */
    	if((close(descripteur1)) ==-1) {perror("Fermeture du fichier fichier echouee");return -1;}
    	else{
    		close(descripteur1);
    		if((close(descripteur2))==-1) {perror("Fermeture du fichier destination echouee"); return -1;}
    		else close(descripteur2);
    		
    	}
    	
    	return 1;	
    }

  2. #2
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    février 2008
    Messages
    2 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : février 2008
    Messages : 2 084
    Points : 4 048
    Points
    4 048
    Billets dans le blog
    4
    Par défaut
    Bonjour.

    Tout d’abord enlève le =C des balises de code pour avoir le bon affichage sur le forum.

    Sans avoir cherché l’erreur j’ai juste regardé la fonction suivante :
    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
    int replaceWord(char * s, char *oldW, char * newW,char *result) 
    { 
    //char result[1024]; 
    int i, cnt, longueur = 0; 
    int newWlen = strlen(newW); 
    int oldWlen = strlen(oldW); 
    int long_s = READ_LEN;
    // Counting the number of times old word 
    // occur in the string 
    for (i = 0; i < READ_LEN ; i++) 
    { 
    if (strstr(s[i], oldW) == s[i]) 
    { 
    cnt++; 
     
    // Jumping to index after the old word. 
    i += oldWlen - 1; 
    } 
    }
    ...
    Lorsque tu transmets des pointeurs à une fonction pense à rendre le plus restrictif possible. Ça te permettra de voir si tu manipules des données en écriture alors que tu n’en as pas le droit.
    Ici s est une chaîne en lecture, il faut donc la déclarer const. La même remarque est aussi applicable à oldW et NewW.

    La fonction strstr(); renvoie l’adresse de la première occurence trouvée ou NULL dans les autres cas. Ton utilisation ne me semble pas correcte. Il vaut mieux écrire if (strstr (s[i], oldW)) ou if (!strstr (s[i], oldW)).

    Il y a bien d’autres remarques pour rendre ton code plus robuste mais j’arrête là pour l’instant 😉.
    Utilisation de Glade avec Gtk+ - N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk

  3. #3
    Expert confirmé
    Avatar de gerald3d
    Homme Profil pro
    Conducteur de train
    Inscrit en
    février 2008
    Messages
    2 084
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Côte d'Or (Bourgogne)

    Informations professionnelles :
    Activité : Conducteur de train
    Secteur : Transports

    Informations forums :
    Inscription : février 2008
    Messages : 2 084
    Points : 4 048
    Points
    4 048
    Billets dans le blog
    4
    Par défaut
    Je reviens vers toi ayant un peu de temps à te consacrer.

    Je reprends la fonction replaceword (); déjà traîtée pour lui ajouter des vérifications :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int replaceWord(const char *s, const char *oldW, const char *newW, char *result) 
    {
      if (!s || !oldW || !newW || !result) {
        fprintf (stderr, "s, oldW, newW and result must be valid pointers in replaceWord (); !\n");
        return -1;
      }
    ...
    Ceci rend encore plus robuste l'utilisation de la fonction. La seule vérification qu'on ne peut pas faire c'est d'être sûr que les chaînes se terminent bien par '\0' et que result est bien alloué pour la longueur nécessaire. Il y a un gros risque de dépassement de tampon ici.

    Une fois cette étape réalisée on progresse un peu dans le code. Tu désires compter le nombre d’occurrences d'un mot dans la phrase contenue dans s.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    for (i = 0; i < READ_LEN ; i++) 
        { 
          if (strstr(s[i], oldW) == s[i]) 
            { 
    	  cnt++; 
     
    	  // Jumping to index after the old word. 
    	  i += oldWlen - 1; 
            } 
        }
    Quelques remarques :
    1. Tu utilises READ_LEN comme longueur de s. Pourquoi pas puisque tu utilises cette valeur pour initialiser une partie de tes buffers. Pourquoi ne pas prendre plutôt la longueur réelle de s qui de toute façon ne dépassera pas READ_LEN ? On gagnerai un peu en temps d’exécution.
    2. Tu incrémentes cnt à chaque fois que tu trouves une occurrence. Sauf que tu ne l'initialises pas avant. Cette variable pourrait tout aussi bien contenir 23 par exemple au départ de la recherche !
    3. Tu utilises strstr ();. J'ai déjà écris quelques lignes à son sujet dans mon premier post. Tu utilises s[i] pensant que tu vas te placer sur l'adresse de s+i. Malheureusement ce n'est pas le cas. En réalité s[i] te donne la valeur de la donnée située en s+i. Utilise plutôt un pointeur temporaire que tu pourras incrémenter pour faire de sauts de mot en mot.
    4. Pour finir avec cette première boucle de recherche, il n'est pas nécessaire d'utiliser une boucle for(); même si ce n'est pas une erreur, il va de soit. On peut utiliser une boucle while qui vérifie que le pointeur temporaire est toujours valide en fonction de sa longueur. On gagne une variable. Ce n'est pas grand chose, mais moins il y en a, mieux on se porte .

    Tout ceci pourrait donner :
    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
    int replaceWord(const char *s, const char *oldW, const char *newW, char *result) 
    {
      if (!s || !oldW || !newW || !result) {
        fprintf (stderr, "s, oldW, newW and result must be valid pointers in replaceWord (); !\n");
        return -1;
      }
     
      int i, cnt=0, longueur = 0; 
      int newWlen = strlen(newW); 
      int oldWlen = strlen(oldW); 
      int long_s = strlen (s);
      // Counting the number of times old word 
      // occur in the string
      const char *text = s;
      while (text < s+long_s)
        { 
          if (strstr(text, oldW))
            { 
    	  cnt++; 
     
    	  // Jumping to index after the old word. 
    	  text += oldWlen - 1; 
            }
         else
            break;
        }
    ...
    Je ne détiens pas la vérité, loin de là. D'autres viendront sûrement modifier ou présenter une autre manière d’appréhender ta problématique. Mais si tu suis ces quelques petits conseils de base, je suis sûr que tu trouveras rapidement les solutions à tes problèmes de gestion mémoire .
    Utilisation de Glade avec Gtk+ - N'oubliez pas de consulter les FAQ Gtk et les cours et tutoriels Gtk

  4. #4
    Membre éprouvé Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mai 2011
    Messages
    407
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : mai 2011
    Messages : 407
    Points : 947
    Points
    947
    Par défaut
    Hello,

    Comme d'habitude, un découpage en fonctions aide. J'y vais de mon petit code, juste pour calculer le nombre d'occurences:
    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>
    #include <string.h>
     
    int countOccur(char *str,char *searched) {
    	if(*searched==0)
    		return(-1);
    	int count=0;
    	while((str=strstr(str,searched))!=NULL) {
    		count++;
    		str++;
    	}
     
    	return(count);
    }
     
    int main(void) {
    	char *str="aababcabcd";
    	char *searched="bc";			// exemple
     
    	printf("%s se trouve %d fois dans %s\n",searched,countOccur(str,searched),str);
     
    	return(0);
    }

  5. #5
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 7 462
    Points : 21 257
    Points
    21 257
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par edgarjacobs Voir le message
    Comme d'habitude, un découpage en fonctions aide. J'y vais de mon petit code, juste pour calculer le nombre d'occurences
    Pas de parenthèses au return, ce n'est pas une fonction.
    Et puis pourquoi ne pas aérer un peu... ?

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int countOccur(char *str,char *searched) {
    	if (*searched == '\0')
    		return -1;
     
    	int count;
    	for (count=0; (str=strstr(str, searched)) != NULL; count++, str++);
    	return count;
    }
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  6. #6
    Membre éprouvé Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    mai 2011
    Messages
    407
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 59
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : mai 2011
    Messages : 407
    Points : 947
    Points
    947
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Pas de parenthèses au return, ce n'est pas une fonction.
    J'ai appris (en bonne partie) le C avec le K & R première édition (que je possède toujours). Et dans tous les codes du bouquin, la valeur du return est entre ( ). Ça m'est resté.... Et aussi, sizeof qui n'est pas une fonction, nécessite des ( ) pour les type natifs

    Citation Envoyé par Sve@r Voir le message
    Et puis pourquoi ne pas aérer un peu... ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int countOccur(char *str,char *searched) {
    	if (*searched == '\0')
    		return -1;
     
    	int count;
    	for (count=0; (str=strstr(str, searched)) != NULL; count++, str++);
    	return count;
    }
    L'éternelle discussion: le for() sous-entend que l'on connait le nombre d'éléments à parcourir, le while() sous-entend que l'on s'interrompt pour un événement donné.

  7. #7
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 263
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 263
    Points : 27 916
    Points
    27 916
    Par défaut
    Salut,
    Citation Envoyé par edgarjacobs Voir le message
    L'éternelle discussion: le for() sous-entend que l'on connait le nombre d'éléments à parcourir, le while() sous-entend que l'on s'interrompt pour un événement donné.
    De mon point de vue, le problème est beaucoup plus complexe que cela...

    Il ne faut pas oublier que C a été développé à une époque où le moindre byte coutait la moitié d'un bras, que ce soit en terme de mémoire ou d'espace de stockage. On doit donc reconnaitre à K et à R le fait d'avoir créé un langage expressif tout en fournissant un grand nombre de "sucres syntaxiques" permettant de limiter très fortement le nombre de bytes nécessaire à l'écriture du code.

    Ajoutons y le fait que, certains (la plupart?) de ces sucres syntaxiques aidaient énormément les compilateurs à optimiser le code binaire généré.

    Et comme les écrans de l'époque étaient -- eux aussi -- vachement restreints quant au nombre de caractères qu'ils étaient susceptibles d'afficher, tout se liguait contre le développeur de manière à l'inciter à fournir le code "le plus compact possible".

    Seulement, voilà : les circonstances ont complètement changé:
    1. à l'heure actuelle, le byte ne vaut plus rien, au point qu'on te le jette à la tête par Giga (ou peu s'en faut ),
    2. les capacités d'optimisation des compilateurs ont évolué au point qu'ils n'ont plus forcément besoin d'être aidés dans leur travail; deux codes a priori différents, l'un utilisant une boucle for et l'autre utilisant une boucle (do) while tout en mettant en place une logique identique ayant de fortes chances de générer un code binaire exécutable parfaitement identique.
    3. Les écrans sont suceptibles de permettre l'affichage d'une centaine de ligne sur plusieurs centaines de colonnes


    La bonne question est donc: faut-il maintenir les habitudes du passé en essayant de garder le code "aussi compact que possible" parce que l'on en a (toujours) la possibilité, ou faut il privilégier un code plus "expressif", et donc "plus lourd" étant acquis que le résultat final sera de toutes manière identique

    A titre personnel, je préfère un code qui facilite la compréhension de celui qui le lit, y compris lorsqu'il n'est pas forcément "au mieux de sa forme", ou qu'il est quelque peu distrait dans sa lecture. D'autres préfèreront sans doute maintenir l'usage des sucres syntaxiques autorisés pour des raisons qui leur sont propres...
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Expert éminent
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    juillet 2013
    Messages
    3 011
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : juillet 2013
    Messages : 3 011
    Points : 6 690
    Points
    6 690
    Par défaut
    Citation Envoyé par koala01 Voir le message
    La bonne question est donc: faut-il maintenir les habitudes du passé en essayant de garder le code "aussi compact que possible" parce que l'on en a (toujours) la possibilité, ou faut il privilégier un code plus "expressif", et donc "plus lourd" étant acquis que le résultat final sera de toutes manière identique
    Ta question ne veut rien dire du tout

    Tu prends l'opérateur ->. C'est un sucre syntaxe qui remplace *. ou (*)..
    Est-il plus compact ? Oui Et donc pour toi il est moins expressif
    Et je te l'accorde - le code sans l'opérateur -> est plus lourd

    Tu prends les opérateurs += -= *= /=.
    Sont-ils plus compact ? Oui Et donc pour toi ils sont moins expressif
    Et je te l'accorde - le code sans ces opérateurs est plus lourd si on parenthèse.

    Une boucle for est pour moi une boucle pour parcourir une collection. Après si dans ton code tu colles des for(;;) infini, je n'y peux rien.
    Mais la différence entre une boucle for et while c'est zéro.
    • zéro en compréhension. C'est une boucle, il faut lire le code pour comprendre ce qu'on va répéter.
    • zéro en terme de lignes. Quoique la boucle while est 1 ou 2 lignes de + parce que les initialisations se font avant et non pas dedans

    Le seul truc, c'est qu'avec la boucle for, à sa sortie, l'incrément peut être +1 par rapport à l’incrément d'une boucle while

  9. #9
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 7 462
    Points : 21 257
    Points
    21 257
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par edgarjacobs Voir le message
    Eéternelle discussion: le for() sous-entend que l'on connait le nombre d'éléments à parcourir, le while() sous-entend que l'on s'interrompt pour un événement donné.
    Euh non. C'est juste chaque fois que je vois "init" + "test" + "incrément" j'ai le réflexe "for()". Mais qu'un seul des 3 vienne à manquer et je mets un "while()" (autrement dit, jamais de for(;;) chez moi).

    En revanche, mettre for(init1, init2; test; increment1, increment2) n'est pas systématique. Disons que je le fais quand je veux montrer un lien fort entre les éléments...
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  10. #10
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : mai 2010
    Messages : 481
    Points : 1 773
    Points
    1 773
    Par défaut
    Bonjour

    Citation Envoyé par Sve@r Voir le message
    Pas de parenthèses au return, ce n'est pas une fonction.

    Sur ce point (cas actuel) , oui pas besoin des parenthèses.

    Cependant, il n'est pas dit ou signifier qu'il ne faut pas mettre des parenthèses. Selon moi ça a du sens de mettre des parenthèses même-si, je vous l'accorde dans le cas présent return ne nécessite pas de parenthèse sur la valeur à retourner.

    En revanche, vous aurez peut-être besoin des parenthèses pour bien signifier que l'ont tien à effectuer l'évaluation d'une expression avec ordre de priorité dont le résultat converti au bon type par return sera renvoyé à l'appelant et justement, le langage de programmation C permet d'utilisation des parenthèse pour modifier ou imposer l'ordre comme dans les mathématiques. Il ne faut pas également oublier que return ne renvoie pas bêtement une valeur ou met fin à une fonction ; return peut parfaitement procéder à l'évaluation d'une expression ; puis la conversion du résultat (valeur) /de l'expression dans le bon type de la fonction (et au passage permettre au compilateur d'émettre un warning si ce n'est pas le bon type attendu dans le cas ou le type que renvoie la fonction est autre que le type des variables traitées dans l'expression/de résult de l'expression) puis il se charge de renvoyer le résultat et terminer la fonction.
    Et si le l'évaluation de l'expression par return contient plusieurs opérateurs son évaluation dépendra alors de l'ordre dans lequel les opérations sont effectuées ainsi donc si l'on procède comme l'exemple ci-dessous, on ne remarquera pas forcément ou du moins pas tout de suite la différence de résultat qui peut avoir un impact et voir considérable selon l'implémentation de l'algorithme permettant la résolution du problème.
    Au final pour le renvoi d'une valeur et une seule valeur; pas besoin de parenthèse mais pour les autres cas et selon la façon dont est implémenté l'algorithme, des parenthèses peuvent être nécessaire.

    Code C : 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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
     
     
    int f_foo_a( int x, int y, int z){
        return x + y * z;
    }
     
     
    int f_foo_b( int x, int y, int z){
        return ( x + y) * z;
    }
     
     
    /*
     * un warning sera émis 
     */
    bool f_foo_c( int x, int y, int z){
        return ( x + y) * z;
    }
     
     
     
     
    int main( void ){
     
        /*    Cas 1    */
        if( f_foo_a(1,1,2) == f_foo_b(1,1,2) )
            (void)puts("Vrai");
        else
            (void)puts("FAUX");  /*    oui 3 != 4    */
     
        /*    Cas 2    */
        if( f_foo_a(2,1,2) == f_foo_b(1,1,2) )
            (void)puts("Vrai");    /* oui 4 == 4    */
        else
            (void)puts("FAUX");
     
        return EXIT_SUCCESS;
    }
    À bientôt.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  11. #11
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 7 462
    Points : 21 257
    Points
    21 257
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    En revanche, vous aurez peut-être besoin des parenthèses pour bien signifier que l'ont tien à effectuer l'évaluation d'une expression avec ordre de priorité dont le résultat converti au bon type par return sera renvoyé à l'appelant et justement, le langage de programmation C permet d'utilisation des parenthèse pour modifier ou imposer l'ordre comme dans les mathématiques.
    Sans déconner quoi, t'es en train de citer l'évidence. Tous les langages de prog offrent des opérateurs qui ont différentes priorités et offrent aussi alors la possibilité de mettre des parenthèses pour modifier ces priorités !!!
    Et ce n'est même pas une question de return mais d'expression dans un cadre général. Une expression c'est des opérandes et des opérateurs et éventuellement des parenthèses pour gérer l'ordre des opérations.
    Et donc la syntaxe du return c'est return expression; sans parenthèses (si l'expression, elle, en a c'est son problème, pas celui du return).
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  12. #12
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : mai 2010
    Messages : 481
    Points : 1 773
    Points
    1 773
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    ... la syntaxe du return c'est return expression; sans parenthèses (si l'expression, elle, en a c'est son problème, pas celui du return).
    Je pense que l'on ne se comprend pas. Je ne dis pas que return doit ou ne doit pas avoir des parenthèses, je dis juste que les parenthèses dans le cas d'une expression telle que l'on peut avoir sous cette forme return 1+1*2; avec un return peuvent influencer le résultat que return renverra. Donc, pour une expression donner qui contient plusieurs opérateurs et que return va évaluer dépendra alors de l'ordre dans lequel les opérations sont effectuées. Il est donc parfois nécessaire de mettre des parenthèses "return (1+1)*2;" et cela ne veut pas dire que l'on considère return comme étant une fonction et rien empêche également que l'on stocke le résultat de l'expression dans une variable qui sera par la suite renvoyée par return.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  13. #13
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 7 462
    Points : 21 257
    Points
    21 257
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    Je pense que l'on ne se comprend pas.
    Normal, j'ai parlé du return et toi tu embrayes sur les expressions.
    Citation Envoyé par sambia39 Voir le message
    Je ne dis pas que return doit ou ne doit pas avoir des parenthèses, je dis juste que les parenthèses dans le cas d'une expression telle que l'on peut avoir sous cette forme return 1+1*2; avec un return peuvent influencer le résultat que return renverra.
    Oui mais tout le monde le sait ça !!! Et il le sait depuis le CM2 où on lui montre la petite image avec la voiture "+" et "-" qui laisse la place à l'ambulance "*"; et l'ambulance "*" qui est obligée de s'arrêter au passage à niveau avec le train contenant (a+b) qui lui passe devant.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  14. #14
    Membre chevronné
    Avatar de sambia39
    Homme Profil pro
    No Comment
    Inscrit en
    mai 2010
    Messages
    481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : No Comment
    Secteur : High Tech - Matériel informatique

    Informations forums :
    Inscription : mai 2010
    Messages : 481
    Points : 1 773
    Points
    1 773
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Normal, j'ai parlé du return et toi tu embrayes sur les expressions.
    Oui, j'embraye là-dessus (return expression;) parce qu’il peut arriver que l'on rencontre une instruction écrite de cette façon return (3*x +1)/2; et les parenthèses dans ou autour de l'expression "(3*x +1)/2;" sont d'abord évaluées par return uniquement dans le cadre/contexte de l'expression "(3*x +1)/2;" dont a l'issue; le résultat de l'évaluation sera renvoyé par return. Donc, selon la façon dont est écrit l'expression, des parenthèses peuvent être nécessaires et justifiées.
    Celui qui peut, agit. Celui qui ne peut pas, enseigne.
    Il y a deux sortes de savants: les spécialistes, qui connaissent tout sur rien,
    et les philosophes, qui ne connaissent rien sur tout.
    George Bernard Shaw

  15. #15
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 7 462
    Points : 21 257
    Points
    21 257
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par sambia39 Voir le message
    et les parenthèses dans ou autour de l'expression "(3*x +1)/2;" sont d'abord évaluées par return
    Non elles ne sont pas évaluées par return. Elles sont évaluées par le module mathématique chargé d'effectuer les opérations. Ensuite le résultat est récupéré dans le contexte de l'instruction et utilisé par return. Mais dans une autre situation, (ex int a=(3*x +1)/2;) les parenthèses seront évaluées par le même module et le résultat sera récupéré cette fois dans cet autre contexte et stocké dans "a".

    Citation Envoyé par sambia39 Voir le message
    Donc, selon la façon dont est écrit l'expression, des parenthèses peuvent être nécessaires et justifiées.
    Punaise, t'es vraiment le fils de casse couilles toi. Elles sont peut-être justifiées mais pas par return. Elles sont justifiées par la volonté du développeur d'obtenir un calcul où les opérations se feront dans un ordre précis.
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  16. #16
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 263
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 263
    Points : 27 916
    Points
    27 916
    Par défaut
    Citation Envoyé par foetus Voir le message
    Tu prends les opérateurs += -= *= /=.
    Sont-ils plus compact ? Oui Et donc pour toi ils sont moins expressif
    Et je te l'accorde - le code sans ces opérateurs est plus lourd si on parenthèse.
    Et même sans les parenthèses : a += b;(sucre syntaxique) aura le même effet que a = a + b;(expression exacte de ce que l'on veut faire).

    Mais le sucre syntaxique utilisera, en comptant les espaces que j'ai volontairement placé, six bytes dans le fichier de code (setp, si on compte le retour à la ligne qui n'apparaît pas), contre 10 (onze, si on compte le retour à la ligne qui n'apparait pas non plus) pour l'expression exacte de ce que l'on veut faire.

    Il n'y a donc rien à faire : l'écriture d'un code expressif va souvent de paire avec une augmentation du nombre de caractères nécessaires à sa représentation, ce qui produit des fichiers "plus lourds" (ne serait-ce qu'en terme de nombre de byte à placer sur le support lors de l'enregistrement)

    Tu feras sans doute valoir qu'un cluster de disque dur permet, classiquement, de représenter 512 bytes successifs, et je te l'accorde sans problème. Mais ajoute suffisamment souvent quatre caractères à la représentation d'une expression, et ton fichier finira tôt ou tard par nécessiter un cluster de plus lors de l'enregistrement

    La question est donc de savoir si cela pose un problème d'avoir recours à des expressions qui nécessitent un nombre plus important de caractères si c'est pour gagner en expressivité, au point que même un type à moitié endormi ne pourrait faire autrement que de comprendre l'objectif poursuivi par cette expression.

    A l'heure actuelle, j'estime que "quelques caractères" de plus (fussent-ils vraiment nombreux) ne présentent aucun danger, que le système n'a aucun risque de se trouver "à court d'espace de stockage" à cause de ces quelques caractères de plus.

    Soyons cependant bien clairs sur le fait que je ne milite aucunement pour l'abandon de tous les sucres syntaxiques. Les opérateurs mahtématiques d'assignement (+= et ceux adaptés aux autre opérations) ne m'ont jamais posé le moindre problème, et je n'ai absolument aucune raison de leur préférer la forme "fully expresive" des expressions
    Une boucle for est pour moi une boucle pour parcourir une collection.
    Excactement, ou pour effectuer le contenu de la boucle un nombre bien spécifique de fois
    Après si dans ton code tu colles des for(;;) infini, je n'y peux rien.
    Hé bien, pour moi, c'est une hérésie; parce qu'une boucle ne sera jamais infinie par nature (il y aura toujours bien un moment où il faudra la quitter pour une raison ou une autre), et parce que ce genre de boucle va régulièrement se dégrader sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    for(;;){
       /* du code */
       if(condition){
          /* peut-etre du code */
          break;
       }
       /* peut être encore du code
    }
    Or, s'il y a une condition pour sortir de la boucle, c'est bien qu'il ne s'agit pas d'une boucle infinie. Dés lors, pourquoi ne pas utiliser le style de boucle qui présente la condition de sortie pour ce qu'elle est
    Mais la différence entre une boucle for et while c'est zéro.
    C'est exactement ce que j'ai dit, me semble-t-il, non

    Cependant, une boucle while (ou do... while) sera amplement plus expressive, car la condition de sortie (pardon : la condition pour entrer "une fois de plus" dans la boucle) se trouve exactement à l'endroit où l'on s'attend à la trouver
    • zéro en compréhension. C'est une boucle, il faut lire le code pour comprendre ce qu'on va répéter.
    Pour savoir ce qu'on va répéter, on n'a effectivement pas d'autre choix que de lire le code de la boucle.

    Mais tu oublie un aspect important du principe même de boucle : le nombre de fois que l'on va répéter la chose (ou la condition qui permet à la chose de se répéter). Les différents styles de boucles sont, justement, prévus pour te permettre de déterminer SI on va répéter ou non, indépendamment de ce qui sera répété
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  17. #17
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 7 462
    Points : 21 257
    Points
    21 257
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Et même sans les parenthèses : a += b;(sucre syntaxique) aura le même effet que a = a + b;(expression exacte de ce que l'on veut faire). Mais le sucre syntaxique utilisera, en comptant les espaces que j'ai volontairement placé, six bytes dans le fichier de code (sept, si on compte le retour à la ligne qui n'apparaît pas), contre 10 (onze, si on compte le retour à la ligne qui n'apparait pas non plus) pour l'expression exacte de ce que l'on veut faire.
    9, pas 10 (ou alors tu comptes le point-virgule qu'il aurait alors aussi fallu compter dans a += b;...)

    Citation Envoyé par koala01 Voir le message
    Il n'y a donc rien à faire : l'écriture d'un code expressif va souvent de paire avec une augmentation du nombre de caractères nécessaires à sa représentation, ce qui produit des fichiers "plus lourds" (ne serait-ce qu'en terme de nombre de byte à placer sur le support lors de l'enregistrement)
    Pour moi l'expressivité du code se fait par les commentaires. Je ne sais pas si je suis lisible (je suis seul à me relire) mais je n'écris jamais un bloc sans mettre au début le but de ce bloc ce qu'il va faire et comment il va le faire.
    Mais sinon es-tu en train de dire qu'écrire i=i+n produira un code plus lourd qu'écrire i+=n ?

    Citation Envoyé par koala01 Voir le message
    Hé bien, pour moi, c'est une hérésie; parce qu'une boucle ne sera jamais infinie par nature (il y aura toujours bien un moment où il faudra la quitter
    Je n'irai pas donner un terme aussi fort que "hérésie". Je préfère parler de "simplification d'expression". C'est plus facile de dire "je pars sur une boucle infinie" que "je pars sur une boucle qui ne s'arrêtera que si telle situation exceptionnelle survient".
    Par ailleurs il y a quand-même parfois de vraies boucles infinies. Les serveurs (ex apache, ftp) démarrent avec la machine et s'arrêtent avec elle.

    Citation Envoyé par koala01 Voir le message
    Dés lors, pourquoi ne pas utiliser le style de boucle qui présente la condition de sortie pour ce qu'elle est
    Parce que parfois ce n'est pas possible. Par exemple pour une saisie d'int, je préfère de loin écrire ceci
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char tampon[256];
    int n;
    while (1) {
    	printf("Entrez un entier\n");
    	fgets(tampon, 256, stdin);
    	if (sscanf(tampon, "%d", &n) == 1) break;
    	printf("Vous n'avez pas saisi un entier => try again !!!\n")
    }
    que de partir dans une tournure bien alambiquée juste pour ne pas écrire while (1)...
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  18. #18
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 263
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 263
    Points : 27 916
    Points
    27 916
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    9, pas 10 (ou alors tu comptes le point-virgule qu'il aurait alors aussi fallu compter dans a += b;...)
    Ou, plus vraisemblablement, j'étais sans doute un peu fatigué quand j'ai écrit mon message... Mais, quoi qu'il en soit, il y a bel et bien une différence dans le nombre de caractères nécessaire à sa représentation


    Pour moi l'expressivité du code se fait par les commentaires.
    De mon point de vue, surtout pas.

    J'admets les commentaires à but pédagogiques ainsi que les "cartouches" de structures et / ou de fonctions. Mais je me batterai "jusqu'à la mort" contre les commentaires qui ne font que paraphraser le code

    De mon point de vue, si tu estimes que ton code nécessite un commentaire, c'est que tu as foiré "quelque chose" au moment de l'écriture du code
    Je ne sais pas si je suis lisible (je suis seul à me relire) mais je n'écris jamais un bloc sans mettre au début le but de ce bloc ce qu'il va faire et comment il va le faire.
    Et combien de fois t'est-il arrivé de modifier le bloc en question, en modifiant -- le cas échéant de manière fondamentale -- la manière dont les choses sont faites, sans modifier le code qui va avec

    Le lecteur est un fainéant par principe : si tu lui donne l'occasion, au travers d'un commentaire, de croire avoir une parfaite compréhension de se que fait le code en se contentant de lire un commentaire, il se contentera de lire le commentaire, en laissant le code "de coté".

    Si, pour une raison ou une autre, ton commentaire est "désynchronisé" par rapport à ton code, le lecteur ne comprendra plus rien à ce qui se passe lorsqu'il devra commencer à débuger ton code, parce qu'il partira du principe que le commentaire disait la vérité.

    Or, les raisons de modifier le code "après coup" sont légions, et on ne pense pas forcément à adapter les commentaires qui vont avec.
    Mais sinon es-tu en train de dire qu'écrire i=i+n produira un code plus lourd qu'écrire i+=n ?
    Je ne m'intéresse pas forcément à l'écriture du code, mais bien résultat sur le support d'enregistrement.

    Pour donner un exemple tout bête, imagine le résultat si ton code devait être enregistré sur les bonnes vieilles carte perforées de l'époque. Trois caractères ferait décaler tout le reste de près d'une demi colonne!
    Je n'irai pas donner un terme aussi fort que "hérésie". Je préfère parler de "simplification d'expression". C'est plus facile de dire "je pars sur une boucle infinie" que "je pars sur une boucle qui ne s'arrêtera que si telle situation exceptionnelle survient".
    La situation n'a rien d'exceptionnel! Je t'accorde la rareté de la situation, mais pas son aspect exceptionnel
    Par ailleurs il y a quand-même parfois de vraies boucles infinies. Les serveurs (ex apache, ftp) démarrent avec la machine et s'arrêtent avec elle.
    Mais ils finissent donc bien par s'arrêter à un moment ou un autre

    Et, pire encore : de par la rareté de leur arrêt, il y a tout intérêt à veiller à ce que cet arrêt se fasse correctement, pour éviter qu'il y ait une perte de donnée quelconque, qui soit émise mais non reçue juste avant l'extinction
    Parce que parfois ce n'est pas possible. Par exemple pour une saisie d'int, je préfère de loin écrire ceci
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char tampon[256];
    int n;
    while (1) {
    	printf("Entrez un entier\n");
    	fgets(tampon, 256, stdin);
    	if (sscanf(tampon, "%d", &n) == 1) break;
    	printf("Vous n'avez pas saisi un entier => try again !!!\n")
    }
    que de partir dans une tournure bien alambiquée juste pour ne pas écrire while (1)...
    Et quoi tu trouve que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    do{
        printf("Entrez un entier\"n);
        fgets(tampon, 256, stdin);
        accepted = sscanf(tampon, "%d", &n);
        if(accepted != 1)
            printf("Vous n'avez pas saisi un entier =>try again !!!\n);
    }while(accepted == 1);
    est plus alambiqué

    Encore une fois, je t'accorde sans problème qu'il faudra beaucoup plus de caractères pour représenter la logique. Et je reconnais aussi que cela implique l'utilisation d'une variable supplémentaire.

    En échange, le code exprime exactement la volonté du développeur, et même un lecture à moitié endormi n'aura pas la moindre excuse pour ne pas l'avoir comprise .

    Je dois cependant t'avouer que je suis contre les goto et l'utilisation du break si ce n'est pas dans le cadre d'un test à choix multiple (switch... case), ce qui influe sans doute bien plus sur ma manière de penser que je n'en ai moi-même conscience
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  19. #19
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    7 462
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : février 2006
    Messages : 7 462
    Points : 21 257
    Points
    21 257
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ou, plus vraisemblablement, j'étais sans doute un peu fatigué quand j'ai écrit mon message...
    Ben tu l'as écrii à 22h25. Et celui-ci à 04h18. Donc là tu dois être sur les genoux non ???


    Citation Envoyé par koala01 Voir le message
    J'admets les commentaires à but pédagogiques ainsi que les "cartouches" de structures et / ou de fonctions. Mais je me batterai "jusqu'à la mort" contre les commentaires qui ne font que paraphraser le code
    De mon point de vue, si tu estimes que ton code nécessite un commentaire, c'est que tu as foiré "quelque chose" au moment de l'écriture du code
    Pas d'accord. Je n'écris pas "je vais faire une boucle dans laquelle je mémoriserai tout élément plus petit que celui déjà mémorisé" mais plutôt un truc comme "Recherche du minimum des valeurs stockées en bdd"

    Citation Envoyé par koala01 Voir le message
    Et combien de fois t'est-il arrivé de modifier le bloc en question, en modifiant -- le cas échéant de manière fondamentale -- la manière dont les choses sont faites, sans modifier le code qui va avec
    Jamais puisque je ne détaille juste ce que je veux, pas comment je le récupère.

    Citation Envoyé par koala01 Voir le message
    Le lecteur est un fainéant par principe : si tu lui donne l'occasion, au travers d'un commentaire, de croire avoir une parfaite compréhension de se que fait le code en se contentant de lire un commentaire, il se contentera de lire le commentaire, en laissant le code "de coté".
    Pas moi. Je suis en train d'étudier le logiciel WAZUH, je te promets que je lis tout ce que je peux glâner dessus...

    Citation Envoyé par koala01 Voir le message
    Mais ils finissent donc bien par s'arrêter à un moment ou un autre
    Ah non, çà c'est de la mauvaise foi !!! L'arrêt ne survient pas par une volonté du développeur mais parce que le programme n'a plus de support pour fonctionner. C'est comme si je disais que l'énergie solaire est infinie et que tu répondais "ben non, il s'éteindra dans 4 milliards d'années". Tu ne peux raisonnablement pas étayer une discussion intéressante avec des arguments aussi terre à terre...

    Citation Envoyé par koala01 Voir le message
    Et, pire encore : de par la rareté de leur arrêt, il y a tout intérêt à veiller à ce que cet arrêt se fasse correctement, pour éviter qu'il y ait une perte de donnée quelconque, qui soit émise mais non reçue juste avant l'extinction
    Là je suis d'accord. Généralement on trappe le signal 15 et d'autres que je n'ai pas en tête pour arrêter le bouzin (et on trappe aussi le 1 pour qu'il recharge ses paramètres => cas du cron)

    Citation Envoyé par koala01 Voir le message
    Et quoi tu trouve que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    do{
        printf("Entrez un entier\"n);
        fgets(tampon, 256, stdin);
        accepted = sscanf(tampon, "%d", &n);
        if(accepted != 1)
            printf("Vous n'avez pas saisi un entier =>try again !!!\n);
    }while(accepted == 1);
    est plus alambiqué
    Oui c'est vrai. J'ai essayé de trouver un cas de while (1) inéluctable et j'ai foiré. Je suis en train de grepper tous mes sources pour trouver là où j'écris while (1) (ou while True en Python) pour voir si je peux en trouver un autre ...
    ... et j'ai trouvé. En dehors de certains TP de serveurs qui, fatalement, doivent utiliser la boucle infinie, que penses-tu de cette portion de code (un petit TP sur une création d'un dictionnaire français/anglais avec en plus définition du mot). Je suis parti sur une liste chainée où chaque mot français aurait sa traduction en anglais plus un pointeur sur les autres mots français de la définition (mots ayant donc eux aussi la traduction en anglais plus un pointeur sur d'autres mots etc etc etc) et bien évidemment (liste chainée oblige) un pointeur sur un autre mot du dico.
    Ainsi "niche" défini comme "maison du chien" et traduit par "doghouse" aurait sa définition en anglais comme "house of the dog" (en admettant que "maison", "du" et "chien" soient eux aussi dans la liste)

    Bref j'ai écrit ma saisie du mot français et anglais ainsi
    Code c : 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
    void mot_nouveau(t_liste* const l) {
    	char fr[CAR_MAX + 1];
    	char en[CAR_MAX + 1];
     
    	while (1) {
    		// Saisie du mot français
    		mot_saisie(fr, "Entrez votre mot français (rien pour quitter) :");
     
    		// Si quitter
    		if (fr[0] == '\0')
    			break;
     
    		// Si le mot français existe déjà
    		if (mot_exist(fr, l) != NULL) {
    			printf("Le mot français [%s] existe déjà\n", fr);
    			continue;
    		}
     
    		// Saisie du mot anglais
    		mot_saisie(en, "Entrez votre mot anglais (rien pour annuler) :");
     
    		// Si annuler
     		if (en[0] == '\0')
    			continue;
     
    		// Insertion du mot
    		if (mot_insert(fr, en, l, NULL) == NULL)
    			fprintf(stderr, "Erreur insertion [%s][%s] - %s\n", fr, en, strerror(errno));
    		else
    			printf("Insertion %s/%s ok\n", fr, en);
    	}
    }
    et là je suis curieux de voir comment faire sans les break et continue

    Citation Envoyé par koala01 Voir le message
    Je dois cependant t'avouer que je suis contre les goto et l'utilisation du break si ce n'est pas dans le cadre d'un test à choix multiple (switch... case), ce qui influe sans doute bien plus sur ma manière de penser que je n'en ai moi-même conscience
    Argh tristesse Tu semblais pourtant si ouvert d'esprit...
    Je t'invite à aller lire ce post où je conseille du "goto"... (c'est dans le code source posté)

    Pour moi les outils existent donc on peut s'en servir. Mais comme tout, on peut s'en servir bien ou mal

    Super sympa
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site

  20. #20
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 263
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 263
    Points : 27 916
    Points
    27 916
    Par défaut
    Citation Envoyé par Sve@r Voir le message
    Je n'écris pas "je vais faire une boucle dans laquelle je mémoriserai tout élément plus petit que celui déjà mémorisé" mais plutôt un truc comme "Recherche du minimum des valeurs stockées en bdd"
    Et que penses tu d'appliquer, tout simplement, le SRP, histoire de pouvoir mettre des cartouches sur tes fonctions

    Si tu pars de rien, tu crées
    • une fonction de sélection des enregistrement selon le critère choisi
    • une fonction pour le tri des enregistrement
    • une fonction de recherche des valeurs minimum

    Je t'ai dit, je n'ai rien contre les cartouches, qui permettront au développeur de connaitre le but poursuivi par une fonction. Mais, à l'intérieur même de la fonction, il n'y a aucune raison d'ajouter un commentaire si tu respecte quelques règles simples
    Jamais puisque je ne détaille juste ce que je veux, pas comment je le récupère.
    c'est donc bien le role du cartouche d'une fonction, contre lequel je n'ai absolument rien

    Mais si tu en viens à décrire ce que tu veux au milieu de ta fonction, c'est que tu a foiré quelque part, parce que la partie que tu commente de la sorte aurait sans doute largement justifié de se retrouver dans une fonction "séparée".
    Ah non, çà c'est de la mauvaise foi !!! L'arrêt ne survient pas par une volonté du développeur mais parce que le programme n'a plus de support pour fonctionner.
    Ou de la propre volonté de l'utilisateur, ne serait-ce que pour des raisons de maintenance...

    Mais si tu ne laisses pas d'autre choix à l'utilisateur que de tuer violemment le processus pour pouvoir lancer sa maintenance, tu cours toujours le risque qu'il décide de le faire à un moment inopportun, avec le risque de perte de données ou d'incohérences que cela entraine.

    A moins bien sur que tu ne décide d'intercepter ce signal destiné à tuer ton processus, histoire de lancer une procédure bien spécifique lorsque le signal en question est lancé.

    Mais, à ce moment là, tu as une condition parfaite utilisable pour ta boucle qui est -- en principe -- destinée à se répéter longtemps : tant que je n'ai pas intercepté le signal de fin du programme
    C'est comme si je disais que l'énergie solaire est infinie et que tu répondais "ben non, il s'éteindra dans 4 milliards d'années". Tu ne peux raisonnablement pas étayer une discussion intéressante avec des arguments aussi terre à terre...
    Si ce n'est qu'il n'y a rien de comparable entre un processus qui n'arrivera qu'une fois dans quatre milliard d'années avec des effets irréversible, et un processus que l'on sait par avance qu'il se reproduira de manière (plus ou moins) régulière tous les quelque

    Là je suis d'accord. Généralement on trappe le signal 15 et d'autres que je n'ai pas en tête pour arrêter le bouzin (et on trappe aussi le 1 pour qu'il recharge ses paramètres => cas du cron)
    Bref j'ai écrit ma saisie du mot français et anglais ainsi
    Code c : 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
    void mot_nouveau(t_liste* const l) {
    	char fr[CAR_MAX + 1];
    	char en[CAR_MAX + 1];
     
    	while (1) {
    		// Saisie du mot français
    		mot_saisie(fr, "Entrez votre mot français (rien pour quitter) :");
     
    		// Si quitter
    		if (fr[0] == '\0')
    			break;
     
    		// Si le mot français existe déjà
    		if (mot_exist(fr, l) != NULL) {
    			printf("Le mot français [%s] existe déjà\n", fr);
    			continue;
    		}
     
    		// Saisie du mot anglais
    		mot_saisie(en, "Entrez votre mot anglais (rien pour annuler) :");
     
    		// Si annuler
     		if (en[0] == '\0')
    			continue;
     
    		// Insertion du mot
    		if (mot_insert(fr, en, l, NULL) == NULL)
    			fprintf(stderr, "Erreur insertion [%s][%s] - %s\n", fr, en, strerror(errno));
    		else
    			printf("Insertion %s/%s ok\n", fr, en);
    	}
    }
    et là je suis curieux de voir comment faire sans les break et continue
    S'il n'y a que cela pour te faire plaisir ...
    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
     
    void mot_nouveau(t_list * const l){
        char fr[CAR_MAX + 1];
        char en[CAR_MAX + 1];
        int again = 1;
        while(again){
            mot_saisie(fr, "Entrez votre mot français (rien pour quitter) :");
            if(fr[0]=='\0')
                again = 0;
            else if (mot_exist(fr, l) != NULL) {
                printf("Le mot français [%s] existe déjà\n", fr);
                again = 0;
            }
            if(again){
                mot_saisie(en, "Entrez votre mot anglais (rien pour annuler) :");
                if (en[0] == '\0'){
                    printf("Aucune traduction, annullation de l'insertion\n");
                    again = 0;
                }
            }
            if(again && mot_insert(fr, en, l, NULL) == NULL){
                fprintf(stderr, "Erreur insertion [%s][%s] - %s\n", fr, en, strerror(errno));
                again = 0;
            } else
                printf("Insertion %s/%s ok\n", fr, en);
        }
    }
    Ah oui, le code est plus long, et je t'avouerai que je me suis limité à vérifier qu'il compile sans problème...

    Mais, a priori, je n'ai fait aucune erreur de logique, si bien que tu devrais pouvoir l'utiliser tel quel en remplacement du tien . Et tu remarquera qu'il n'y a ni goto, ni continue, ni break dans cette boucle

    Si tu as une série de tests qui peuvent confirmer le bon fonctionnement de ton programme, je te proposerais bien de les faire tourner pour t'assurer de l'innocuité des modifications apportées
    Argh tristesse Tu semblais pourtant si ouvert d'esprit...
    Je crois pourtant être ouvert d'esprit, tu sais...


    Maintenant, cela vient peut être du fait que j'ai eu un prof d'algo qui nous a présenté le flowchart que le temps de nous montrer le plat de spagetti que cela devient dés qu'il y a deux boucles imbriquées, puis qui nous a incité à utiliser le nassi-shneiderman (en nous menaçant de nous jeter par la fenêtre si on utilisait goto)

    Mais le fait est que rien dans mon expérience ne m'a jamais laissé face à la nécessité absolue d'avoir recours à un goto, ou à un break|continue pour sortir d'une boucle
    Pour moi les outils existent donc on peut s'en servir. Mais comme tout, on peut s'en servir bien ou mal
    Et je suis tout à fait d'accord avec toi sur ce point!

    Le problème, c'est que la principale raison de mauvaise utilisation d'un outil est sans doute le fait de vouloir l'utiliser pour un travail pour lequel il n'est pas prévu.

    Or, de mon point de vue, goto (ou plutôt, son équivalent en assembleur, par exemple) est un "reliquat" des pratiques imposées par les langages de deuxième génération.

    Je me doute bien que Richie et Thompson avaient d'excellentes raisons d'ajouter ces mots (je parle de goto et de continue ici) clé au langage, mais si je devais réécrire C depuis 0 cinquante ans après eux (si tant est que j'en ai les capacité, ce qui reste à démonter ), je garderais break pour le cas bien spécifique du switch ... case, en essayant autant que faire se peu de limiter son utilisation à ce seul cas, et je virerais purement et simplement les mots clés goto et continue du langage
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. [Flex4] erreur non localisée
    Par execrable dans le forum Flex
    Réponses: 1
    Dernier message: 27/04/2011, 11h46
  2. FOP + erreurs non localisées
    Par yozine dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 07/09/2009, 11h05
  3. Erreur de segmentation non trouvée
    Par Bladelight dans le forum OpenCV
    Réponses: 6
    Dernier message: 31/08/2009, 13h40
  4. erreurs de segmentation non détectée
    Par Benoit_T dans le forum Langage
    Réponses: 5
    Dernier message: 21/07/2009, 14h47
  5. Erreur non localisée
    Par nezdeboeuf62 dans le forum Eclipse Java
    Réponses: 1
    Dernier message: 24/01/2008, 22h13

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