sharp - pasar un arreglo como parametro en java
Pasar una matriz 2D de estructuras (2)
Estoy repartiendo estructuras de tipo tarjeta desde una matriz.
struct card deck[DECKSIZE]; //The deck is an array of cards structures
Estoy usando una matriz 2D. Un conjunto de conjuntos de estructuras de tipo tarjeta
struct card allHands[hands][cards];
Estoy usando esta función pasando el mazo y la matriz como punteros con los parámetros de la matriz. También cambio la ubicación del puntero del mazo para simular que el mazo pierde la carta cuando se pasa al jugador.
void dealHands(struct card *deck, struct card **handArray, int hands, int cards){
int players;
int cardCount;
int passCard = 0;
struct card * thisDeck;
thisDeck = deck;
for(players = 0; players < hands; players++){
for(cardCount = 0; cardCount < cards; cardCount++){
handArray[players][cardCount] = thisDeck[passCard];
passCard++;
}
}
deck = (deck + passCard);
}
Ha pasado mucho tiempo que programo en c, así que creo que así es como se hace el prototipo.
void dealHands(struct card[], struct card*[], int, int);
Esto es como el esqueleto de mi principal de cómo estoy implementando la función.
int main(int argc, char *argv[])
{
/* Declare and initialize variables */
int hands = atoi(argv[HANDSINPUT]); //How many players
int cards = atoi(argv[CARDSINPUT]); //How many cards per hand
struct card deck[DECKSIZE]; //The deck is an array of cards structures
struct card allHands[hands][cards];
//Builds the deck
//Shuffles deck with a RNG and swapping every card
int players;
int cardCount;
int passCard = 0;
dealHands(deck, allHands, hands, cards);
}
Recibo las 2 siguientes declaraciones durante la compilación
advertencia: pasar el argumento 2 de ''dealHands'' del tipo de puntero incompatible [habilitado por defecto] dealHands (mazo, allHands, manos, cartas); ^
nota: se esperaba ''struct card **'' pero el argumento es del tipo ''struct card ( ) [(sizetype) (cards)]'' void dealHands (struct card [], struct card [], int, int); ^
Siempre me equivoco cuando se trata de punteros y matrices cuando necesito llamarlos en una función. Así que no estoy seguro de dónde falla mi lógica. ¿Dónde paso la dirección en lugar del valor o viceversa?
Lo más importante al pasar matrices como argumentos de función es: no se puede pasar una matriz a / desde una función .
Dicho eso, lea lo siguiente con mucho cuidado.
(Usaré
int
por simplicidad, pero, por supuesto, también puedes usar otros tipos).
Pero puede pasar un "puntero al primer elemento" de una matriz.
Afortunadamente, C realiza la conversión automáticamente.
Aún más, para todas menos tres excepciones (
sizeof
,
_Alignof
,
&
operadores), C convierte el nombre de una matriz automáticamente en dicho puntero.
Esto a menudo se llama "la matriz se
desintegra
en un puntero al primer elemento".
Pero esta descomposición no es recursiva. Entonces, si pasa una matriz 2D a una función, se desintegra a un puntero a una matriz 1D:
int a[1][2]; // 1 = outer dimension, 2 = inner
cuando se pasa a una función
void f(int a[1][2]);
se convierte
int (*a)[2] // pointer to array of inner dimension
Alternativamente, uno puede usar explícitamente la sintaxis del puntero
void f(int (*a)[2]);
El tipo de
a
es
int (*)[2]
para todos los casos.
¡Cuidado con los paréntesis!
La sintaxis que usa es básicamente una preferencia personal.
Prefiero la sintaxis de matriz con todas las dimensiones, porque eso documenta la intención más claramente.
Siempre debe pasar todos los tamaños, excepto la dimensión más externa. Eso es solo para documentación y no es obligatorio (consulte a continuación para ver un ejemplo).
Dentro de la función, utiliza el operador de índice normal:
int t, i; // index variable for ouTer, Inner
a[t][i];
Tenga en cuenta que esto se puede aplicar a matrices de dimensiones superiores. Para la matriz 1D, esto también se aplica, en realidad. Simplemente elimine la dimensión interna:
int a[1];
decae a
int *a;
(Acabo de usar las constantes
1
y
2
para numerar las dimensiones; por supuesto, puede usar las dimensiones que desee).
Si desea pasar una matriz con longitud variable (VLA, matriz de longitud variable), debe pasar a la función todos menos la dimensión más externa:
f(int inner, a[][inner]);
Pero mejor para verificar, etc. es pasar todas las dimensiones:
f(int outer, int inner, a[outer][inner]);
Todo esto puede ser un poco difícil de entender, pero es bastante fácil una vez que experimentas con él. Verá, nunca puede pasar una matriz completa como argumento (quiero decir que podría hacerlo, pasando cada elemento, pero ese no es el punto). Una matriz es básicamente una especie de tabla. Si es 1D, tienes una línea de cajas. Si es 2D, tienes una tabla de cajas. Si es 3D, tiene un cachorro (e / oid) de cajas. Sin embargo, lo que podría hacer es explotar cómo se presentan los números en la memoria y utilizar la aritmética de puntero. Es bastante simple.
OK vamos-
Digamos que tenemos una función, set_up_array, que toma un puntero a una matriz 2D como parámetro.
void set_up_array(int **array, int row_size, int column_size){
for(int i = 0; i < row_size; i++){
for(int j = 0; j < column_size; j++){
*((int*)array + i*row_size + j) = i + j + k;
}
}
}
Eso podría hacerte enloquecer, pero quédate conmigo aquí, ¿está bien?
Ahora, imagine la matriz 2D que está pasando como una tabla.
Tiene filas, y luego tiene columnas.
¿Cómo irías al siguiente elemento en una tabla así?
Bueno, tienes el índice de tu elemento y lo descubres, ¿verdad?
Eso es exactamente lo que estamos haciendo aquí.
Comenzaré explicando la razón por la que estamos encasillando la matriz a int *.
Es bastante simple.
Cada vez que hacemos cálculos de punteros, el compilador de C intenta facilitar nuestro trabajo (como un brote real ...), por lo que en lugar de agregar la dirección a los punteros, simplemente agregamos el número de elementos y, en función de eso, el C El compilador determinará automáticamente la dirección que queremos.
Ahora, aquí está el problema, el compilador de C se da cuenta descubriendo el tamaño del tipo al que apunta el puntero.
Entonces, para simplificar nuestras vidas y también para hacer feliz al compilador de C, lo convertimos en int *, lo que significa que, de aquí en adelante, lo que agreguemos se agregará a la dirección inicial como lo haría con int * s.
Ahora volvamos a la analogía de la tabla.
Conocemos el número de fila y el número de columna.
Una cosa que puede tener en cuenta es que esta imagen tiene las etiquetas de columna y fila invertidas
Para hacer nuestras vidas aún más simples, pasemos a una vista cartesiana (una vista gráfica, con una coordenada x y ay).
Digamos que x es horizontal, mientras que y es vertical.
Entonces podemos escribir el arrray como
array[y][x]
Lo que significa que el elemento que queremos es el elemento
x*row_size + y
.
Lo que básicamente podemos agregar al puntero en nuestra función, y desreferenciarlo, como se hizo, justo allí, usamos i y j.