Cortar Cadena [slice]

Iniciado por bash, 29 Septiembre 2016, 23:28 PM

0 Miembros y 2 Visitantes están viendo este tema.

bash

Buenas A tod@s en el foro , tengo una duda media boba e interesante he estado viendo varias libreria para manejo de cadenas o mejor dicho un par porque necesito una funcion para cambiar el tamano de una cadena (claro eliminando caracteres ) lamentablemente no encontre ninguna que haga esto eficientemente o que requiera de alguna otra libreria y entonces por esa razon decidi crear una pequena libreria en parte me ha funcionadod correctamente , pero tengo un inconveniente creando una funcion que recorte un mi cadea desde algun punto especifico que pertenezca  a ella misma obviamente, quizas se el manejo de memoria. la verdad tengo un par de dias en esto y ya no encuentro como hacer esta funcion , posteare el codigo para recibir su recomendacion para ver si me pueden hechar una mano o algun consejo.


Código (cpp) [Seleccionar]
ini String::CutString(int beg, int end)
{
Dbg(__FUNCTION__, __LINE__, "");
   if(this->szChars == NULL)
    return 0;
if(this->inlen < end || this->inlen < beg)
return 0;

int   inLen         = 0;
char *szBeg         = NULL;
char *szEnd         = NULL;
char *szCharsCopy   = NULL;


szBeg       = (char *)calloc(inlen, sizeof(char ));
szEnd       = (char *)calloc(inlen, sizeof(char ));
szCharsCopy = (char *)calloc(inlen, sizeof(char ));


strncpy( szBeg, &this->szChars[0], beg);
strncpy( szEnd, &this->szChars[end], inlen);
// memcpy( szBeg, &this->szChars[0], beg);
// memcpy( szEnd, &this->szChars[end], inlen);


strncat( szCharsCopy, szBeg , strlen(szBeg));
strncat( szCharsCopy , szEnd, strlen(szEnd));

free (this->szChars);
this->szChars = NULL;

   inLen = strlen(szCharsCopy);
this->szChars = (char *)calloc(inLen + 1, sizeof(char ));
strncat( this->szChars , szCharsCopy, inLen );
this->szChars[inLen + 1] = NULL;

if(szBeg)
 free(szBeg);
if(szEnd)
 free(szEnd);
if(szCharsCopy)
 free(szCharsCopy);
if(this->szChars)
   return strlen(this->szChars);
else
 return 0;
}
gracias por responder mis dudas

MAFUS

No entendí que querías hacer.

ivancea96

Cita de: bash en 29 Septiembre 2016, 23:28 PM
lamentablemente no encontre ninguna que haga esto eficientemente

Si estás en C++, la clase string tiene el método substr.
Además, la librería algorithm de la librería estándar también, tiene funciones para manejar contenedores (string incluido).


A parte:

- Pusiste de retorno de la función ini.
- (char *)calloc(inlen, sizeof(char ));: inlen es 0. Quizás quisieras decir this->inlen.
- strncpy( szEnd, &this->szChars[end], inlen);: si lo que querías decir ahí era this->inlen, ten en cuenta que vas a copiar caracteres fuera del rango, y probablemente, de la memoria de tu cadena.
Luego, yo cambiaría calloc y strncpy por malloc y memcpy, poniendo posteriormente el caracter nulo al final de las cadenas. Ya a tu gusto.
Y bueno, estás reservando memoria 4 veces. Puedes hacer esta función reservando memoria solo 1 vez (o ninguna si reutilizas la memoria que ya había, dejando que sobre espacio). Además, coges memoria de un tamaño excesivo.

La cadena tendrá 3 partes:
--- A ---|beg| --- B --- |end| --- C ---
Deberías reservar solo memoria de tamaño A + C + 1 (caracter nulo). Con eso, te llegará.

bash

#3
primero que todo gracias por las respuestas !!!

@Mafus : lo que quiero hacer es lo siguiente , te muestro con un ejemplo
Código (cpp) [Seleccionar]

 
char *cadena = "esta cadena  especial";

CutString(cadena, 5, 12);

cadena == "esta especial"



es decir elimine de la cadena los caracteres del 5 al 12 claro mi funcion esta dentro de una clase por eso uso this.


@ivancea96 estoy usando c++ pero lo que estoy haciendo es creando una clase "String" ademas como explique arriba quiero eliminarlo del string actual no deseo devolverlo, de hecho la funcion es de tipo int(edite mal esa parte cuand postea ) , cierto debi verificar que inlen sea diferente de "0" pero como siempre la estuve probando con una longitud mayor de 0 no me di cuenta de eso.


Código (cpp) [Seleccionar]

