Soy relativamente nuevo en C y necesito ayuda con los métodos que tratan con matrices. Viniendo de la programación Java, estoy acostumbrado a poder decir int [] method()
para devolver una matriz. Sin embargo, descubrí que con C tienes que usar punteros para las matrices cuando las devuelves. Siendo un nuevo programador, realmente no entiendo esto en absoluto, incluso con los muchos foros que he revisado.
Básicamente, estoy tratando de escribir un método que devuelva una matriz de caracteres en C. Proporcionaré el método (llamémoslo returnArray) con una matriz. Creará una nueva matriz a partir de la matriz anterior y le devolverá un puntero. Solo necesito ayuda sobre cómo comenzar esto y cómo leer el puntero una vez que se envía fuera de la matriz. Cualquier ayuda para explicar esto es apreciada.
Formato de código propuesto para la función de devolución de matriz
char *returnArray(char array []){
char returned [10];
//methods to pull values from array, interpret them, and then create new array
return &(returned[0]); //is this correct?
}
Llamador de la función
int main(){
int i=0;
char array []={1,0,0,0,0,1,1};
char arrayCount=0;
char* returnedArray = returnArray(&arrayCount); ///is this correct?
for (i=0; i<10;i++)
printf(%d, ",", returnedArray[i]); //is this correctly formatted?
}
Todavía no lo he probado, ya que mi compilador de C no funciona en este momento, pero me gustaría resolverlo
Respuestas:
No puede devolver matrices de funciones en C. Tampoco puede (no debería) hacer esto:
returned
se crea con una duración de almacenamiento automática y las referencias a él serán inválidas una vez que deje su alcance de declaración, es decir, cuando regrese la función.Deberá asignar dinámicamente la memoria dentro de la función o llenar un búfer preasignado proporcionado por la persona que llama.
Opción 1:
Asignar dinámicamente la memoria dentro de la función (persona que llama responsable de desasignar
ret
)Llámalo así:
Opcion 2:
llenar un búfer preasignado proporcionado por la persona que llama (la persona que llama asigna
buf
y pasa a la función)Y llámalo así:
fuente
El tratamiento de C de las matrices es muy diferente al de Java, y tendrá que ajustar su pensamiento en consecuencia. Las matrices en C no son objetos de primera clase (es decir, una expresión de matriz no retiene su "matriz" en la mayoría de los contextos). En C, una expresión de tipo "matriz de elementos N de
T
" se convertirá implícitamente ("decaimiento") en una expresión de tipo "puntero aT
", excepto cuando la expresión de matriz sea un operando de los operadoressizeof
unarios&
, o si el La expresión de matriz es un literal de cadena que se utiliza para inicializar otra matriz en una declaración.Entre otras cosas, esto significa que no puede pasar una expresión de matriz a una función y recibirla como un tipo de matriz ; la función realmente recibe un tipo de puntero:
En la llamada a
foo
, la expresiónstr
se convierte de tipochar [6]
achar *
, razón por la cualfoo
se declara el primer parámetro de enchar *a
lugar dechar a[6]
. Ensizeof str
, dado que la expresión de matriz es un operando delsizeof
operador, no se convierte en un tipo de puntero, por lo que obtiene el número de bytes en la matriz (6).Si está realmente interesado, puede leer El desarrollo del lenguaje C de Dennis Ritchie para comprender de dónde proviene este tratamiento.
El resultado es que las funciones no pueden devolver tipos de matriz, lo cual está bien ya que las expresiones de matriz tampoco pueden ser el objetivo de una asignación.
El método más seguro es que la persona que llama defina la matriz y pase su dirección y tamaño a la función que se supone que debe escribirle:
Otro método es que la función asigne la matriz dinámicamente y devuelva el puntero y el tamaño:
En este caso, la persona que llama es responsable de desasignar la matriz con la
free
función de biblioteca.Tenga
dst
en cuenta que en el código anterior hay un puntero simple achar
, no un puntero a una matriz dechar
. La semántica de puntero y matriz de C es tal que puede aplicar el operador de subíndice[]
a una expresión de tipo de matriz o tipo de puntero; ambossrc[i]
ydst[i]
accederá ali
elemento 'th de la matriz (aunque solosrc
tenga un tipo de matriz).Usted puede declarar un puntero a una matriz de n elementos de
T
y hacer algo similar:Varios inconvenientes con lo anterior. En primer lugar, las versiones anteriores de C esperan
SOME_SIZE
ser una constante de tiempo de compilación, lo que significa que la función solo funcionará con un tamaño de matriz. En segundo lugar, debe desreferenciar el puntero antes de aplicar el subíndice, que satura el código. Los punteros a matrices funcionan mejor cuando se trata de matrices multidimensionales.fuente
bar
recibe es un puntero, no una matriz. En el contexto de una declaración de parámetro de función,T a[N]
yT a[]
ambos se tratan comoT *a
.void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
último parámetro debe estar en elsize_t
tipo nochar
.No estoy diciendo que esta sea la mejor solución o una solución preferida para el problema dado. Sin embargo, puede ser útil recordar que las funciones pueden devolver estructuras. Aunque las funciones no pueden devolver matrices, las matrices pueden envolverse en estructuras y la función puede devolver la estructura llevando así la matriz consigo. Esto funciona para matrices de longitud fija.
Invito comentarios sobre las fortalezas y debilidades de esta técnica. No me he molestado en hacerlo.
fuente
CHAR_ARRAY returned
en el montón? Ciertamente no puede en la pila (en el marco de la pila de lareturnArray()
derecha?¿Qué tal esta implementación deliciosamente malvada?
array.h
C Principal
fuente
struct
como un contenedor / objeto de matriz. Piense en ello como un C ++ std :: vector. El preprocesador expandiría laint
versión de esto astruct intArray { int* contents; int size; };
.En su caso, está creando una matriz en la pila y una vez que abandona el alcance de la función, la matriz se desasignará. En su lugar, cree una matriz asignada dinámicamente y devuélvale un puntero.
fuente
new
operador en C. Eso es C ++.sizeof(char)
está garantizado que lo será1
, por lo que en este caso puede soltar ese bitmalloc
.&arr
. Quieresarr
ser unchar *
y pasarlo usandoarr
.Puede hacerlo utilizando la memoria de almacenamiento dinámico (a través de la invocación malloc () ) como otras respuestas informadas aquí, pero siempre debe administrar la memoria (use la función free () cada vez que llame a su función). También puedes hacerlo con una matriz estática:
Puede usarlo sin preocuparse por la administración de la memoria.
En este ejemplo, debe usar una palabra clave estática en la definición de matriz para establecer en toda la aplicación la vida útil de la matriz, por lo que no se destruirá después de la declaración de devolución. Por supuesto, de esta manera usted ocupa TAMAÑO de bytes en su memoria durante toda la vida de la aplicación, ¡así que dimensione correctamente!
fuente
Su método devolverá una variable de pila local que fallará gravemente. Para devolver una matriz, cree una fuera de la función, pásela por dirección en la función, luego modifíquela o cree una matriz en el montón y devuelva esa variable. Ambos funcionarán, pero el primero no requiere ninguna asignación de memoria dinámica para que funcione correctamente.
fuente
Puedes usar un código como este:
Cuando haga esto, la memoria debería liberarse más tarde, pasando la dirección a libre.
Hay otras opciones Una rutina puede devolver un puntero a una matriz (o parte de una matriz) que es parte de alguna estructura existente. La persona que llama puede pasar una matriz, y la rutina simplemente escribe en la matriz, en lugar de asignar espacio para una nueva matriz.
fuente