Afficher le contenu des cellules identique dans un tableau en C

Fermé
bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017 - Modifié par baladur13 le 4/06/2016 à 13:45
paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018 - 6 juin 2016 à 21:11
Bonsoir tous le monde,
je veux faire un programme en C qui m'affiche les lignes où le contenu des premières colonnes sont identiques. Exemple: Soit le tableau suivant (deux dimensions):
0 0 0
0 1 6
0 3 7
0 1 8
0 4 7
0 3 15

Le résultat, doit m'afficher:
1,6,8
3,7,15

voici ce que j'ai déjà fait:
int main()

{

int i,j;
int dim1 = 6, dim2 = 3;

// Création dynamique d’un tableau à 2 dimensions
int** tab = (int**) malloc(dim1 * sizeof (int*) );

for (i=0; i<dim1; i++)
{
tab[i] = (int*) malloc (dim2 * sizeof (int) );
}
//Initialiation de la première colonne à 0
for (i=0; i<dim1; i++)
{
 tab[i][0]=0;
}
//Initialiation de la première ligne à 0
for (j=0; j<dim2; j++)
{
 tab[0][j]=0;
}
//Initialisation du reste du tableau
for (i=1; i<dim1; i++)
{
for (j=1; j<dim2; j++){
 //tab[i][j]=i+j;
 printf("L%d C%d: ",i,j);
 scanf("%d",&tab[i][j]);
}

}
//affichage

for (i=0; i<dim1; i++)
{
for (j=0; j<dim2; j++){
 printf("%d ",tab[i][j]);
}
 printf("\n");
}
printf("\n \n");
///Comparaison
for(j=1;j< dim1;j++)
{
 for(i=1;i<dim1;i++){
   if((tab[j][1]==tab[i][1]))                     
      printf(" %d, %d\n",tab[j][1]);                          
     
}
}


// Libération mémoire : tableau dynamique à 2 dimensions

free(tab);
  return 0;
}

S'il vous lait, j'ai besoin d'aide
EDIT : Ajout des balises de code (la coloration syntaxique).
Explications disponibles ici : ICI

Merci d'y penser dans tes prochains messages.

8 réponses

paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018 25
2 juin 2016 à 17:21
Juste pour nous aider à comprendre, ça serait bien d'utiliser la balise "code c" afin d'avoir la coloration syntaxique et de conserver les tabulations...

Je n'ai pas beaucoup regardé l'algorithme (trop difficile à lire en l'état), mais j'y vois un problème de libération de mémoire: il faut que tu fasses un free sur tous les "sous-tableaux" de tab avant de faire un free sur tab. De la même façon que tu alloues en fait, mais en remplaçant malloc par free.
De plus, ici, l'utilisation de l'allocation dynamique n'est pas justifiée car tu ne changes pas la taille de ton tableau: tu peux donc aussi bien l'allouer statiquement (automatiquement):
int dim1 = 6, dim2 = 3;
int tab[dim1][dim2];

Cette syntaxe est autorisée depuis pas mal de temps (norme C99 en... 1999). Si tu ne comptes pas insérer des lignes entre la déclaration de dim1/dim2 et celle du tableau qui modifient dim1 et dim2, tu peux même tout simplement faire:
int tab[6][3];

Ce qui est autorisé depuis encore plus longtemps (depuis la première norme du C en 1989 en fait, ANSI C ou C89).
0
bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017 2
2 juin 2016 à 17:26
Merci pour la réponse. En effet, la taille du tableau change régulièrement. Comment enlever les dim1 et dim2 afin de l'adopter à n'importe quelle taile?
0
paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018 25
2 juin 2016 à 19:55
Ah, si la taille du tableau doit changer, effectivement, une allocation dynamique comme tu as faite est nécessaire ! Pense juste à modifier ton free.

Et surtout, repaste ton code avec les balises <code c>.
0
bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017 2
2 juin 2016 à 19:58
Ce que je veux réellement c'est:
Si on a un tableau comme ceci:
1 2
3 9
5 8
1 4
3 12
1 21

le résultat final nous affiche, les valeurs qui s'affichent au moins deux fois dans la première colonne avec leur correspondance dans la deuxième colonne comme:
1 (2,4,21)
3 (9,12)
0
Franck7511 Messages postés 14296 Date d'inscription jeudi 24 décembre 2009 Statut Membre Dernière intervention 10 août 2017 1 121
2 juin 2016 à 20:36
Pourquoi pas trier dans ce cas ?
Trivialement tu peux faire ça en O(n²)
0
bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017 2
2 juin 2016 à 21:02
Comment?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018 25
3 juin 2016 à 07:13
1. Trouver tous les différents nombres dans la première colonne et enregistrer leur ligne (tu peux utiliser une boucle pour trouver les nombres, un tableau dynamiquement alloué que tu agrandis à chaque fois que tu trouves un nouveau nombre, et une structure pour stocker les nombres qui contient elle-même une variable int pour le nombre et un tableau dynamiquement alloué pour les lignes auxquelles ils se trouvent, ainsi que de préférence une variable qui indique la taille de ce tableau).

Là tu as presque fait tout le boulot. Ensuite:

2. Pour tous les nombres de ton nouveau tableau:
A) Tu l'affiche
B) Tu affiche un espace et tu ouvres une parenthèse
C) Pour toutes les lignes auxquelles se trouvent le nombre dans la première colonne :
a) Tu affiches le deuxième nombre de la ligne.
b) Tu affiches une virgule sauf pour le dernier nombre.
D) Tu fermes la parenthèse et tu reviens à la ligne.
0
Franck7511 Messages postés 14296 Date d'inscription jeudi 24 décembre 2009 Statut Membre Dernière intervention 10 août 2017 1 121
Modifié par Franck7511 le 3/06/2016 à 08:31
"un tableau dynamiquement alloué que tu agrandis à chaque fois que tu trouves un nouveau nombre" ??? Encore plus lent stp, c'est pas gratuit une allocation mémoire

