[C] Passer un tableau multi-dimension en paramètre

Hello, je tente vainement de faire passer un tableau d’integer deux dimensions à une fonction, sans succès :/.

Comment faire? Doit-on utiliser une technique dans ce style :

[code]void imp_tab(int t, int nb_elem) / définition de imp_tab */
{
int i;

for (i = 0; i < nb_elem; i++) printf("%d ",*(t + i));
}[/code]

Merci d’avance.

Bah là tu nous as posté un code avec un tableau à une dimension, la version à deux dimensions devrait ressembler à :

[code]void imp_tab(int *t, int nb_elem) / définition de imp_tab */
{
int i,j;

for (i = 0; i < nb_elem; i++)
{
for(j=0;j<nb_elem;j++)
printf("%d “,((t + i)+j)); //je prefere la notation printf(”%d “,t[i][j]); qui revient au meme en plus lisible
printf(”\n");
}
}[/code]

Ca c’est dans le cas d’un tableau carré, sinon faut prendre longueur et largeur en argument à la place de nb_elem.

Peut etre que le lis pas dans le bon sens mais c’est juste i et un j à intervertir si c’est le cas. (je m’embrouilles toujours dans les matrices)

En fait, un tableau c’est juste un pointeur.

Merci pour la réponse, mais je bloque :

signature de ma fonction :

je déclare deux tableaux deux dimensions :

// declaration du tableau stockage des requetes int requetes[tailleV->nombre_requetes][NOMBRE_COLONNES_REQUETES]; // declaration du tableau stockage des alternatives int alternatives[tailleV->nombre_alternatives][NOMBRE_COLONNES_ALTERNATIVES];

et je tente de les passer en paramètre, le compilateur n’est pas content content :P.

Je n’arrive d’ailleurs pas à m’imaginer ce que représente int**…

A l’oeil là, le compilo est pas content parce qu’un tableau c’est pas vraiment un **. Faudrait le caster en fait. A la rigueur tu fais un vrai **, donc avec des mallocs et tout le taintouin chiant.

Un ** c’est un pointeur sur des pointeurs. En gros imagine que tu pointe vers une cellule memoire, et ensuite dans celle-ci y a encore un autre pointeur vers une autre cellule mémoire.
Typiquement, un tableau à 2 dimensions c’est un ** spécial, alloué de manière continue (donc premier niveau de pointeur = ligne, deuxieme = colonne).

C’est plus simple à comprendre de manière visuelle, mate sur CommentCaMarche ou chope un bouquin d’intro au C.

[special EPFL] Je te conseille de choper le cours de Programmation III, nous on a vu le C avec ce cours (Chappi en plus quelle horreur).

Rassure-nous, on est quand meme pas en train de te faire ton projet :stuck_out_tongue:

[quote=« Maverick, post:3, topic: 28929 »]je déclare deux tableaux deux dimensions :

// declaration du tableau stockage des requetes int requetes[tailleV->nombre_requetes][NOMBRE_COLONNES_REQUETES];

et je tente de les passer en paramètre, le compilateur n’est pas content content :P.

Je n’arrive d’ailleurs pas à m’imaginer ce que représente int**…[/quote]

C’est normal, ton compilateur est sévère mais juste.

[code]#include <stdio.h>
#include <stdlib.h>

int
somme(int** tbl, int tx, int ty)
{
int i, j, somme = 0;

for (i = 0; i < tx; i++)
for (j = 0; j < ty; j++)
somme += tbl[i][j];

return somme;
}

int
main(void)
{
int x = 3;
int tab[3][4];
int tab2[x][4];

printf("\n%d", somme((int**)tab2, 3, 4));
return 0;
}[/code]

Déjà, dans la norme, on ne devrait pas pouvoir déclarer un tableau avec une taille non-constante, c’est déjà bien que cela passe.
Ensuite, en C, dans une déclaration de fonction, tu as le droit de mettre int myfun(int t[3][4]) ou int myfun(int** t), point final. Tu es d’accord que ce sont deux types différents? Eh bien, c’est ce qui explique la conversion de type (‹ cast ›) que j’ai dü réaliser dans codetab2[/code].

Voilà, ca devrait calmer ton compilateur (qui est ton ami: tous ses messages sont justifiés).

Quant au pourquoi du int**, je te recommande grandement de t’immerger dans ton cours rapidement. En gros, int mytab[3], int mytab[3][4] sont des écritures un peu spéciales pour désigner un type de tableau dont la taille doit correspondre à un nombre bien défini (utile pour représenter un point 3d). En fait, en C, la notation universelle et courante est celle des pointeurs. Cela donne: int* et int** respectivement. Quant aux tailles, il faut que tu les stockes séparément.

Alors pourquoi deux *? Bon, voilà la manière générale de créer des tableaux en 1 et 2 dimensions en C:

. int* l1 = (int*) malloc(4 * sizeof(int)); int* l2 = (int*) malloc(4 * sizeof(int)); int* l3 = (int*) malloc(4 * sizeof(int)); int** tab3 = (int**) malloc(3 * sizeof(int*)); tab3[0] = l1; tab3[1] = l2; tab3[2] = l3;.

l1 est une des 3 lignes de ta matrice. malloc va allouer un espace mémoire suffisant pour chaque ligne, et en retourner l’adresse sous forme de pointeur. Comme on pointe une série de int, le type est int*. Le cast qui est présent est dü au fait que malloc renvoie un pointeur sur n’importe quoi (void*), alors que l1 est pointeur sur int seulement.

tab3, maintenant. Ta matrice, ca va etre un tableau contenant tes trois lignes. Donc, sa taille est de 3, et le type contenu est int*, et non plus seulement int. tab3 pointe sur une série de int*, il est de type int**.

Ok?

Tout d’abord merci beaucoup pour ton aide. Pour info je ne suis pas en première année informatique, loin de là, mais je n’ai jamais fait de C.

J’ai essayé de faire au plus simple, pour comprendre, mais segmentation fault :

main.c

[code]#include <stdio.h>
#include <stdlib.h>

#include “fonction.h”

int main(int argc, char *argv[]){
int i,j;
int test[10][10];

testFonction((int**)test, 10, 10);

for(i=0; i<10; i++){
	for(j=0; j<10; j++){
		printf("%d ", test[i][j]);	
	}	
	printf("\n");
}

}[/code]
fonction.h

[code]#ifndef FONCTION_H_
#define FONCTION_H_

#endif /FONCTION_H_/

void testFonction(int** tableau, int taillex, int tailley);[/code]

fonction.c

[code]#include <stdio.h>
#include <stdlib.h>

#include “fonction.h”

void testFonction(int** tableau, int taillex, int tailley){
int i, j;

for(i=0; i<taillex; i++){
	for(j=0; j<tailley; j++){
		tableau[i][j] = 9;
	}
}

}[/code]

Qué passa senior?

Il ne faut pas confondre les tableaux à deux dimensions et les tableaux de pointeurs. Ils s’utilisent certes de la même façon, mais ils n’ont pas la même représentation en mémoire. Quand tu déclares un test[10][10], il va créer un tableau de 100 cases contigues, sans pointeur à l’intérieur du tableau (donc pas la même chose que ce que présente vectra en fin de son post).

Pour accéder à une case du tableau, par exemple test[3][4], le code fait simplement 10x3 + 4 et accède à la 34ème 35ème case de test.
Problème : quand tu passes test en argument, la fonction ne connait plus combien il y a de lignes dans ton tableau. Il faut donc lui spécifier.

main.c reste inchangé, mais fonction.c et fonction.h deviennent :

fonction.c

[code]#include <stdio.h>
#include <stdlib.h>

#include “fonction.h”

void testFonction(int tableau[][10], int taillex, int tailley){
int i, j;

for(i=0; i<taillex; i++){
	for(j=0; j<tailley; j++){
		tableau[i][j] = 9;
	}
}

}[/code]

fonction.h (juste pour éviter un warning)

[code]#ifndef FONCTION_H_
#define FONCTION_H_

#endif /FONCTION_H_/

void testFonction(int tableau[][], int taillex, int tailley);[/code]

Pour le fonction.h, faut mettre la declaration de la fonction avant le #endif, ça évite des redifinitions de fonction si on inclue deu fois le fichier (ce qui peut arriver des fois)

[quote=“kineox, post:7, topic: 28929”]fonction.h (juste pour éviter un warning)

[code]#ifndef FONCTION_H_
#define FONCTION_H_

#endif /FONCTION_H_/

void testFonction(int tableau[][10], int taillex, int tailley);[/code][/quote]
Super merci, ca fonctionne, mais j’ai du spécifier la taille dans le hearder de fonction également.

Meilleures salutations.

Vache, désolé. :stuck_out_tongue:
Je suis vraiment surpris, et tout aussi confus: je ne voulais pas te paraitre méprisant ou quoi que ce soit.
Ce qu’il y a, c’esr que l’étiquette des newsgroups (e.g comp.lang.c) interdit formellement de répondre à des besoins d’exercices ou de projets d’étudiants, par exemple. Pour leur bien: ce n’est qu’en mettant ses mains dans le cambouis qu’on arrive à acquérir les connaissances et à etre autonome.

Mais ici, OK! :stuck_out_tongue:

Mais oui, enfin! :stuck_out_tongue:

J’ai complètement oublié cette histoire de tableaux sans pointeurs. Personellement, je trouve cela tellement abscons et erreurogène qu’après avoir tout testé, j’ai tout enterré bien profondément ca dans ma mémoire. L’avantage des pointeurs, c’est que c’est plus clair et générique, à mon sens. DESOLE :stuck_out_tongue: