[C] Funcion Split

Iniciado por mr.blood, 28 Marzo 2013, 14:46 PM

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

mr.blood

Espero que a alguien le sirva. Yo no he visto fallos, si los encontrais, comentadlos por favor.

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

int len_palabra(char *cadena, int inicio, char separador);
char **split(char *cadena, char separador);

int main()
{
char cadena[]="MrBlood.split.crea.funcion";
int i;
char **retorno=split(cadena, '.');
for(i=0;retorno[i]!=NULL;i++)
{
printf("%s\n", retorno[i]);
free(retorno[i]);
}
free(retorno);
return 0;
}

int len_palabra(char *cadena, int inicio, char separador)
{
int len=0, i=inicio;
while(cadena[i]!=separador&&cadena[i]!='\0')
{
len++;
i++;
}
return len;
}

char **split(char *cadena, char separador)
{
int num_palabras=1, len_cadena=strlen(cadena), i, j=1, *inicios;
for(i=0;i<len_cadena;i++)
{
if(cadena[i]==separador)
{
num_palabras++;
}
}
inicios=malloc(sizeof(int)*num_palabras);
inicios[0]=0;
for(i=1;i<len_cadena;i++)
{
if(cadena[i]==separador)
{
inicios[j]=i+1;
j++;
}
}
char **retorno=malloc(sizeof(char *)*num_palabras+1);
retorno[num_palabras]=NULL;
for(i=0;i<num_palabras;i++)
{
j=len_palabra(cadena, inicios[i], separador);
retorno[i]=(char *)malloc(sizeof(char)*j);
strncpy(retorno[i], &cadena[inicios[i]], j);
retorno[i][j]='\0';
}
free(inicios);
return retorno;
}


Sa1uDoS

EDITO: Ahora se libera la memoria reservada con malloc.

naderST

Esta bien pero recuerda que debes hacerle free a cada palabra y luego al retorno porque estas dejando memory leaks. Otra cosa, sería interesante que el delimitador pudiera ser un string. Aquí te dejo una que hice yo, pero en C++ mucho más sencillo utilizando la clase string y vector:

http://gauss.com.ve/articulos/articulo.php?id=10

mr.blood

En realidad aunque es una buena costumbre usar free, el SO se encarga de liberar la memoria reservada cuando el proceso termina ;). Aun asi deberia mejorar eso.

Sa1uDoS

naderST

Cita de: mr.blood en 28 Marzo 2013, 16:34 PM
En realidad aunque es una buena costumbre usar free, el SO se encarga de liberar la memoria reservada cuando el proceso termina ;). Aun asi deberia mejorar eso.

Sa1uDoS

Sí, pero que tal si mi proceso es un servidor que va a correr durante meses usando esa función split cada vez que recibe alguna petición? En cierto punto va a reventar. Fuera de eso, muy bueno el aporte.

durasno

Y para molestar un poco mas faltaria comprobar q malloc asigne memoria correctamente


Saludos
Ahorrate una pregunta, lee el man

rir3760

Cita de: mr.blood en 28 Marzo 2013, 14:46 PMEspero que a alguien le sirva. Yo no he visto fallos, si los encontrais, comentadlos por favor.
Algunos comentarios:

* Para tener acceso al prototipo de malloc es mejor, en lugar de <malloc.h>, incluir <stdlib.h> ya que este ultimo es parte de la biblioteca estándar de C.

* Cuando reservas memoria para cada parte de la cadena debes utilizar "j + 1", el elemento adicional es para almacenar ahí el '\0'.

* En lugar de copiar la cadena y a continuación almacenar manualmente el '\0':
strncpy(retorno[i], &cadena[inicios[i]], j);
retorno[i][j] = '\0';

Puedes realizar los dos pasos con sprintf:
sprintf(retorno[i], "%.*s", j, cadena + inicios[i]);

* En la función "len_palabra" puedes obtener el numero de caracteres utilizando solo una variable local, de esta forma:
int len_palabra(char *cadena, int inicio, char separador)
{
   int i = inicio;
   
   while (cadena[i] != separador && cadena[i] != '\0')
      i++;
   
   return i - inicio;
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

mr.blood

La funcion len_palabra puedo eliminarla y aprovechar el for donde busco los inicios, pero muy buen apunte. Luego cambio todo esto.
Lo del sprintf ni se me ocurrio.

Gracias a todos por los comentarios, en especial a @rir3760. Luego lo cambio y edito.

Sa1uDoS