Sinon très simplement tu tries le tableau sur la première colonne (O(nlogn)), et tu boucles sur le tableau trié...

Petite douille, chaque élément de ton tableau est une ligne (donc de type int *), adapte num et size en conséquence.
Pour la fonction de comparaison, elle va prendre deux int * (deux lignes) en argument et retourner une valeur suivant le premier élément des 2 lignes.

http://www.cplusplus.com/reference/cstdlib/qsort/

1 2
3 9
5 8
1 4
3 12
1 21

deviendra

1 2
1 4
1 21
3 9
3 12
5 8

J'espère que tu vois comment faire ensuite.
0
paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018 25
3 juin 2016 à 12:28

"un tableau dynamiquement alloué que tu agrandis à chaque fois que tu trouves un nouveau nombre" ??? Encore plus lent stp, c'est pas gratuit une allocation mémoire


Une allocation de mémoire ce n'est pas gratuit, mais qsort, ça l'est encore moins. Jette un coup d'oeil aux algorithmes, pourtant très optimisés. En plus, qsort en fait, des allocations dynamiques.

Si tu ne me crois pas, fais un test de vitesse de deux programmes conçus l'un avec ma technique, l'autre avec qsort...
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
3 juin 2016 à 14:26
qsort() fait des allocations dynamiques ? Depuis quand ?

Si tu ne me crois pas, fais un test de vitesse de deux programmes conçus l'un avec ma technique, l'autre avec qsort...
Pas étonnant. Lorsqu'il y a peu de données à trier, qsort() n'est clairement pas l'algorithme le plus rapide. Cependant grâce à sa meilleure complexité algorithmique, il est plus performant (rapide) lorsqu'il y a beaucoup de données.
0
paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018 25
3 juin 2016 à 14:54
qsort() fait des allocations dynamiques ? Depuis quand ?
Depuis quand ? Je ne sais pas. Mais en tout cas, elle en fait: par exemple, dans la GNU glibc 2.9 (qui reste LA référence pour la bibliothèque standard C), tu as un malloc ligne 219, et un __alloca ligne 177 du fichier stdlib/msort.c.
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
3 juin 2016 à 17:47
GNU glibc 2.9 (qui reste LA référence pour la bibliothèque standard C)
Non, ce n'est pas la référence. Ici, il s'agit de la surcouche GNU, non standard.
En C standard, il n'y a pas d'allocation.
Dans le man "while qsort() does not allocate memory, it is implemented using
recursion.
0
bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017 2
4 juin 2016 à 21:20
Je dois faire une allocation dynamique car la taille du tableau varie.
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
4 juin 2016 à 23:02
Beh dans ce cas, utilisation de malloc() pour une première allocation, et puis réallocation avec realloc().
Note : on évite de réallouer pour une seule case. Il vaut mieux réinitialiser plusieurs cases d'un coup pour plus de performances.
0
bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017 2
4 juin 2016 à 23:11
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
int main()
{
int ** t2D;
int n;
int m;

printf ("n ? ");
scanf("%d",&n);
printf ("m ? ");
scanf("%d",&m);

// t2D = malloc(sizeof(int *) * n);
t2D = (int**) malloc(n * sizeof (int*) );
int i;
for (i = 0 ; i < n ; i++)
// t2D[i] = malloc(sizeof(int) * m);
t2D[i] = (int*) malloc (m * sizeof (int) );

int j;
printf ("Saisie des valeurs :\n");
for (i = 0 ; i < n ; i++)
for (j = 0 ; j < m ; j++)
{
printf ("t2D[%d][%d] = ? ",i,j);
scanf("%d", &t2D[i][j]);
}

printf ("Affichage du tableau : \n");
for (i = 0 ; i < n ; i++)
{
for (j = 0 ; j < m ; j++)
printf ("%6d",t2D[i][j]);
printf ("\n");
}
//

for (i = 0 ; i < n ; i++)
free (t2D[i]);
free (t2D);

return 0;
}


