Contenu | Rechercher | Menus

Annonce

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

À propos de l'équipe du forum.

#1 Le 30/05/2019, à 19:27

chris7522

[RESOLU] La derniere fonction ne fonctionne pas (C)

Bonjour a toutes et a tous ,
Dans ma derniere fonction , j'essaie de classer mes nombres en ordre croissant , je n'ai pas de messages d'erreur  mais , elle ne fonctionne pas . Je crois que c'est du grand n'importe quoi ...

   

#include <stdio.h>
  #define TAILLE 5

  void afficherTablo(int tablo[]);
  void incremTablo(int tablo[]);
  void classement(int tablo[]);

  int main()
  {
     int n[]={98,2,35,65,16};
     int x;
     
     puts("Votre tableau avant transformation : ");
       afficherTablo(n);
       incremTablo(n);
     puts("Votre tableau apres fonction incremTablo : ");
       afficherTablo(n);
       classement(n);
     puts("Votre tableau apres classement : ");
       afficherTablo(n);
     for(x=0; x<TAILLE; x++)
       printf("%d\n",n[x]);
     
     
     return 0;
  }
  void incremTablo(int tablo[])
  {
     int x;
 
     for(x=0; x<TAILLE;x++)
     tablo[x]++;
  }

  void afficherTablo(int tablo[])
  {
     int x;

     for(x=0; x<TAILLE; x++)
        printf("%d\t",tablo[x]);
     putchar('\n');
  }
  void classement(int tablo[]) 
  {
      int interne,externe,temp;
    
      for(interne=0; interne<TAILLE-1; interne++)
      {
        for(externe=interne+1; externe<TAILLE; externe++)
        {
          if(tablo[interne]>tablo[externe])
          {
            temp=tablo[interne];
            tablo[interne]=tablo[externe];
            tablo[externe]=temp;
          }
       }
    }
  }

        

Merci de votre aide

Dernière modification par chris7522 (Le 19/06/2019, à 22:54)

Hors ligne

#2 Le 30/05/2019, à 19:37

nam1962

Re : [RESOLU] La derniere fonction ne fonctionne pas (C)

Un titre plus explicite et le langage utilisé (C++ ? je n'y connais rien...) contribueront sûrement à trouver de l'aide (et aider les futurs lecteurs du fil)


[ Modéré ]

Hors ligne

#3 Le 30/05/2019, à 19:39

Nuliel

Re : [RESOLU] La derniere fonction ne fonctionne pas (C)

Je viens de compiler ton programme, cela retourne

Votre tableau avant transformation : 
98	2	35	65	16	
Votre tableau apres fonction incremTablo : 
99	3	36	66	17	
Votre tableau apres classement : 
3	17	36	66	99	
3
17
36
66
99

mais c'est trié. Quel est le problème?

Hors ligne

#4 Le 30/05/2019, à 19:54

chris7522

Re : [RESOLU] La derniere fonction ne fonctionne pas (C)

Oh la la , je suis fatigué moi ! Desolé hmm

Hors ligne

#5 Le 30/05/2019, à 19:58

Nuliel

Re : [RESOLU] La derniere fonction ne fonctionne pas (C)

Pas de problème.
Juste une petite chose, j'imagine que tu l'as compris mais au cas où je le précise: les tableaux statiques passés en argument de fonction sont toujours passés avec référence, ce qui n'est pas le cas avec d'autres types d'arguments.

@nam: #include <stdio.h> ça indique plutôt du C

Dernière modification par Nuliel (Le 30/05/2019, à 20:06)

Hors ligne

#6 Le 30/05/2019, à 21:13

chris7522

Re : [RESOLU] La derniere fonction ne fonctionne pas (C)

Je n'ai pas compris . passés avec référence ? Que veux tu dire par la ? pardonne mon ignorance mais , je suis débutant .

Hors ligne

#7 Le 30/05/2019, à 21:25

Nuliel

Re : [RESOLU] La derniere fonction ne fonctionne pas (C)

Une fonction prend des arguments et renvoie quelque chose (sauf quand ça commence par void)
Ces arguments peuvent être de plusieurs types: entier, caractère, chaîne de caractères, pointeur, .... et notamment un tableau statique (les tableaux que tu utilises)
Ces arguments, tu peux les passer de trois manières:
- de manière normale: une modification de l'argument dans la fonction ne le modifie pas à l'extérieur de la fonction (une variable locale en fait)
- par référence: on utilise l'esperluette & et une modification de l'argument dans la fonction le modifie aussi à l'extérieur de la fonction (variable globale?)
- par un pointeur: c'est l'adresse où se trouve les données si je dis pas de bêtises, et *pointeur permet d'accéder au contenu

La particularité de passer un tableau statique en argument d'une fonction, c'est que le tableau est forcément passé par référence. En d'autres termes, si tu modifies le tableau, il est aussi modifié à l'extérieur de la fonction

Dernière modification par Nuliel (Le 30/05/2019, à 21:27)

Hors ligne

#8 Le 30/05/2019, à 21:37

chris7522

Re : [RESOLU] La derniere fonction ne fonctionne pas (C)

Ok bien compris . Merci pour ces explications .
  Bonne soirée

Hors ligne

#9 Le 04/06/2019, à 22:58

Zakhar

Re : [RESOLU] La derniere fonction ne fonctionne pas (C)

Naziel a écrit :

Une fonction prend des arguments et renvoie quelque chose (sauf quand ça commence par void)
Ces arguments peuvent être de plusieurs types: entier, caractère, chaîne de caractères, pointeur, .... et notamment un tableau statique (les tableaux que tu utilises)
Ces arguments, tu peux les passer de trois manières:
- de manière normale: une modification de l'argument dans la fonction ne le modifie pas à l'extérieur de la fonction (une variable locale en fait)
- par référence: on utilise l'esperluette & et une modification de l'argument dans la fonction le modifie aussi à l'extérieur de la fonction (variable globale?)
- par un pointeur: c'est l'adresse où se trouve les données si je dis pas de bêtises, et *pointeur permet d'accéder au contenu

La particularité de passer un tableau statique en argument d'une fonction, c'est que le tableau est forcément passé par référence. En d'autres termes, si tu modifies le tableau, il est aussi modifié à l'extérieur de la fonction

Tu compliques ;-)

