Problema con remove_if

Iniciado por DvNe, 8 Abril 2014, 17:48 PM

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

DvNe

Buenas, estoy intentando usar la función remove_if para eliminar espacios en blanco de una cadena de caracteres de bajo nivel. He aquí la función que he diseñado:

Código (cpp) [Seleccionar]
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <string>
using namespace std;

class EsBlanco {
public:
  bool operator() (const char& c) const { return std::isspace(c); }
};

int main() {
  string s = "4539 4512 0398 7356";
  char *letras = new char [s.length() + 1];
  strcpy (letras, s.c_str());
 
  char * inicio = letras;
  char * fin = letras + s.length();
 
  fin = std::remove_if(inicio,fin,EsBlanco());
 
  for (char * p = inicio; p != fin; ++p)
     cout  << *p;
  return 0;
}


El problema que ocurre es que elimina los 3 espacios en blanco que hay en el string pero el numero resultante es: 4539451203987356356

Creo que se vuelven a repetir los 3 últimos números porque se eliminaron los otros 3 huecos de los espacios. Alguien podría guiarme para encontrar una solución

amchacon

#1
No hace falta crear una clase para eso. Puedes hacerlo en una función directamente (Y para un char no hace falta una referencia):
Código (cpp) [Seleccionar]
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <string>
using namespace std;

bool EsBlanco(const char c)
{
    return std::isspace(c);
}

int main()
{
    string s = "4539 4512 0398 7356";
    char *letras = new char [s.length() + 1];
    strcpy (letras, s.c_str());

    char * inicio = letras;
    char * fin = letras + s.length();

    fin = std::remove_if(inicio,fin,EsBlanco);

    for (char * p = inicio; p != fin; ++p)
        cout  << *p;
    return 0;
}


En cuanto al error, a mí me imprime el resultado correcto :huh:

De todas formas no entiendo porque usas char*. Con lo facil que sería hacerlo en el mismo string:
Código (cpp) [Seleccionar]
string s = "4539 4512 0398 7356";
remove_if(s.begin(),s.end(),EsBlanco);

cout<<s<<endl;
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

DvNe

A ver el caso es que en realidad no estoy usando strings, estoy usando una clase (hecha por mi) que emula el comportamiento de string en ciertos aspectos, he aquí su implementación:

Código (cpp) [Seleccionar]
#ifndef _CADENA_
#define _CADENA_
#include <iostream>
#include <stdexcept>

class Cadena {
public:
  explicit Cadena (const size_t longitud = 0, const char cadena = ' ');
  Cadena (const Cadena& );
  Cadena (const char* );

  ~Cadena() {delete[] cadena_;}

  size_t longitud() const {return longitud_ - 1;}
  char* c_str() const {return cadena_;}

  Cadena& operator = (const char*);
  Cadena& operator = (const Cadena&);
  Cadena& operator += (const Cadena&);

  char operator [] (int pos) const {return cadena_[pos];}
  char& operator [] (int pos) {return cadena_[pos];}
  char at(size_t) const throw (std::out_of_range);
  char& at(size_t) throw (std::out_of_range);

  //  operator char*() const {return (*this).cadena_str();}
  Cadena subcadena (int, int) const throw(std::out_of_range);
 
  friend std::ostream& operator << (std::ostream&, const Cadena&);
  friend std::istream& operator >> (std::istream&, Cadena&);
private:
  char *cadena_;
  size_t longitud_;
};

Cadena operator + (const Cadena&, const Cadena&);


bool operator == (const Cadena&, const Cadena&);
bool operator != (const Cadena&, const Cadena&);
bool operator < (const Cadena&, const Cadena&);
bool operator <= (const Cadena&, const Cadena&);
bool operator > (const Cadena&, const Cadena&);
bool operator >= (const Cadena&, const Cadena&);
#endif


Código (cpp) [Seleccionar]
#include <iostream>
#include <cstring>
#include <stdexcept>

#include "cadena.h"

using namespace std;

Cadena::Cadena (const size_t longitud, const char caracter) : longitud_(longitud+1) {
  cadena_ = new char[longitud_];
  for (size_t i = 0; i < longitud; ++i)
    cadena_[i] = caracter;
  cadena_[longitud] = '\0';
}

Cadena::Cadena (const Cadena &cadena1) : longitud_(cadena1.longitud() + 1){
  cadena_ = new char[longitud_];
  strcpy(cadena_,cadena1.c_str());
}

Cadena::Cadena (const char *cadena) : longitud_(strlen(cadena) + 1){
  cadena_ = new char[longitud_];
  strcpy(cadena_,cadena);
}

Cadena& Cadena::operator = (const char* cadena) {
  longitud_ = strlen(cadena) + 1;
  cadena_ = new char[longitud_];
  strcpy(cadena_,cadena);
  return (*this);
}