voici le tableau que j'ai, il me reste maintenant, à afficher les valeurs identiques du première colonne ainsi que leurs correspondance au niveau de la deuxième colonne. Aidez moi s'il vous plait à le finir.

Merci pour vos réponses
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842
4 juin 2016 à 23:51
On a demandé d'utiliser la balise <code c> lorsque tu postes ton code sinon c'est illisible...
Exemple :
<code c>/*ici tu mets ton code*/</code>

Mes remarques sur ton code :
#include <conio.h>
Non standard, et inutile ici -> à supprimer.

int main()
Le bon prototype du main sans argument est :
int main (void)


t2D = (int**) malloc(n * sizeof (int*) );
Ce n'est pas une faute, mais le cast est superflu. Il est même déconseillé.
Donc plutôt :
t2D = malloc (n * sizeof (int*));


Il est conseillé également de contrôler le retour des malloc(). Si cela renvoie NULL, c'est que l'allocation a échoué (par exemple, imagine si n est négatif...).

Ensuite, il me semble que Paly t'a déjà expliqué algorithmiquement comment faire.
Cela ne te convient pas ?
0
bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017 2
4 juin 2016 à 23:25
Par exemple, si j'ai:
1 3
2 9
8 98
1 7
8 65

le programme m'affiche:
1 (3,7)
8 (98,65)

Merci
0
paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018 25
5 juin 2016 à 11:37
Ce que je t'expliquais dans un précédent message, c'est de:
1. Créer une structure (appelons-la "nombre").
struct nombre {
    int nombre; // Le nombre de la première colonne que représente la structure.
    int* lignes; // Le tableau (qu'il faudra allouer avec malloc puis libérer avec free) qui contient les numéros des lignes auxquelles se trouve le nombre.
    int taille_lignes; // Le nombre de cases utilisées du tableau lignes.
};


2. Obtenir tous les nombres différents de la première colonne. Ici un exemple pas du tout optimisé et non testé (donc contenant très probablement des erreurs):
struct nombre nombres[n] = {{0, NULL, 0}};
int taille_nombres = 0;
// ...
for (i = 0 ; i < n ; i++) {
    for (j = 0 ; j < taille_nombres ; j++) {
        if (nombres[j].nombre == t2D[i][0]) {
            nombres[j].lignes[taille_lignes] = i;
            nombres[j].taille_lignes++;
            break;
        }
    }
    if (j == taille_nombres) { // Si t2D[i][0] n'était pas déjà dans nombres
        nombres[taille_nombres].lignes = malloc(n * sizeof(int));
        // Vérifier que malloc a fonctionné!! (= que nombres[taille_nombres].lignes n'est pas NULL)
        nombres[taille_nombres].nombre = t2D[i][0];
        nombres[taille_nombres].lignes[0] = i;
        nombres[taille_nombres].taille_lignes++;
    }
}
// Voilà, le tableau nombres est prêt ! Plus qu'à l'afficher ! Ne pas oublier de free() tous les nombres[x]·lignes.


