Consulta sobre punteros y memoria dinámica

Iniciado por ing_maipu, 12 Octubre 2017, 22:13 PM

0 Miembros y 1 Visitante están viendo este tema.

ing_maipu

Hola! Estoy intentando implementar una función en C que me arme una trama (cadena de caracteres) que luego será mandada a través de un canal de comunicación.

Para esto, primero tengo que crear la trama, la cual está compuesta de sus respectivos encabezados, campos de información, indicadores de fin de trama y finalmente el checksum.

Mi problema es que la longitud de la trama (cantidad de caracteres que poseerá) nunca será fija. Esto es, dependiendo de la trama que deseo enviar, varía la longitud de la misma, ya que ni la cantidad de campos es fija, ni la cantidad de caracteres lo es.

Para esto, se me ocurrió que podía hacer una función cuya declaración sea la siguiente:

char *armar_trama(char **campos, int cant_campos);//Funcion que devuelve una trama ya armada lista para enviar.


En donde **campos vendría a ser un vector de <cant_campos> cadenas de caracteres, en donde cada una de estas es de longitud distinta. Cada uno de estas cadenas representará un campo disitinto.

La idea es que la función concatene cada uno de estos campos dentro de una misma cadenas de caracteres y luego esta cadena de caracteres (trama) sea devuelta por la función.

Mi pregunta es: ¿Es necesario pedir memoria dinámica cada vez que concateno un campo dentro de la cadena de caracteres (trama) que será devuelta?

Muchas gracias por su ayuda

Gallu

Si la "trama"(cadena de caracteres) es un puntero a char es seguro que necesitas reservar memoria para incluir todo lo que deseas incluir en ella, si es un array de char pues deberás inicializarlo también.

Yo lo que haría es crear una estructura que represente la trama que quiero devolver, algo como:


struct Trama{
   char  * headers;
   char  * info;
   char  * indicators;
   char *checksum;
};


Luego en la función debes calcular la longitud de cada uno de los elementos de la trama para reservar la memoria necesaria que deberás reservar.

Espero haberme explicado y que te sirva.

Saludos
Nadie alcanza la meta con un solo intento, ni perfecciona la vida con una sola rectificación, ni alcanza altura con un solo vuelo.

ing_maipu

Muchas gracias por tu respuesta Didacso.

Había pensado en hacer algo de ese tipo pero sucede que la función que me envía las tramas al canal de comunicación recibe únicamente variables del tipo char*. Por esta razón estaba necesitando una función que me devuelva la trama como cadena de caracteres.

Sucede que para ese puntero doble que recibirá la función (char **campos), ya habré pedido memoria dinámica.

Entonces el procedimiento dentro de mi función consistirá en volver a pedir memoria dinámica y liberar la que ya habia pedido cuando creé el puntero doble?

Saludos

Gallu

#3
Entiendo que el puntero doble lo creas tú, correcto  ??

lo que te proponía es algo asi:


char * getData(Trama trama){
   int sizeofheader = sizeOf(trama->header);
    int sizeofInfo = ...
..


   char * data = malloc(sizeofheader  + sizeofInfo  ); etc etc

   //luego tienes que copiar los diferentes valores de los campos de la trama en tu puntero de char

   return data;
}


En resumen calculas el tamaño de cada uno de los campos de tu Trama y luego  reservas la memoria necesaria para poder copiar toda la información en el puntero de char que la función devolverá.

Saludos
Nadie alcanza la meta con un solo intento, ni perfecciona la vida con una sola rectificación, ni alcanza altura con un solo vuelo.

Gallu

Hola, estaba aburrido y decidí escribir una implementación de lo comentado, espero te sirva.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
char * headers;
char * info;
char * checksum;
}Trama;


char * dataFromTrama(Trama * trama);
char checksum(char* s);
 

int main(int argc, char **argv)
{
char* header = "the header";
char* info = "the info";


Trama * trama = (Trama *) malloc(sizeof(Trama));
(*trama).headers = (char *) malloc(sizeof(header));
(*trama).info = (char *) malloc(sizeof(info));

strcpy((*trama).headers, header);
strcpy((*trama).info, info);

char * result = dataFromTrama(trama);

printf ("%s\n" , result );

return 0;

}


char * dataFromTrama(Trama * trama){

char* tmpData;

int sizeTotal = sizeof((*trama).headers) + sizeof((*trama).info) + sizeof(char);

tmpData = (char *) malloc(sizeTotal);

memset(tmpData, '\0', sizeTotal);

strcpy(tmpData, (*trama).headers);

strcat(tmpData , (*trama).info);

char checksumdata = checksum(tmpData);

printf ("Checksum %d \n" , checksumdata );

tmpData = strcat(tmpData , &checksumdata);

return tmpData;
}

 
char checksum(char* s){
signed char sum = -1;
while (*s != 0) {
sum += *s;
s++;
}
return sum;
}

Nadie alcanza la meta con un solo intento, ni perfecciona la vida con una sola rectificación, ni alcanza altura con un solo vuelo.

ing_maipu

Hola Gallu

Muchas gracias por tu respuesta. La misma me ha sido de gran ayuda para la implementación puesto que he hecho algo similar. La unica diferencia es que los campos los guardo en una  una matriz de cantidad de columnas variable (i.e, puntero doble) para así poder poner correctamente los separadores de campos cuando corresponda.

Saludos