Cadena& Cadena::operator = (const Cadena &cadena1) {
  if (this != &cadena1) {
    delete[] cadena_;
    if (cadena1.c_str()) {
      longitud_ = cadena1.longitud() + 1;
      cadena_ = new char[longitud_];
      strcpy(cadena_,cadena1.c_str());
    }
    else
      cadena_ = NULL;
  }
  return (*this);
}

Cadena& Cadena::operator += (const Cadena &cadena1) {
  Cadena cadena2 (longitud() + cadena1.longitud());
  strcpy(cadena2.cadena_,cadena_);
  strcat(cadena2.cadena_,cadena1.cadena_);
  (*this) = cadena2;
  return (*this);
}

char Cadena::at(size_t pos) const throw(std::out_of_range) {
  if (pos < 0 || pos > longitud())
    throw (std::out_of_range("Posicion fuera de rango"));
  else if ((*this)[pos] == 0)
    throw (std::out_of_range("Posicion inexistente"));
  else
    return (*this)[pos];
}

char& Cadena::at(size_t pos) throw(std::out_of_range) {
  if (pos < 0 || pos > longitud())
    throw (std::out_of_range("Posicion fuera de rango"));
  else if ((*this)[pos] == 0)
    throw (std::out_of_range("Posicion inexistente"));
  else
    return (*this)[pos];
}

Cadena operator + (const Cadena &cad1, const Cadena &cad2) {
  Cadena aux(cad1);
  aux += cad2;
  return aux;
}
/* Tam_i no puede ser negativo */
Cadena Cadena::subcadena (int pos_i, int tam_i) const  throw(std::out_of_range) {
  if ((size_t) pos_i < 0 || (size_t) pos_i > longitud() - 1)
    throw (std::out_of_range("Posicion inicial fuera de rango"));

  if (tam_i < 0 || (size_t) pos_i + tam_i > longitud())
    throw (std::out_of_range("Posicion fuera de rango"));

  Cadena cadena (tam_i);
  size_t i = 0;
  for (size_t k = pos_i; k < (size_t) tam_i + pos_i; k++) {
    cadena.at(i) = at(k);
    i++;
  }
  return cadena;
}
/**
* strcmp(x,y)
* Si x == y return 0;
* Si x <  y return -1;
* Si x >  y return 1;
*/

bool operator == (const Cadena &cad1, const Cadena &cad2) {
  return !(strcmp(cad1.c_str(),cad2.c_str()));
}

bool operator != (const Cadena &cad1, const Cadena &cad2) {
  return !(cad1 == cad2);
}

bool operator < (const Cadena &cad1, const Cadena &cad2) {
  if (strcmp(cad1.c_str(),cad2.c_str()) >= 0)
    return false;
  return true;
}

bool operator <= (const Cadena &cad1, const Cadena &cad2) {
  return cad1 < cad2 || cad1 == cad2;
}

bool operator > (const Cadena &cad1, const Cadena &cad2) {
  if (strcmp(cad1.c_str(),cad2.c_str()) <= 0)
    return false;
  return true;
}

bool operator >= (const Cadena &cad1, const Cadena &cad2) {
  return cad1 > cad2 || cad1 == cad2;
}

ostream& operator << (ostream &output, const Cadena &c) {
  output << c.c_str();
  return output;
}

istream& operator >> (istream &input, Cadena &c) {
  char* entrada = new char[32];
  entrada[0] = '\0';
  input.width(32);
  input >> entrada;
 
  c = entrada;
  delete[] entrada;
  return input;
}


Por tanto, realmente, la variable s sería de tipo CADENA y como esta clase no es tan potente como la string no puedo hacer lo de s.begin() ni s.end().

Ahora bien te puedes preguntar, por qué no uso string y me dejo de líos? Porque es un proyecto para la universidad y tengo prohibido usar esa clase en el proyecto  :(


amchacon

#3
Pues revisalo porque he vuelto a copypastear tu código y me lo hace bien :huh:

De hecho, incluso lo he hecho con strings y he comparado salidas. Son identicas:
Código (cpp) [Seleccionar]
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <string>
using namespace std;

class EsBlanco
{
public:
   bool operator() (const char& c) const
   {
       return std::isspace(c);
   }
};

int main()
{
   string s = "4539 4512 0398 7356";
   string b = s;

   char *letras = new char [s.length() + 1];
   strcpy (letras, s.c_str());

   char * inicio = letras;
   char * fin = letras + s.length();

   fin = std::remove_if(inicio,fin,EsBlanco()); // metodo por char*
   b = string(s.begin(),std::remove_if(s.begin(),s.end(),EsBlanco())); // metodo por strings

   *fin = 0; // caracter nulo

   string a = inicio;

   if (a == b) cout<<"Funciono!"<<endl;
   else cout<<"No funciono! :("<<endl;

   cout<<b<<endl;
   for (char * p = inicio; p != fin; ++p)
       cout  << *p;
   return 0;
}


Ambos metodos me generan la misma salida. No consigo generar tu error...
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar