Tri d'un tableau

Bonjour,
Voila je dois faire un programme sous Geany (avec les contraintes de mon école) . Il faut écrire une fonction indiceInsert qui étant donné un tableau de flottant "tab" de taille "taille" contenant "nbE1" éléments triés par ordre croissant et un flottant f , retourne l'indice auquel f doit être inséré pour que le tableau reste trié . Si le tableau est plein ou si l'élément est déja présent , la fonction retourne la valeur -1 .

Voila le programme que je propose avec un test dans la fonction main :
#include <cini.h>

int indiceInsert (float tab[] , int taille , float f) {
int i=0, nbe1 ;
nbe1=taille ;
while (tab[i]<f && i<taille) {
i = i++ ;
}
nbe1 = nbe1++ ;
if(tab[i] == f && nbe1>taille) {
return (-1) ;
}
else {
return (i) ;
}
}

int main () {
int test ;
float tab1 [] = {1,2,3,4} ;
test = indiceInsert (tab1 , 5 , 5) ;
if (test==-1) {
printf ("le tableau est trop grand ou la valeur est déja contenu") ;
}
else {
printf ("l'élément ce trouve à la place : %d" , test ) ;
}
return 0 ;
}

2 problèmes :
- 2 warning du type : warning: operation on `i' may be undefined sur i et nbE1 et quand je remplace i = i++ par i=i+1 sa marche (pourquoi ? c'est un mystère ...)
-Quand sa compile bien après remplacement , le programme m'affiche la taille du tableau et pour une valeur très très grande il m'affiche 12 :O

Bref j'ai besoin de votre aide !

18 réponses

  • Votes
  • Date
  • Date décroissante
  1. Les valeurs élévées sont clasique de l'affichage de la valeur d'un pointeur ^^
    On évite de faire plusieurs return dans une fonction, ici on peut en faire qu'un avec un ternaire.

    Je vais c/c le code sur mon geany et je te dirai ou ça coince :)

    Edit: sans stdio et stdlib, tu vas avoir du mal par contre.
    Reedit : i=i++ est incohérent, soit tu met i++; soit i=i+1; ^^

    Ps: ta façon de mettre les accolades, je trouve ça deguelasse :/ Essaye de t'inspirer des normes.
    1. J'ai pas besoin de regarder le code longtemps au final, tu fais beaucoup d'erreur d'incohérences :

      Tu écris "nbe=taille; nbe=nbe+1; si nbe > taille" ... bah forcément qu'il sera plus grand ! ^^

      Tu passe en parametre taille = 5 alors que ton tableau fait 4, l'erreur viens surement de là.
      1. Après correction et vérification le programme fonctionne ;) . Merci :) , je pourrai avoir besoin de toi car l'exo n'est pas fini . Maintenant je dois écrire une fonction distincte qui insert f dans tab si l'élement n'est pas présent et si le tableau n'est pas plein !
        1. Tu vas tout au bout du tableau, tu deplace la valeur sur sa case de droite. Autant de fois que necessaire.
          1. j'ai fait ce programme et il y a encore plein d'erreur apparement , je ne maitrise pas encore les fonctions :(

            #include <cini.h>

            int indiceInsert (float tab[] , float f, int taille , int nbe1) {
            int i=0 ;
            while (tab[i]<f && i<taille) {
            i++ ;
            }
            nbe1++ ;
            if(tab[i] == f || nbe1>taille) {
            return (-1) ;
            }
            else {
            return (i) ;
            }
            }

            void inserElt {
            int indice = indiceInsert(tab1 , VALEUR , TAILLE , nbe1) , i ;
            for (i=nbe1 ; i>=indice ; i--) {
            tab[i+1]=tab[i] ;
            }
            }

            int main () {
            int taille=5 , nbe1=4 , int j ;
            float tab1[]={1,2,4,5} ; f=3.25 ;
            printf ("l'indice de la valeur insérée est %f" , indiceInsert(tab1,f,taille,nbe1)) ;
            for (j=0 ; j<taille ; j++) {
            printf ( "%f\n" , tab1[j] ) ;
            }
            return 0 ;
            }
            1. Ca peut pas marcher ^^

              Tu déclare ton tableau avec une taille de 4 (indice 0 a 3) mais tu dis "ouais euh, la taille c'est 5 au fait" bah nan, tu vas te taper un seg fault parce que tu touche à de la ram qui t'appartient pas ! :)

              Fait comme ça :
              int taille = 5 , nbe = 4 ;(si tu veux)
              et aprés
              int tableau[taille]={1,2,3,4}; // je reserve taille (5) cases mais j'en utilise 4.
              1. Contributeur
                int tableau[taille]={1,2,3,4};
                Attention à l'utilisation de VLA qui ne fonctionne qu'en C99.
                Il vaut mieux, surtout pour un exercice d'école, utiliser l'allocation dynamique classique.
                Soit : int *tableau = malloc(4*sizeof(*tableau));
              2. VLA ? ^^

                Et je pense pas que ce soit une bonne idée d'introduire l'alloc dynamique quand elle a déjà du mal a faire un tri a bulle ...
              3. Contributeur
                VLA = Variable Length Array. C'est un mécanisme apporté par C99. Mais en C89/90, on ne peut pas l'utiliser. Donc à oublier pour un exercice scolaire.

                Pour l'allocation dynamique, je suis d'accord. Mais c'est la seule façon d'allouer un tableau à l'exécution...
                Soit tu utilises int tableau[TAILLE]; avec #define TAILLE 5
                Soit tu utilises int *tableau=malloc(...);
                Pas d'alternatives...
                Ceci dit, rien n'empêche d'allouer statiquement un grand tableau et de n'en utiliser qu'une partie.
            2. Voila mon programme (corrigé , recorrigé et rerecorrigé) et pourtant de multiples erreurs persistent :

              Voila le programme :

              #include <cini.h>

              int indiceInsert (float tab[] ,int taille , float f, int nbe1) {
              int i=0 ;
              while (tab[i]<f && i<taille) {
              i++ ;
              }
              nbe1++ ;
              if(tab[i] == f || nbe1>taille) {
              return (-1) ;
              }
              else {
              return (i) ;
              }
              }

              void inserElt (indice) {
              int i ;
              for (i=nbe1 ; i>=indice ; i--) {
              tab1[i+1]=tab1[i] ;
              }
              }

              int main () {
              int j , nbe1=4 , taille = 5 ;
              float tab1[taille]={1,2,4,5} , f=3.25 ;
              indice = indiceInsert(tab1 ,taille , f , nbe1) ;
              printf ("l'indice de la valeur insérée est : %d" , indiceInsert(tab1,taille,f,nbe1)) ;
              inserElt(indice) ;
              for (j=0 ; j<taille ; j++) {
              printf ( "%f\n" , tab1[j] ) ;
              }
              return 0 ;
              }

              Voila les erreurs :

              In function `inserElt':
              error: `nbe1' undeclared (first use in this function)
              note: each undeclared identifier is reported only once for each function it appears in
              error: `tab1' undeclared (first use in this function)
              In function `main':
              error: variable-sized object may not be initialized
              warning: excess elements in array initializer
              warning: (near initialization for `tab1')
              warning: excess elements in array initializer
              warning: (near initialization for `tab1')
              warning: excess elements in array initializer
              warning: (near initialization for `tab1')
              warning: excess elements in array initializer
              warning: (near initialization for `tab1')
              error: `indice' undeclared (first use in this function)
              error: expected `)' before numeric constant
              error: too few arguments to function `indiceInsert'
              note: declared here
              1. Ta faction inserElt ne connait pas nbe1, il faut que tu le passe en parametre, de même pour tab1.
                Pareil tu fais un "indice=" alors qu'a aucun moment tu ne declare "indice".
                1. #include <cini.h>

                  int indiceInsert (float tab[] ,int taille , float f, int nbe1) {
                  int i=0 ;
                  while (tab[i]<f && i<taille) {
                  i++ ;
                  }
                  nbe1++ ;
                  if(tab[i] == f || nbe1>taille) {
                  return (-1) ;
                  }
                  else {
                  return (i) ;
                  }
                  }

                  void inserElt (int indice , int neb1 , float tab1 ) {
                  int i ;
                  for (i=nbe1 ; i>=indice ; i--) {
                  tab1[i+1]=tab1[i] ;
                  }
                  }

                  int main () {
                  int j , nbe1=4 , taille = 5 , indice ;
                  float tab1[taille]={1,2,4,5} , f=3.25 ;
                  indice = indiceInsert(tab1 ,taille , f , nbe1) ;
                  printf ("l'indice de la valeur insérée est : %d" , indiceInsert(tab1,taille,f,nbe1)) ;
                  inserElt(indice , nbe1 , tab1) ;
                  for (j=0 ; j<taille ; j++) {
                  printf ( "%f\n" , tab1[j] ) ;
                  }
                  return 0 ;
                  }

                  gcc -DFONTFILE='"/usr/share/libcini/font.ttf"' -Wall -O -o "td8 exo 3" "td8 exo 3.c" -lm -lcini (dans le dossier : /home/eleve)
                  Compilation échouée.
                  td8 exo 3.c: In function `inserElt':
                  td8 exo 3.c:20:9: error: `nbe1' undeclared (first use in this function)
                  td8 exo 3.c:20:9: note: each undeclared identifier is reported only once for each function it appears in
                  td8 exo 3.c:21:7: error: subscripted value is neither array nor pointer
                  td8 exo 3.c:21:17: error: subscripted value is neither array nor pointer
                  td8 exo 3.c: In function `main':
                  td8 exo 3.c:29:2: error: variable-sized object may not be initialized
                  td8 exo 3.c:29:2: warning: excess elements in array initializer
                  td8 exo 3.c:29:2: warning: (near initialization for `tab1')
                  td8 exo 3.c:29:2: warning: excess elements in array initializer
                  td8 exo 3.c:29:2: warning: (near initialization for `tab1')
                  td8 exo 3.c:29:2: warning: excess elements in array initializer
                  td8 exo 3.c:29:2: warning: (near initialization for `tab1')
                  td8 exo 3.c:29:2: warning: excess elements in array initializer
                  td8 exo 3.c:29:2: warning: (near initialization for `tab1')
                  td8 exo 3.c:32:2: error: incompatible type for argument 3 of `inserElt'
                  td8 exo 3.c:18:6: note: expected `float' but argument is of type `float *'

                  toujours pas ...
                  1. Met
                    int taille = 5;
                    int tab[5] plutot que int tab[taille].

                    et dans ta 2d fonction, t'as oublié les crochets sur le tableau.
                    1. #include <cini.h>

                      int indiceInsert (float tab[] ,int taille , float f, int nbe1) {
                      int i=0 ;
                      while (tab[i]<f && i<taille) {
                      i++ ;
                      }
                      nbe1++ ;
                      if(tab[i] == f || nbe1>taille) {
                      return (-1) ;
                      }
                      else {
                      return (i) ;
                      }
                      }

                      void inserElt (int indice , int nbe1 , float tab1[] ) {
                      int i ;
                      if (indice !=-1) {
                      for (i=nbe1 ; i>=indice ; i--) {
                      tab1[i+1]=tab1[i] ;
                      }
                      }
                      }

                      int main () {
                      int j , nbe1=4 , taille = 5 , indice ;
                      float tab1[5]= {1,2,4,5} , f=3.25 ;
                      indice = indiceInsert(tab1 ,taille , f , nbe1) ;
                      printf ("l'indice de la valeur insérée est : %d" , indiceInsert(tab1,taille,f,nbe1)) ;
                      inserElt(indice , nbe1 , tab1) ;
                      for (j=0 ; j<taille ; j++) {
                      printf ( "%f\n" , tab1[j] ) ;
                      }
                      return 0 ;
                      }

                      Il compile (yessssssssssssssss) mais me met :
                      l'indice de la valeur insérée est : 21.000000
                      2.000000
                      4.000000
                      4.000000
                      5.000000

                      WTF ? :p
                      1. Tu vas avoir un soucis là

                        int indiceInsert (float tab[] ,int taille , float f, int nbe1) {
                        int i=0 ;
                        while (tab[i]<f && i<taille) {
                        i++ ;
                        }
                        nbe1++ ; <===================================
                        if(tab[i] == f || nbe1>taille) {
                        return (-1) ;
                        }
                        else {
                        return (i) ;
                        }
                        }

                        En C, il y a une notion de portée de variable, ta variable nbe1 reprend la valeur que tu lui a passé (nbe1 du main) MAIS ce n'est PAS la même variable, c'est une COPIE. Du coup, ton nbe1++ (donc nbe1 = 5) est vrai que dans indiceInsert. Après, ton nbe1 (du main) est repris comme base et il est égale à 4 point barre :)

                        Pour contrer ça, il faut utiliser des pointeurs. c'est une variable qui vaut l'adresse (en ram) d'une valeur.
                        Ca s'écris comme ça :
                        int* p = &nbe1; /* Je declare p comme "pointeur d'entier" (* = pointeur) et il est égale à l'adresse (en ram) de nbe1 */

                        Si tu veux modifier nbe1 du main via une fonction, il faut lui passer le pointeur.

                        Du coup ton main ça serai genre

                        int nbe1 = 4 ;
                        int* pnbe1 = &nbe1;

                        indice=indiceinsert(..,..,..., pnbe1);

                        et donc ta fonction change aussi,
                        déjà elle prend en parametre non pas int nbe1 mais int* choisi_un_nom

                        ensuite, si tu veux tester la valeur pointé par un pointeur, faut mettre une etoile, tu peux le voir comme ça :

                        pnbe1 = &nbe1; //pnbe1 vaut l'adresse de nbe1
                        *pnbe1 = nbe1 // etoile pnbe1 vaut la même chose que nbe1.
                        1. Normalement on est pas sensé utiliser les pointeurs ... Car c'est une notion que l'on a pas encore vu . Je peux pas faire autrement ? Comme déclarer nbe1 comme variable globale par exemple ?
                          1. Oui, mais alors fait pareil pour taille et tu peux faire int tab[taille] du coup
                            1. Contributeur
                              Nop, int tab[taille] ça causera un warning...
                            2. Pas si taille est declaré comme ça:

                              #define TAILLE = 5;
                            3. Contributeur
                              Yes. Mais je n'avais pas vu que tu lui avais dit de mettre un #define.
                              Dans ce cas, TAILLE ne sera pas une variable. Mais effectivement ça marchera.
                              La syntaxe est :
                              #define TAILLE 5
                              Surtout pas de point virgule, et pas de signe égal.
                            4. Vi, je me suis corrigé après xD j'utilise quasi jamais ces "variables" ^^
                          2. nan c'est pas la solution , il y a encore un soucis ... il m'affiche encore 21 etc ...
                            1. #include <cini.h>
                              int nbe1=4 , taille=5 ;

                              int indiceInsert (float tab[] ,int taille , float f, int nbe1) {
                              int i=0 ;
                              while (tab[i]<f && i<taille) {
                              i++ ;
                              }
                              nbe1++ ;
                              if(tab[i] == f || nbe1>taille) {
                              return (-1) ;
                              }
                              else {
                              return (i) ;
                              }
                              }

                              void inserElt (int indice , int nbe1 , float tab1[] ) {
                              int i ;
                              if (indice !=-1) {
                              for (i=nbe1 ; i>=indice ; i--) {
                              tab1[i+1]=tab1[i] ;
                              }
                              }
                              }

                              int main () {
                              int j , indice ;
                              float tab1[5]= {1,2,4,5} , f=3.25 ;
                              indice = indiceInsert(tab1 ,taille , f , nbe1) ;
                              printf ("l'indice de la valeur insérée est : %d" , indiceInsert(tab1,taille,f,nbe1)) ;
                              inserElt(indice , nbe1 , tab1) ;
                              for (j=0 ; j<taille ; j++) {
                              printf ( "%f\n" , tab1[j] ) ;
                              }
                              return 0 ;
                              }