¿Se puede añadir una funcion a string.h?

Iniciado por mester, 24 Diciembre 2015, 19:02 PM

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

mester

Hola.

Resulta que he hecho una función que considero bastante útil para el uso popular:

void strssr(const char *arg /*Argumento que contiene los numeros*/,
            char *s /*Puntero a since */,
             char *t /*Puntero a to */,
              uint8_t lim /*Limite de separacion */)
{
  char *str = (char *)arg;
  while(*str)
  {
    *s = *str++;
    if(*str == lim)
      break;
    *s++;
  }
  *str++;
  while(*str)
  {
    *t = *str++;
    *t++;
  }
}


Consiste en separar un argumento en dos a partir de una señal definida en el cuatro argumento, por ejemplo:

int main()
{
   char *ip = (char *)calloc(16,sizeof(char));
   char *puerto = (char *)calloc(5,sizeof(char));
   strssr("192.168.1.1:8080", ip, puerto, ':');
   printf("%s\t%s\n", ip, puerto);
return 0;
}


Me gustaría saber si hay alguien que regule todo esto de las bibliotecas en C. ¿Tal vez el opengroup.org?
Es por el bien de la comunidad jeje.

Gracias por las respuestas.
Justicia es dar a cada uno lo que se merece

ivancea96

Ten en cuenta que existe la función strtok.

A parte, en esa función das por hecho que el segundo y tercer argumento estarán llenos de caracteres nulos.
Además, utilizas como límite uint8_t. ¿Por qué? Son char*, no uint8_t*, tenlo en cuenta.
Luego, ¿qué ocurre si no encuentra el delimitador? Sin comprobar nada, incrementas el puntero, y empiezas a leer memoria que tal vez no te pertenezca.

Hicise la función pensando en el mejor de los casos. Piensa también en el peor de los casos (en cualqueira de ellos).

Las funciones de la librería estándar hacen exactamente lo que dicen. ¿Qué ocurriría si metieras esa función en la librería?

Está bien que quieras compartir tu librería, pero en ese caso, te recomendaría que publicases en, por ejemplo, github.

mester

Cita de: ivancea96 en 24 Diciembre 2015, 19:54 PM
Ten en cuenta que existe la función strtok.

A parte, en esa función das por hecho que el segundo y tercer argumento estarán llenos de caracteres nulos.
Además, utilizas como límite uint8_t. ¿Por qué? Son char*, no uint8_t*, tenlo en cuenta.
Luego, ¿qué ocurre si no encuentra el delimitador? Sin comprobar nada, incrementas el puntero, y empiezas a leer memoria que tal vez no te pertenezca.

Hicise la función pensando en el mejor de los casos. Piensa también en el peor de los casos (en cualqueira de ellos).

Las funciones de la librería estándar hacen exactamente lo que dicen. ¿Qué ocurriría si metieras esa función en la librería?

Está bien que quieras compartir tu librería, pero en ese caso, te recomendaría que publicases en, por ejemplo, github.
Si, ya he visto la función strtok, pero me parece más complicada de usar.

El while(*str) comprueba que str no sea '\0'.
Lo de uint8_t supongo que tienes razón, usaré un char.
Justicia es dar a cada uno lo que se merece

ivancea96

#3
Cita de: nonpromisc en 24 Diciembre 2015, 20:15 PM
El while(*str) comprueba que str no sea '\0'.

Pero eso no soluciona ninguno de los problemas.

En la línea *str++;. Incrementas sin comprobar si llegaste a un caracter nulo. No sabes si saliste del bucle por caracter nulo, o si saliste por haber encontrado el delimitador.
Y a todo esto, no necesita el *str++.

mester

#4
Cita de: ivancea96 en 24 Diciembre 2015, 20:21 PM
Pero eso no soluciona ninguno de los problemas.

En la línea *str++;. Incrementas sin comprobar si llegaste a un caracter nulo. No sabes si saliste del bucle por caracter nulo, o si saliste por haber encontrado el delimitador.
Y a todo esto, no necesita el *str++.

Si no incremento *str++ la segunda cadena es :8080 en vez de 8080 y si llega a carácter nulo no entrará en el segundo while, es decir, que se queda con la primera cadena.