szBeg           = (char *)malloc(beg * sizeof(char ));
szEnd           = (char *)malloc(( inlen - end )* sizeof(char ));
szCharsCopy = (char *)malloc((beg + (inlen - end) + 1)* sizeof(char ));


///strncpy( szBeg, &this->szChars[0], beg);
///strncpy( szEnd, &this->szChars[end], inlen);
memcpy( szBeg, &this->szChars[0], beg);
       memcpy( szEnd, &this->szChars[end], inlen - end);


strncat( szCharsCopy, szBeg , strlen(szBeg));
strncat( szCharsCopy , szEnd, strlen(szEnd));
       szChasrsCopy[beg + (inlen - end))+1] = '\0';




dices algo asi ?
como me recomiendas tomar espacio una sola vez ?

gracias de nuevo por todo ;-) :laugh:

EDIT:


He mejorado el codigo , me gustaria saber su opinion acerca de este.

Código (cpp) [Seleccionar]

char * CutString(char *Chars, int beg_, int end_)
{
char *beg = (char *)malloc( beg_ * sizeof(char) );
char *end = (char *)malloc( (strlen(Chars) - end_) * sizeof(char) );

cout << beg_<<endl;
cout << end_<<endl;
memcpy(beg, &Chars[0], beg_);

if(( strlen(Chars)- end_) != 0)
    memcpy(end, &Chars[end_], strlen(Chars)-end_);
    else
        return beg;

    char *ret = (char *)malloc(((strlen(beg)+ strlen(end)) + 1 )*sizeof(char));

    if(ret == NULL)
    cout << "error buscando memoria\n";

    strcat(ret, beg);
    strcat(ret, end);

    ret[(strlen(beg)+ strlen(end))] = '\0';
    free(beg);
    free(end);
    return ret;
}




anteriormente le pasaba un arreglo gigante digas 20kb y la app terminaba con algun error en malloc pero ahora anda bien , pero me gustaria saber que opinan.


gracias por responder mis dudas

ivancea96

Lo dicho, solo deberías hacer 1 malloc.
Y bueno, ahora que me fijo, siendo C++, deberías poner new en vez de malloc.
Código (cpp) [Seleccionar]
cadenaFinal = new char[this.inlen - end + beg + 1]
Y ahí, copias directamente lo que necesitas.
Código (cpp) [Seleccionar]
memcpy(cadenaFinal, cadenaInicial, beg);
memcpy(cadenaFinal+beg, cadenaInicial+end, this.inlen - end);
cadenaFinal[this.inlen - end + beg] = '\0';



Todo unido:
Código (cpp) [Seleccionar]
#include <iostream>
#include <cstdlib>
#include <cstring>

using namespace std;

int main(){
const char* cadenaInicial = "hola que tal estas";
int lenght = strlen(cadenaInicial);
int beg = 5,
end = 13;
char* cadenaFinal = new char[lenght - end + beg + 1];

memcpy(cadenaFinal, cadenaInicial, beg);
memcpy(cadenaFinal+beg, cadenaInicial+end, lenght - end);
cadenaFinal[lenght - end + beg] = '\0';

cout << cadenaFinal << endl;
}

bash

#5
hey es cierto .... waaoooo donde se fue mi logica , :D , la verdad es asi que deberia de ser. gracias.



ahora bien me encuentro en la necesidad de mutar el "string"


por ejemplo
Código (cpp) [Seleccionar]

/*
    @function :CutStr
    @param    :
    @author(s) : bash &  ivancea96(staff elhacker.net)
    @descripcion : Esta funcion corta una parte de la cadena pasada szChar
                         mandatorio: szChars debe ser creada usando new
*/
void CutStr(int beg, int end , char **szChars)
{
       int lenght = strlen(szCharsl);
char* cadenaFinal = new char[lenght - end + beg + 1];
memcpy(cadenaFinal, szChars, beg);
memcpy(cadenaFinal+beg, szChars+end, lenght - end);
cadenaFinal[lenght - end + beg] = '\0';

        ////aqui es mi duda.
        delete [] *szChars;
        *szChars = NULL;
        *szChars = new char[lenght - end + beg + 1];
        memcpy(*szChars, cadenaFinal, (lenght - end + beg));
      ////
       delete []cadenaFinal;
       cadenaFinal = NULL;
}




En esta parte del codigo me tira un bad_alloc y a veces solo sale pero me imagino que es por lo mismo.




Código (cpp) [Seleccionar]


int main()
{
    char *test = new char[32];
    memcpy(test, "hola que tal", 12);
    CutStr(0,  4,  *test);
    ///...
    delete[] test;
}






quizas mi codigo esta mal ,pero estoy haciendo esto para arm-11 en thumb mode. solo en caso de que le paresca extrano la pregunta. :D

gracias de antemano.
gracias por responder mis dudas