En C classique Kernigan & Ritchie, on ne passe que des variables de type simple, jamais de tableaux ou structure.

C'est à dire qu'on peut passer : char, int (et ses variantes), float (et variantes) et pointeur.

Bien sûr passer un pointeur permet alors de faire plein de choses depuis la fonction sur le chose vers laquelle on pointe (d'où la notion de "référence", parce que le pointeur "se réfère" à l'objet pointé).

Et après, quand on commence à passer des pointeurs de pointeurs... les nœuds au cerveau arrivent ! lol mad

On ne pouvait pas, dans la version initiale, passer autre chose... et c'est une bonne pratique d'en rester là.

Pourquoi ?

Il faut imaginer ce qu'il se passe quand on appelle une fonction, regardez le code assembleur et vous comprendrez...

Si j'ai par exemple une fonction sum(long, long), qui prend deux long et les ajoute, lorsque j'appelle

sum( a, b)

Il va se passer :
push b
push a
call sum

La fonction sum va ensuite travailler sur les arguments qui ont été "pushés" et sont donc des zones mémoires différentes de l'endroit où a et b sont stockés. D'où variables indépendantes.


Et depuis quelques versions, il a été introduit la possibilité de passer des arrays ou structures... mais ça c'est complètement horrible d'un point de vue performance, puisque ça reste des "copies" si on ne travaille pas proprement avec des pointeurs.
Donc si j'ai par exemple maintenant la fonction sum( long[5000])

L'appel de
sum( a[5000])

va faire
sub sp, 40000
<memcpy sp, a>
call sum

... et au lieu de simplement "pousser" 2 variables dans la pile, on se retrouve à copier 40k de données dans la pile juste pour les additionner... alors qu'on ferait le même travail en poussant un pointeur sur des long constant (pour éviter leur modification accidentelle par le code de la fonction).


Bref, c'est tout sauf une bonne idée d'utiliser le passage de tableaux/structures !..


Bien sûr les explications là sont simplifiées. Dans les niveaux d'optimisation plus élevés, les compilateurs peuvent même optimiser au delà du "push" en gardant simplement les variables passées dans des registres... mais pas pour un tableau de 5000 !..


Donc bonne pratique : ne passez jamais autre chose que des variables "simples" !..

Et une petite astuce sympathique pour éviter les "magic numbers" (5 dans ton cas)

  int main()
  {
     int n[]={98,2,35,65,16};

  #define TAILLE (sizeof(n) / sizeof(n[0]))

Ainsi tu peux modifier comme tu veux ton tableau, la "TAILLE" suivra toute seule. Idem si tu modifies le type et choisis des long ou des float, ou même de structures.

Et si l'objet était de développer une fonction de tri, c'est très bien. Sinon il en existe des plus efficaces (qui ne font pas du N carré !) dans la bibliothèque standard, comme qsort.

Et donc une version plus "propre" de tes fonctions :

void incTab(int *tab, size_t nmemb)
  {
     int i;
 
     for(i=0; i<nmemb; i++)
         tab[i]++;
  }

incTab(n, TAILLE);

Et la fonction s'appelle avec le tableau (qui est en fait un pointeur constant), et le nombre d'éléments (ton define). La fonction est ainsi "générique" car elle ne dépend pas d'une constante externe, mais uniquement des valeurs que tu lui passes (pas "d'effet de bord").

Aussi tu vois, qu'à l'opposé de l'array qui est un pointeur constant, tu peux également utiliser un pointeur comme si c'était une array pour les affectation, tel que je l'ai fait dans l'exemple de la fonction re-architecturée. La logique d'addition de pointeur va alors se mettre en place.

Alternativement à l'écriture

tab[i]++;

tu peux utiliser le moins lisible

*(tab + i)++;

Ou alors faire

     for(i=0; i<nmemb; i++, tab++)
         *tab++;

En version "optimisée" tout cela produira à la fin le même code, donc à choisir le plus lisible (sans doute la version "tableau")

Enfin, la version plus complète (on y pense rarement !)...

#include <errno.h>
#include <limits.h>

int incTab(int *tab, size_t nmemb)
  {
     int i;
 
     for(i=0; i<nmemb; i++) {
         if (INT_MAX == tab[i])
              return EOVERFLOW;
         tab[i]++;
     }
     return 0;
  }

En l'occurrence, il est possible que ta fonction provoque un "overflow" : si les entiers contenus dans le tableau sont déjà INT_MAX, les incrémenter produit un résultat "indéterminé". Ce qui veut dire qu'à partir du moment où cela se produit, le compilateur est en droit de produire n'importe quel code!
A l'idéal il faut donc que la fonction s'arrête et retourne une erreur dans ce cas, ce que fait cette version "sophistiquée".

Bien sûr l'appelant doit aussi tester l'erreur, et réagir en conséquence : message, arrêt, etc...

Dernière modification par Zakhar (Le 04/06/2019, à 23:44)


"A computer is like air conditioning: it becomes useless when you open windows." (Linus Torvald)

Hors ligne