Pour l'affichage, je répète ce que j'avais dit:
Pour chaque nombres[x]:
A) Tu affiches nombre.
B) Tu affiches un espace et tu ouvres une parenthèse
C) Pour toutes les lignes auxquelles se trouvent le nombre dans la première colonne :
a) Tu affiches le deuxième nombre de la ligne.
b) Tu affiches une virgule sauf pour le dernier nombre.
D) Tu fermes la parenthèse et tu reviens à la ligne.
0
bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017 2 > paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018
6 juin 2016 à 03:39
Merci pour l'aide que vous venez de m'apporter mais voici le programme et j'obtiens des erreur. Aussi, pourquoi for (j = 0 ; j < taille_nombres ; j++) alors que vous l'avez initialisé à 0?

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
struct nombre {
int nombre; // Le nombre de la première colonne que représente la structure.
int* lignes; // Le tableau (qu'il faudra allouer avec malloc puis libérer avec free) qui contient les numéros des lignes auxquelles se trouve le nombre.
int taille_lignes; // Le nombre de cases utilisées du tableau lignes.
};
int main()
{
int ** t2D;
int n;
int m;
printf ("n ? ");
scanf("%d",&n);
printf ("m ? ");
scanf("%d",&m);
struct nombre nombres[n] = {{0, NULL, 0}};
int taille_nombres = 0;

// t2D = malloc(sizeof(int *) * n);
t2D = (int**) malloc(n * sizeof (int*) );
int i;
for (i = 0 ; i < n ; i++)
// t2D[i] = malloc(sizeof(int) * m);
t2D[i] = (int*) malloc (m * sizeof (int) );

int j;
printf ("Saisie des valeurs :\n");
for (i = 0 ; i < n ; i++)
for (j = 0 ; j < m ; j++)
{
printf ("t2D[%d][%d] = ? ",i,j);
scanf("%d", &t2D[i][j]);
}

printf ("Affichage du tableau : \n");
for (i = 0 ; i < n ; i++)
{
for (j = 0 ; j < m ; j++)
printf ("%6d",t2D[i][j]);
printf ("\n");
}
////
for (i = 0 ; i < n ; i++) {
for (j = 0 ; j < taille_nombres ; j++) {
if (nombres[j].nombre == t2D[i][0]) {
nombres[j].lignes[taille_lignes] = i;
nombres[j].taille_lignes++;
break;
}
}
if (j == taille_nombres) { // Si t2D[i][0] n'était pas déjà dans nombres
nombres[taille_nombres].lignes = malloc(n * sizeof(int));
// Vérifier que malloc a fonctionné!! (= que nombres[taille_nombres].lignes n'est pas NULL)
nombres[taille_nombres].nombre = t2D[i][0];
nombres[taille_nombres].lignes[0] = i;
nombres[taille_nombres].taille_lignes++;
}
}
return 0;
}
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 842 > bayefalle Messages postés 122 Date d'inscription jeudi 7 novembre 2013 Statut Membre Dernière intervention 12 mai 2017
Modifié par fiddy le 6/06/2016 à 07:03
Ca serait bien de tenir compte de l'ensemble des commentaires.
Donc, je remets ici pour une dernière fois :
Merci d'utiliser la balise <code c> lorsque tu postes ton code sinon c'est illisible...
Exemple :
<code c>/*ici tu mets ton code*/</code>

Et au lieu de laisser dans les commentaires "vérifier que malloc a fonctionné", il faut le faire. C'est-à-dire, mettre un if...

Le cast() devant les malloc() est inutile, voire même déconseillé.
0
paly2 Messages postés 254 Date d'inscription vendredi 29 août 2014 Statut Membre Dernière intervention 15 février 2018 25
6 juin 2016 à 21:11
Aussi, pourquoi for (j = 0 ; j < taille_nombres ; j++) alors que vous l'avez initialisé à 0?

Parce que taille_nombres augmente. En fait j'ai oublié de mettre la ligne taille_nombre++ (comme je te le disais je n'ai pas testé le code) :p dsl


struct nombre nombres[n] = {{0, NULL, 0}};
int taille_nombres = 0;
// ...
for (i = 0 ; i < n ; i++) {
    for (j = 0 ; j < taille_nombres ; j++) {
        if (nombres[j].nombre == t2D[i][0]) {
            nombres[j].lignes[taille_lignes] = i;
            nombres[j].taille_lignes++;
            break;
        }
    }
    if (j == taille_nombres) { // Si t2D[i][0] n'était pas déjà dans nombres
        nombres[taille_nombres].lignes = malloc(n * sizeof(int));
        if (nombres == NULL) {
            fprintf(stderr, "Erreur d'allocation.\n");
            for (i = 0 ; i < taille_nombres ; i++) // Les allocations précédentes ont pu fonctionner, il faut désallouer.
                free(nombres[taille_nombres].lignes);
            exit(EXIT_FAILURE);
        }
        nombres[taille_nombres].nombre = t2D[i][0];
        nombres[taille_nombres].lignes[0] = i;
        nombres[taille_nombres].taille_lignes++;
        taille_nombres++;
    }
}
// ...
for (i = 0 ; i < taille_nombres ; i++)
    free(nombres[taille_nombres].lignes);
0