Disons que j'ai un tableau unidimensionnel de 100 éléments. Existe-t-il un moyen de traiter ce tableau comme un tableau bidimensionnel 10x10 afin de pouvoir effectuer un tri multiparamétrique. Je ne veux vraiment pas stocker le contenu du tableau original dans un nouveau tableau multidimensionnel, je veux juste un moyen d'opérer sur le tableau unidimensionnel comme s'il était bidimensionnel.
Réponses
Trop de publicités?Oui, c'est possible, mais ce n'est généralement pas recommandé. Que vous utilisiez un tableau 1D ou un tableau 2D, vous utilisez simplement une quantité X de mémoire. Vous pouvez utiliser ce bloc de mémoire comme bon vous semble. Si vous devez stocker un "tableau de tableaux" dans ce bloc, vous gagnez en commodité en déclarant le bloc comme un tableau 2D, mais rien ne vous oblige à procéder de cette manière.
Si votre tableau 1D contient 100 éléments et que vous souhaitez stocker 10 éléments dans le tableau, il vous suffira d'indexer manuellement les sous-réseaux en fournissant des multiples de 10 * sizeof(type)
ce qui est exactement ce que l'arithmétique des pointeurs fait pour vous. En fait, vous vous adresserez au tableau 1D comme si vous aviez déclaré un pointeur sur un tableau de total/n
et ensuite alloués pour les n
d'entre eux. (ex. char (*s)[10];
si vous deviez par analogie diviser votre mémoire de 100 caractères en 10 chaînes)
Prenons l'exemple trivial d'un tableau de 100 caractères que vous souhaitez utiliser pour stocker et trier des chaînes de 10 à 10 caractères (9 caractères + l'élément nul-terminant ). Vous pouvez simplement déclarer char s[100] = "";
et stockez ensuite vos chaînes de caractères à des décalages de s + n * 10
. Pour trier le tableau, vous pouvez effectuer votre propre tri ou simplement utiliser qsort
pour trier vos éléments en fournissant une fonction de comparaison appropriée. C'est précisément ce que fait la fonction suivante :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NROW 10
#define NCOL NROW
/* qsort - string comparison */
int cmpstrings (const void *a, const void *b) {
return strcmp ((char * )a, (char *)b);
}
int main (void) {
char s[NROW * NCOL] = ""; /* 1D array 100 chars */
strcpy (s, "my"); /* fill with 10 strings */
strcpy (s + NROW, "dog");
strcpy (s + NROW * 2, "has");
strcpy (s + NROW * 3, "fleas");
strcpy (s + NROW * 4, "but");
strcpy (s + NROW * 5, "the");
strcpy (s + NROW * 6, "cat");
strcpy (s + NROW * 7, "doesn't");
strcpy (s + NROW * 8, "have");
strcpy (s + NROW * 9, "any");
printf ("unsorted:\n");
for (int i = 0; i < NROW; i++)
printf (" s[%2d] : %s\n", i, &s[i*NCOL]);
qsort (s, NCOL, NROW, cmpstrings); /* qsort strings */
printf ("\nsorted:\n");
for (int i = 0; i < NROW; i++)
printf (" s[%2d] : %s\n", i, &s[i*NCOL]);
}
( note : strcpy
a été utilisé par commodité pour charger les chaînes individuelles dans le tableau. Vous auriez tout aussi bien pu initialiser le tableau avec les 100 caractères spécifiés dans un initialisateur)
Par exemple, vous auriez pu utiliser l'initialisateur suivant et éliminer les appels à strcpy
tout à fait - juste un peu plus fastidieux...
/* initialize 100-char array with 10 sub-arrays of strings */
char s[] = "my\0 dog\0 has\0 fleas\0 but\0 "
"the\0 cat\0 doesn't\0 have\0 any\0 ";
Exemple d'utilisation/de sortie
$ ./bin/array1dstrings
unsorted:
s[ 0] : my
s[ 1] : dog
s[ 2] : has
s[ 3] : fleas
s[ 4] : but
s[ 5] : the
s[ 6] : cat
s[ 7] : doesn't
s[ 8] : have
s[ 9] : any
sorted:
s[ 0] : any
s[ 1] : but
s[ 2] : cat
s[ 3] : doesn't
s[ 4] : dog
s[ 5] : fleas
s[ 6] : has
s[ 7] : have
s[ 8] : my
s[ 9] : the
Le langage C n'impose aucune limite à l'utilisation d'un bloc de mémoire tant que vous n'essayez pas d'accéder à la mémoire en dehors du bloc valide. C'est à vous d'utiliser un système d'adressage qui permette d'atteindre cet objectif. Le tableau 2D fournit simplement un moyen pratique d'éviter d'avoir à trouver ce plan d'adressage par vous-même.
La question de savoir s'il s'agit d'un code C11 strictement légal est controversée, mais un code tel que celui présenté ci-dessous est tout à fait courant :
#include <stdio.h>
int a1[100];
int (*a2)[10] = (int (*)[10])a1;
int main(int argc, char *argv[]) {
for (int i = 0; i < 100; i += 1) a1[i] = i + 1;
for (int i = 0; i < 10; i += 1) {
for (int j = 0; j < 10; j += 1) {
printf("%2d ", a2[i][j]);
}
printf("\n");
}
}
Vous pourriez le rendre strictement conforme, mais un peu moins pratique, en remplaçant a2 par :
#define a2(x,y) a1[10*(x)+(y)]
et remplacez ensuite a2[x][y]
con a2(x,y)
. Ou utiliser une fonction, mais cela vous coûte un surcoût d'appel de fonction (ou faire un inline
).