
usuario1506919
Soy relativamente nuevo en C y necesito ayuda con los métodos que se ocupan de las 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 matrices cuando los 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 retorno 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 he probado esto porque mi compilador de C no funciona en este momento, pero me gustaría resolverlo.
El tratamiento de C de las matrices es muy diferente al de Java, y tendrá que ajustar su forma de pensar en consecuencia. Las matrices en C no son objetos de primera clase (es decir, una expresión de matriz no conserva su “condición de matriz” en la mayoría de los contextos). En C, una expresión de tipo “arreglo de elementos N de T
” se convertirá implícitamente (“decay”) en una expresión de tipo “puntero a T
“, excepto cuando la expresión de matriz es un operando de la sizeof
o unario &
operadores, o si 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 en realidad recibe un tipo de puntero:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
en la llamada a foo
la expresion str
se convierte de tipo char [6]
para char *
por lo que el primer parámetro de foo
se declara char *a
en vez de char a[6]
. En sizeof str
ya que la expresión de matriz es un operando de la sizeof
operador, no se convierte en un tipo de puntero, por lo que obtiene la cantidad de bytes en la matriz (6).
Si tu eres De Verdad interesado, puede leer el libro de Dennis Ritchie El desarrollo del lenguaje C para entender de dónde viene 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 escribir en ella:
void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
...
dstArray[i] = some_value_derived_from(srcArray[i]);
...
}
int main(void)
{
char src[] = "This is a test";
char dst[sizeof src];
...
returnArray(src, sizeof src, dst, sizeof dst);
...
}
Otro método es que la función asigne la matriz dinámicamente y devuelva el puntero y el tamaño:
char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
char *dstArray = malloc(srcSize);
if (dstArray)
{
*dstSize = srcSize;
...
}
return dstArray;
}
int main(void)
{
char src[] = "This is a test";
char *dst;
size_t dstSize;
dst = returnArray(src, sizeof src, &dstSize);
...
free(dst);
...
}
En este caso, la persona que llama es responsable de desasignar la matriz con el free
función de biblioteca.
Tenga en cuenta que dst
en el código anterior hay un puntero simple a char
no un puntero a una matriz de char
. 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 matriz o tipo de puntero; ambas cosas src[i]
y dst[i]
accederá a la i
‘th elemento de la matriz (aunque sólo src
tiene tipo de matriz).
Tú puede declarar un puntero a una matriz de N elementos de T
y hacer algo similar:
char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
if (dstArr)
{
...
(*dstArr)[i] = ...;
...
}
return dstArr;
}
int main(void)
{
char src[] = "This is a test";
char (*dst)[SOME_SIZE];
...
dst = returnArray(src, sizeof src);
...
printf("%c", (*dst)[j]);
...
}
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 eliminar la referencia del puntero antes de aplicar el subíndice, lo que desordena el código. Los punteros a arreglos funcionan mejor cuando se trata de arreglos multidimensionales.

Mengo
Puede hacerlo usando la memoria del montón (a través de malloc() invocación) como otras respuestas informadas aquí, pero siempre debe administrar la memoria (usar gratis() función cada vez que llame a su función). También puedes hacerlo con una matriz estática:
char* returnArrayPointer()
{
static char array[SIZE];
// do something in your array here
return array;
}
Puede usarlo sin preocuparse por la administración de la memoria.
int main()
{
char* myArray = returnArrayPointer();
/* use your array here */
/* don't worry to free memory here */
}
En este ejemplo, debe usar la palabra clave estática en la definición de la matriz para establecer la vida útil de la matriz durante toda la aplicación, de modo que no se destruya después de la declaración de devolución. Por supuesto, de esta manera ocupa SIZE bytes en su memoria durante toda la vida útil de la aplicación, ¡así que dimensione correctamente!
En su caso, está creando una matriz en la pila y una vez que abandone el alcance de la función, la matriz se desasignará. En su lugar, cree una matriz asignada dinámicamente y devuélvale un puntero.
char * returnArray(char *arr, int size) {
char *new_arr = malloc(sizeof(char) * size);
for(int i = 0; i < size; ++i) {
new_arr[i] = arr[i];
}
return new_arr;
}
int main() {
char arr[7]= {1,0,0,0,0,1,1};
char *new_arr = returnArray(arr, 7);
// don't forget to free the memory after you're done with the array
free(new_arr);
}

Snaipe
¿Qué tal esta implementación deliciosamente malvada?
matriz.h
#define IMPORT_ARRAY(TYPE) \
\
struct TYPE##Array { \
TYPE* contents; \
size_t size; \
}; \
\
struct TYPE##Array new_##TYPE##Array() { \
struct TYPE##Array a; \
a.contents = NULL; \
a.size = 0; \
return a; \
} \
\
void array_add(struct TYPE##Array* o, TYPE value) { \
TYPE* a = malloc((o->size + 1) * sizeof(TYPE)); \
TYPE i; \
for(i = 0; i < o->size; ++i) { \
a[i] = o->contents[i]; \
} \
++(o->size); \
a[o->size - 1] = value; \
free(o->contents); \
o->contents = a; \
} \
void array_destroy(struct TYPE##Array* o) { \
free(o->contents); \
} \
TYPE* array_begin(struct TYPE##Array* o) { \
return o->contents; \
} \
TYPE* array_end(struct TYPE##Array* o) { \
return o->contents + o->size; \
}
C Principal
#include <stdlib.h>
#include "array.h"
IMPORT_ARRAY(int);
struct intArray return_an_array() {
struct intArray a;
a = new_intArray();
array_add(&a, 1);
array_add(&a, 2);
array_add(&a, 3);
return a;
}
int main() {
struct intArray a;
int* it;
int* begin;
int* end;
a = return_an_array();
begin = array_begin(&a);
end = array_end(&a);
for(it = begin; it != end; ++it) {
printf("%d ", *it);
}
array_destroy(&a);
getchar();
return 0;
}
¿La matriz de retorno tiene un tamaño conocido como se indica en su ejemplo de código? El único otro problema que veo además de los problemas de pila mencionados en las respuestas es que si su matriz de retorno tiene un tamaño indeterminado, dada la forma en que funcionan los punteros/matrices en C, no sabrá qué tan grande es.
– extraño mundo libre
25 de julio de 2012 a las 18:56
Sí, sé el tamaño de la matriz entrante en todo momento. El tamaño de la matriz de entrada y salida no cambiará.
– usuario1506919
25 de julio de 2012 a las 19:01
El desarrollo del lenguaje C* – bell-labs.com/usr/dmr/www/chist.html
– x4444
31 de diciembre de 2017 a las 7:45