int strssr(const char *arg /*Argumento que contiene los numeros*/,
             char *s /*Puntero a since */,
              char *t /*Puntero a to */,
               char lim /*Limite de separacion */)
{
   if(s == NULL||t == NULL)
     return 1;
   char *str = (char *)arg;
   while(*str)
   {
     *s = *str++;
     if(*str == lim)
       break;
     *s++;
   }
   *str++;
   while(*str)
   {
     *t = *str++;
     *t++;
   }
return 0;
}


¿Así? Compruebo los argumentos, a excepción de lim, que es cosa del usuario, digo yo.
Justicia es dar a cada uno lo que se merece

ivancea96

¿Qué ocurre si el primer while sale por el conducto ordinario? (*str == 0)
Pues que se acabó la cadena y no s eha encontrado el delimitador.
Sin embargo, ignoras esa posibilidad, incrementas str, y te posiciones fuera de la cadena. Desde ahí, todo lo que hagas, puede dar lugar a error y es inesperado para el programador final.

E insisto, para incrementar un puntero, str++. El * sobra.

mester

#6
Cita de: ivancea96 en 24 Diciembre 2015, 21:09 PM
¿Qué ocurre si el primer while sale por el conducto ordinario? (*str == 0)
Pues que se acabó la cadena y no s eha encontrado el delimitador.
Sin embargo, ignoras esa posibilidad, incrementas str, y te posiciones fuera de la cadena. Desde ahí, todo lo que hagas, puede dar lugar a error y es inesperado para el programador final.

E insisto, para incrementar un puntero, str++. El * sobra.

El compilador no me permite incrementar el puntero con str++. No sé si lo que me dices será en C++.
Y no sé, yo considero que así va bien. Lo pruebo con todas las posibilidades haciendo NULL todo y no devuelve violacion de segmento, para mí esto ya esta xd
El codigo ha quedado así:

int strssr(const char *arg /*Argumento que contiene los numeros*/,
             char *s /*Puntero a since */,
              char *t /*Puntero a to */,
               char lim /*Limite de separacion */)
{
   if(arg == NULL || s == NULL || t == NULL)
     return 1;
   char *str = (char *)arg;
   while(*str)
   {
     *s = *str++;
     if(*str == lim)
       break;
     *s++;
   }
   *str++;
   while(*str)
   {
     *t = *str++;
     *t++;
   }
return 0;
}


¿Alguna recomendación o mejora?

Gracias
Justicia es dar a cada uno lo que se merece

MAFUS

Muy buenas.

Pues hay unos cuantos bugs.
Línea 14, 16 y 20: debes cambiar la forma con que haces el incremento. No te interesa el valor que hay guardado en el puntero, solo incrementarlo. Eso es cambiar *var++ por var++.

Por otra parte cuándo la cadena original no tiene separador, el separador es el primer carácter, o hay pocos caracteres en la cadena apuntada por s hay basura en las cadenas s y t.

mester

#8
Cita de: MAFUS en 25 Diciembre 2015, 01:23 AM
Muy buenas.

Pues hay unos cuantos bugs.
Línea 14, 16 y 20: debes cambiar la forma con que haces el incremento. No te interesa el valor que hay guardado en el puntero, solo incrementarlo. Eso es cambiar *var++ por var++.

Por otra parte cuándo la cadena original no tiene separador, el separador es el primer carácter, o hay pocos caracteres en la cadena apuntada por s hay basura en las cadenas s y t.

¿Qué diferencia hay entre *s++ y s++? Creo que en la primera incrementas la posición de la memoria en la que se encuentra *s, pero en la segunda no sé que haces.

¿Que os parece así? :D

int strssr(const char *arg /*Argumento que contiene los numeros*/,
            char *s /*Puntero a since */,
             char *t /*Puntero a to */,
              char lim /*Limite de separacion */)
{
  if(arg == NULL||s == NULL||t==NULL)
    return 1;
  char *str = (char *)arg;
  while(*str && (*s++ = *str) && !(*++str eq lim));
  while(*str && (*t++ = *++str));
}


Más resumido todo.
Justicia es dar a cada uno lo que se merece

MAFUS

Cuándo a un puntero le antepones el asterisco (*) le estas diciendo al compilador que quieres obtener el valor que guarda.
Para incrementar el valor de la posición apuntada basta usar el operador de incremento (++).
Por eso, como en susodichas líneas no haces uso del valor devuelto por el puntero, algunos compiladores lanzaran alertas informando de ello.