web-dev-qa-db-fra.com

La valeur en indice C n'est ni un tableau, ni un pointeur, ni un vecteur lors de l'attribution d'une valeur d'élément de tableau

Désolé de poser la question déjà répondue, je suis un débutant en C et ne comprends pas les solutions .

int rotateArr(int *arr) {
    int D[4][4];
    int i = 0, n =0;
    for(i; i < M; i ++ ){
        for(n; n < N; n++){
            D[i][n] = arr[n][M - i + 1];
        }
    }
    return D;
}

Il jette une erreur 

main.c | 23 | error: la valeur indiquée n'est ni tableau ni pointeur ni vecteur |

en ligne 

D [i] [n] = arr [n] [M - i + 1];

Qu'est-ce qui ne va pas? Je ne fais que définir la valeur d'un élément de tableau sur un autre élément de tableau.

L'arr passé est déclaré comme

int S[4][4] = { { 1, 4, 10, 3 }, { 0, 6, 3, 8 }, { 7, 10 ,8, 5 },  { 9, 5, 11, 2}  };
10
Euphe

C vous permet d’utiliser l’indicateur [] sur les tableaux et les pointeurs. Lorsque vous utilisez cet opérateur sur un pointeur, le type résultant est le type vers lequel le pointeur pointe. Par exemple, si vous appliquez [] à int*, le résultat serait une int.

C’est précisément ce qui se passe: vous passez int*, ce qui correspond à un vecteur d’entiers. L'utilisation de l'indice dessus une fois le rend int, vous ne pouvez donc pas lui appliquer le second indice.

D'après votre code, il apparaît que arr devrait être un tableau à deux dimensions. S'il est implémenté en tant que tableau "en dents de scie" (c'est-à-dire un tableau de pointeurs), le type de paramètre doit être int **.

De plus, il semble que vous essayez de retourner un tableau local. Afin de le faire légalement, vous devez allouer le tableau dynamiquement et renvoyer un pointeur. Cependant, une meilleure approche consisterait à déclarer une struct spéciale pour votre matrice 4x4 et à l'utiliser pour envelopper votre tableau de taille fixe, comme ceci:

// This type wraps your 4x4 matrix
typedef struct {
    int arr[4][4];
} FourByFour;
// Now rotate(m) can use FourByFour as a type
FourByFour rotate(FourByFour m) {
    FourByFour D;
    for(int i = 0; i < 4; i ++ ){
        for(int n = 0; n < 4; n++){
            D.arr[i][n] = m.arr[n][3 - i];
        }
    }
    return D;
}
// Here is a demo of your rotate(m) in action:
int main(void) {
    FourByFour S = {.arr = {
        { 1, 4, 10, 3 },
        { 0, 6, 3, 8 },
        { 7, 10 ,8, 5 },
        { 9, 5, 11, 2}
    } };
    FourByFour r = rotate(S);
    for(int i=0; i < 4; i ++ ){
        for(int n=0; n < 4; n++){
            printf("%d ", r.arr[i][n]);
        }
        printf("\n");
    }
    return 0;
}

This imprime ce qui suit :

3 8 5 2 
10 3 8 11 
4 6 10 5 
1 0 7 9 
14
dasblinkenlight

Vous ne passez pas correctement votre tableau 2D. Cela devrait fonctionner pour vous 

int rotateArr(int *arr[])

ou 

int rotateArr(int **arr) 

ou 

int rotateArr(int arr[][N]) 

Plutôt que de renvoyer le tableau, passez le tableau cible en argument. Voir la réponse de John Bode.

6
Sadique

Sauf s’il s’agit de l’opérande de l’opérateur sizeof ou unary &, ou d’un littéral utilisé pour initialiser un autre tableau dans une déclaration, une expression de type "tableau N-élément de T" est convertie en un expression de type "pointeur sur T", et la valeur de l'expression est l'adresse du premier élément du tableau. 

Si la déclaration du tableau en cours de passage est

int S[4][4] = {...};

alors quand tu écris

rotateArr( S );

l'expression S a le type "tableau à 4 éléments d'un tableau à 4 éléments de int"; étant donné que S n'est pas l'opérande des opérateurs sizeof ou unaire &, il sera converti en une expression de type "pointeur sur un tableau à 4 éléments de int", ou int (*)[4], et ce pointeur valeur est ce qui est réellement transmis à rotateArr. Votre prototype de fonction doit donc être l’un des suivants:

T rotateArr( int (*arr)[4] )

ou

T rotateArr( int arr[][4] )

ou même

T rotateArr( int arr[4][4] )

Dans le contexte d'une liste de paramètres de fonction, les déclarations de la forme T a[N] et T a[] sont interprétées comme T *a; tous les trois déclarent a comme pointeur sur T.

Vous vous demandez probablement pourquoi j'ai changé le type de retour de int à T. Comme vous l'avez écrit, vous essayez de renvoyer une valeur de type "tableau à 4 éléments d'un tableau à 4 éléments de int"; Malheureusement, vous ne pouvez pas faire ça. Les fonctions C ne peuvent pas renvoyer les types de tableaux, ni affecter les types de tableaux. IOW, vous ne pouvez pas écrire quelque chose comme:

int a[N], b[N];
...
b = a; // not allowed
a = f(); // not allowed either

Les fonctions peuvent renvoyer pointeurs aux tableaux, mais ce n'est pas ce que vous voulez ici. D cessera d'exister une fois la fonction retournée, ainsi tout pointeur que vous renverrez sera invalide. 

Si vous souhaitez affecter les résultats du tableau pivoté à un autre tableau, vous devrez alors passer le tableau cible en tant que paramètre à la fonction:

void rotateArr( int (*dst)[4], int (*src)[4] )
{
  ...
  dst[i][n] = src[n][M - i + 1];
  ...
}

Et appelez comme

int S[4][4] = {...};
int D[4][4];

rotateArr( D, S );
6
John Bode

Le problème est que arr n'est pas (déclaré comme) un tableau 2D et vous le traitez comme s'il s'agissait de 2D.

3
NPE

le second opérateur en indice n'est pas valide ici . Vous avez passé un pointeur int * dans function, qui est un tableau 1-d Donc, un seul opérateur en indice peut être utilisé. 

Solution: vous pouvez passer le pointeur int ** dans funciton

0
nathan

Vous avez "int * arr" alors "arr [n]" est un int, non? Ensuite, votre bit "[M - 1 + 1]" tente d'utiliser cet int en tant que tableau/pointeur/vecteur.

0
Peter Cardona