Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - DvNe

#1
Tu problema esta en que los parámetros en Java se pasan por valor, es decir el parámetro que recibe la función es una copia del parámetro real y los cambios que se efectúan dentro de la función no afectan al parámetro real.

Hay lenguajes de programación que permiten el paso de parámetros por referencia, aquí los cambios que se realicen sobre el parámetro se verán reflejados en el parámetro real.

Una forma de eludir un poco esta restricción de Java se presenta en esta web, échale un vistazo a ver si te ayuda.

http://lineadecodigo.com/java/parametros-por-referencia-en-java/
#2
Java / Diferenciar USBs en uso
18 Noviembre 2015, 18:03 PM
Buenas,

Estoy realizando un proyecto en Java con el que necesito saber qué USB está siendo usado, me explico:

Estoy programando en un portátil que tiene 3 entradas USB:

  • USB 3.0
  • USB 2.0
  • USB 2.0
Y por otro lado, tengo un escaner de huella dactilar que se conecta por USB.

He estado mirando la librería jUSB pero esta necesita instalar un driver para poder usarla así que la he descartado.
Luego he estado indagando sobre la librería usb4java y he visto sus ejemplos. Copiando y pegando he preparado este pequeño código:

Código (java) [Seleccionar]

package pruebausb;

import org.usb4java.Context;
import org.usb4java.Device;
import org.usb4java.DeviceDescriptor;
import org.usb4java.DeviceList;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;

public class PruebaUSB {

    public static void main(String[] args) {
          // Create the libusb context
        Context context = new Context();

        // Initialize the libusb context
        int result = LibUsb.init(context);
        if (result < 0)
            throw new LibUsbException("Unable to initialize libusb", result);
       
        // Read the USB device list
        DeviceList list = new DeviceList();
        result = LibUsb.getDeviceList(context, list);
        if (result < 0)
            throw new LibUsbException("Unable to get device list", result);
       
        try {
            // Iterate over all devices and list them
            for (Device device: list) {
                               
                DeviceDescriptor descriptor = new DeviceDescriptor();
                result = LibUsb.getDeviceDescriptor(device, descriptor);
                if (result < 0)
                    throw new LibUsbException("Unable to read device descriptor", result);               
                System.out.println(descriptor.dump());
            }
        } finally {
            // Ensure the allocated device list is freed
            LibUsb.freeDeviceList(list, true);
        }

        // Deinitialize the libusb context
        LibUsb.exit(context);
    }
}


Y al ejecutarlo me aparece esto:

Device Descriptor:
  bLength                 18
  bDescriptorType          1
  bcdUSB                0.00
  bDeviceClass             0 Per Interface
  bDeviceSubClass          0
  bDeviceProtocol          0
  bMaxPacketSize0          0
  idVendor            0x1022
  idProduct           0x7809
  bcdDevice             0.00
  iManufacturer            0
  iProduct                 0
  iSerial                  0
  bNumConfigurations       1

Device Descriptor:
  bLength                 18
  bDescriptorType          1
  bcdUSB                0.00
  bDeviceClass             0 Per Interface
  bDeviceSubClass          0
  bDeviceProtocol          0
  bMaxPacketSize0          0
  idVendor            0x1022
  idProduct           0x7807
  bcdDevice             0.00
  iManufacturer            0
  iProduct                 0
  iSerial                  0
  bNumConfigurations       1

Device Descriptor:
  bLength                 18
  bDescriptorType          1
  bcdUSB                0.00
  bDeviceClass             0 Per Interface
  bDeviceSubClass          0
  bDeviceProtocol          0
  bMaxPacketSize0          0
  idVendor            0x1022
  idProduct           0x7807
  bcdDevice             0.00
  iManufacturer            0
  iProduct                 0
  iSerial                  0
  bNumConfigurations       1

Device Descriptor:
  bLength                 18
  bDescriptorType          1
  bcdUSB                0.00
  bDeviceClass             0 Per Interface
  bDeviceSubClass          0
  bDeviceProtocol          0
  bMaxPacketSize0          0
  idVendor            0x1022
  idProduct           0x7808
  bcdDevice             0.00
  iManufacturer            0
  iProduct                 0
  iSerial                  0
  bNumConfigurations       1

Device Descriptor:
  bLength                 18
  bDescriptorType          1
  bcdUSB                0.00
  bDeviceClass             0 Per Interface
  bDeviceSubClass          0
  bDeviceProtocol          0
  bMaxPacketSize0          0
  idVendor            0x1022
  idProduct           0x7808
  bcdDevice             0.00
  iManufacturer            0
  iProduct                 0
  iSerial                  0
  bNumConfigurations       1

Device Descriptor:
  bLength                 18
  bDescriptorType          1
  bcdUSB                2.00
  bDeviceClass           239 Unknown
  bDeviceSubClass          2
  bDeviceProtocol          1
  bMaxPacketSize0         64
  idVendor            0x04f2
  idProduct           0xb3b1
  bcdDevice            57.16
  iManufacturer            3
  iProduct                 1
  iSerial                  2
  bNumConfigurations       1

Por esto deduzco que usb4java no soporta USB 3.0 (no se si estoy en lo cierto), pero lo que me confunde es que deberían aparecer bcdUSB con valor 2.00 (que creo que es la versión del puerto USB si estoy en lo cierto).

Necesito saber si hay alguna forma de darle a cada puerto USB un nombre estilo COM1, COM2, etc. para distinguir cuándo conecto el escaner de huella dactilar a un USB u otro.
#3
Java / UrU 4500 o UrU5000 fingerprint scanner
7 Octubre 2015, 19:14 PM
Buenas,

Estoy realizando un proyecto en Java y necesito comprar un detector de huellas dactilares. Me decidido a comprar el UrU 4500 de DigitalPerson pero cuando he comenzado a buscar dónde comprarlo comparando precios me he encontrado con que existe un modelo llamado UrU 5000 que es mas fácil de adquirir.

¿Alguien sabe las diferencias entre ambos modelos?
#4
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  :(

#5
Programación C/C++ / Problema con remove_if
8 Abril 2014, 17:48 PM
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
#6
Programación C/C++ / Re: unary_negate
8 Abril 2014, 17:46 PM
Ya lo resolví tenias razón muchas gracias
#7
Programación C/C++ / Re: unary_negate
7 Abril 2014, 23:49 PM
Algo estoy haciendo mal porque ahora me sale este fallo:

In file included from /usr/include/c++/4.6/string:50:0,
                 from /usr/include/c++/4.6/bits/locale_classes.h:42,
                 from /usr/include/c++/4.6/bits/ios_base.h:43,
                 from /usr/include/c++/4.6/ios:43,
                 from /usr/include/c++/4.6/ostream:40,
                 from /usr/include/c++/4.6/iostream:40,
                 from prueba.cpp:1:
/usr/include/c++/4.6/bits/stl_function.h: En la instanciación de 'std::unary_negate<bool>':
prueba.cpp:36:38:   instanciado desde aquí
/usr/include/c++/4.6/bits/stl_function.h:352:11: error: 'bool' no es de tipo clase, struct o union
/usr/include/c++/4.6/bits/stl_function.h:363:7: error: 'bool' no es de tipo clase, struct o union
In file included from /usr/include/c++/4.6/algorithm:63:0,
                 from prueba.cpp:4:
/usr/include/c++/4.6/bits/stl_algo.h: En la función '_RandomAccessIterator std::__find_if(_RandomAccessIterator, _RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [con _RandomAccessIterator = char*, _Predicate = std::unary_negate<bool> (*)(EsDigito)]':
/usr/include/c++/4.6/bits/stl_algo.h:4427:41:   instanciado desde '_IIter std::find_if(_IIter, _IIter, _Predicate) [con _IIter = char*, _Predicate = std::unary_negate<bool> (*)(EsDigito)]'
prueba.cpp:36:38:   instanciado desde aquí
/usr/include/c++/4.6/bits/stl_algo.h:210:4: error: no se puede convertir '* __first' de 'char' a 'EsDigito'
/usr/include/c++/4.6/bits/stl_algo.h:214:4: error: no se puede convertir '* __first' de 'char' a 'EsDigito'
/usr/include/c++/4.6/bits/stl_algo.h:218:4: error: no se puede convertir '* __first' de 'char' a 'EsDigito'
/usr/include/c++/4.6/bits/stl_algo.h:222:4: error: no se puede convertir '* __first' de 'char' a 'EsDigito'
/usr/include/c++/4.6/bits/stl_algo.h:230:4: error: no se puede convertir '* __first' de 'char' a 'EsDigito'
/usr/include/c++/4.6/bits/stl_algo.h:234:4: error: no se puede convertir '* __first' de 'char' a 'EsDigito'
/usr/include/c++/4.6/bits/stl_algo.h:238:4: error: no se puede convertir '* __first' de 'char' a 'EsDigito'
#8
Programación C/C++ / Re: unary_negate
7 Abril 2014, 23:31 PM
Entonces debería definir la clase como

class EsDigito {
public:
bool operator() (const char& c) const { return isdigit(c); }
typedef char argument_type;
};

y la llamada a la función sería find_if(inicio,fin,EsAlfabetico) ?
#9
Programación C/C++ / unary_negate
7 Abril 2014, 22:53 PM
Buenas estoy escribiendo la siguiente funcion


Código (c++) [Seleccionar]

#include <iostream>
#include <cstring>
#include <functional>
#include <algorithm>

using namespace std;

class EsDigito {
public:
bool operator() (const char& c) const { return isdigit(c); }
};

int main() {
unary_negate<bool> EsAlfabetico (EsDigito);

char letras2[] = " 452485A56321";
inicio = letras;
fin = letras + sizeof(letras)/sizeof(char);

if (find_if(inicio,fin,EsAlfabetico()))

   cout << "Alfabetico" << endl;

  return 0;

}




Cuando compilo me sale el siguiente error:

prueba.cpp:35:39: error: faltan argumentos para la función 'std::unary_negate<bool> EsAlfabetico(EsDigito)'
prueba.cpp:30:22: nota: se declara aquí

Alguien me puede explicar el por qué


 

#10
A ver ya encontré solución a mi problema pondré todos los ficheros de mi problema ya que hace falta conocer todas las clases para ver el por qué de algunas cosas que apuntas eferion.

CLASE USUARIO JUNTO CON SU IMPLEMENTACION

Código (cpp) [Seleccionar]
#ifndef _USUARIO_H_
#define _USUARIO_H_

#include "articulo.h"
#include "tarjeta.h"

#include <istream>
#include <map>
#include <set>
using std::map;
using std::set;

class Tarjeta;

#include "cadena.h"

class Clave {
public:
  enum Razon {CORTA, ERROR_CRYPT};
 
  class Incorrecta {
  public:
    Incorrecta (const Razon& r) : razon_(r) {}
    Razon razon() const { return razon_; }
  private:
    Razon razon_;
  };
  Clave (const char*) throw (Clave::Incorrecta);

  Cadena clave() const { return pass_cifrada; }
  bool verifica (const char*);
private:
  Cadena pass_cifrada;
};

class Usuario {
public:
  //CONSTRUCTOR Y DESTRUCTOR
  Usuario (const Cadena&, const Cadena&, const Cadena&, const Cadena&, const Clave&);
  ~Usuario();
 
  class Id_duplicado {
  public:
    Id_duplicado (const Cadena& id) : id_duplicado(id) {}
    const Cadena idd() const { return id_duplicado; }
  private:
    const Cadena id_duplicado;
  };
  //FUNCIONES OBSERVADORAS
  Cadena id() const { return identificador_; }
  Cadena nombre() const { return nombre_; }
  Cadena apellidos() const { return apellidos_; }
  Cadena direccion() const { return direccion_; }


  //FUNCIONES CON TARJETAS
  typedef map<Numero, Tarjeta*> Tarjetas;
  void es_titular_de(Tarjeta&);
  void no_es_titular_de(Tarjeta&);
  const Tarjetas& tarjetas() const { return tarjetas_; }

 
  //FUNCIONES CON LOS ARTICULOS
  typedef map<Articulo*, unsigned> Articulos;
  void compra(Articulo& articulo, unsigned cant = 1);
  const Articulos& compra() const { return articulos_; }
  size_t n_articulos() const { return articulos_.size(); }

  //SOBRECARGA OPERADOR
  friend std::ostream& operator << (std::ostream&, const Usuario&);
 
private:
  Cadena identificador_;
  Cadena nombre_;
  Cadena apellidos_;
  Cadena direccion_;
  Clave password_;
  Tarjetas tarjetas_;
  Articulos articulos_;

  Cadena password() const { return password_.clave(); }
  static set<Cadena> identificadores;
  bool IdValido() const throw(Usuario::Id_duplicado);
  Usuario (const Usuario&); //Deshabilitamos la copia de un usuario
};

std::ostream& mostrar_carro(std::ostream&, const Usuario&);
#endif


Código (cpp) [Seleccionar]
#include "usuario.h"
#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdlib>
#include <unistd.h>

using namespace std;

Clave::Clave (const char* pass_no_cifrada) throw (Clave::Incorrecta) {
  if (strlen(pass_no_cifrada) < 5)
    throw(Incorrecta(CORTA));

  srand(time(0));
  const char* const validos = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  const char salto[2] = {validos[rand() % 63], validos[rand() % 63]};
  if (crypt(pass_no_cifrada,salto) == NULL)
    throw(Incorrecta(ERROR_CRYPT));

  pass_cifrada = crypt(pass_no_cifrada,salto);
}

bool Clave::verifica(const char* pass) {
  return (strcmp(pass_cifrada.c_str(), crypt(pass,pass_cifrada.c_str())) == 0);
}

set<Cadena> Usuario::identificadores;

Usuario::Usuario (const Cadena& identificador, const Cadena& nombre, const Cadena& apellidos, const Cadena& direccion, const Clave& pass) : identificador_(identificador), nombre_( nombre), apellidos_(apellidos), direccion_(direccion), password_(pass) {
  IdValido();
}

Usuario::~Usuario() {
  for (Usuario::Tarjetas::iterator i = tarjetas_.begin(); i != tarjetas_.end(); ++i)
    (*(*i).second).anula_titular();
  identificadores.erase(id());
}

bool Usuario::IdValido() const throw(Usuario::Id_duplicado) {
  pair<set<Cadena>::iterator,bool> i;

  i = identificadores.insert(id());
  if (i.second == false) {
    throw(Id_duplicado(id()));
    return false;
  } else {
    return true;
  }
}

ostream& operator << (ostream& output, const Usuario& user) {
  output <<"\n" << user.id() << " [" << user.password() << "] " << user.nombre() << " "
<< user.apellidos() << "\n" << user.direccion() << "\nTarjetas:\n";
  for (Usuario::Tarjetas::const_iterator i = user.tarjetas().begin(); i != user.tarjetas().end(); ++i)
    output << *(*i).second << "\n";
  return output;
}

void Usuario::compra (Articulo& articulo, unsigned cant) {
  if (cant == 0)
    articulos_.erase(&articulo);
  else {
    if (articulos_.find(&articulo) != articulos_.end())
      articulos_.erase(&articulo);
      articulos_.insert(pair<Articulo*,unsigned>(&articulo,cant));
    }
}

ostream& mostrar_carro(ostream& output, const Usuario& user) {

  output << "Carrito de compra de " << user.id() << " [Articulos: "
       << user.n_articulos() << "]\n Cant. Articulo\n================="
       << "=========================================\n";
  for (Usuario::Articulos::const_iterator  p = user.compra().begin(); p != user.compra().end(); p++)
    output << setfill(' ') << setw(4) <<  p->second << setw(4) << *p->first << "\n";
  return output;
}

void Usuario::es_titular_de(Tarjeta& t) {
  tarjetas_.insert(pair<Numero, Tarjeta*>(t.numero(),&t));
}

void Usuario::no_es_titular_de(Tarjeta& t) {
  tarjetas_.erase(t.numero());
}


CLASE TARJETA Y SU IMPLEMENTACION

Código (cpp) [Seleccionar]
#ifndef _TARJETA_H_
#define _TARJETA_H_

#include "cadena.h"
#include "fecha.h"

class Usuario;

class Numero : public Cadena {
public:
  enum Razon {LONGITUD,DIGITOS,NO_VALIDO};

  class Incorrecto {
  public:
    Incorrecto (const Razon& r) { razon_ = r; }
    Razon razon() const { return razon_; }
  private:
    Razon razon_;
  };

  Numero (const Cadena&) throw (Numero::Incorrecto);
  operator const char*() const {return numero_.c_str(); }
 
private:
  Cadena numero_;
  static const unsigned LongitudMinima = 13;
  static const unsigned LongitudMaxima = 19;
  bool numeroValido() const ;
};

bool operator < (const Numero&, const Numero&);

class Tarjeta {
public:
  class Caducada {
  public:
    Caducada (const Fecha& f) : fecha_(f) {}
    Fecha cuando() const { return fecha_; }
  private:
    Fecha fecha_;
  };
  Tarjeta (const Numero&, const Usuario&, const Fecha&) throw (Tarjeta::Caducada);
  ~Tarjeta();

  Numero numero() const { return numero_; }
  Fecha caducidad() const { return caducidad_; }
  Cadena titular_facial() const { return titular_; }
  const Usuario* titular() const { return user_; }
  void anula_titular() { user_ = 0; }

  friend std::ostream& operator << (std::ostream&, const Tarjeta&);
private:
  Numero numero_;
  const Usuario* user_;
  Fecha caducidad_;
  Cadena titular_;


};

bool operator < (const Tarjeta&, const Tarjeta&);
#endif


Código (cpp) [Seleccionar]
#include "tarjeta.h"
#include "usuario.h"
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <iomanip>

using namespace std;

Tarjeta::Tarjeta (const Numero& n, const Usuario& user, const Fecha& f) throw (Tarjeta::Caducada) : numero_(n), user_(&user), caducidad_(f) {
 
  titular_ = user.nombre() + " " +  user.apellidos();
 
  Fecha f_actual;
  if (caducidad_ <  f_actual) {
    throw(Tarjeta::Caducada(caducidad_));return;
  }
  const_cast<Usuario&>(user).es_titular_de(*this);
}

Tarjeta::~Tarjeta() {
  Usuario* u = const_cast<Usuario*>(user_);
  if (u)
    u->no_es_titular_de(*this);
}


std::ostream& operator << (std::ostream& output, const Tarjeta& t) {
  output << "\n  " << (const char*) t.numero() << "\n  " << t.titular_facial()
<< "\n  Caduca: " << setfill('0') << setw(2) << t.caducidad().mes()
<< "/" << setw(2) << (t.caducidad().anno() % 100);
  return output;
}

Numero::Numero (const Cadena& numero) throw (Numero::Incorrecto) {
  unsigned i = 0, j = 0, pos = 0;

  do {
    pos = i;
    while (i < numero.longitud() && numero[i] != ' ') {
      if (isalpha(numero[i]))
throw(Incorrecto(DIGITOS));
      j++; i++;
    }
    numero_ += numero.subcadena(pos,j);
    j = 0;
    while (i < numero.longitud() && numero[i] == ' ') { i++; }
  } while (i < numero.longitud());

  if (numero_.longitud() < LongitudMinima || numero_.longitud() > LongitudMaxima)
    throw(Incorrecto(LONGITUD));
  if (!numeroValido())
    throw(Incorrecto(NO_VALIDO));
}

bool Numero::numeroValido() const { //Algoritmo de Lhun
  int suma = 0;
  bool impar = true;

  for (int i = numero_.longitud() - 1; i >= 0; i--) {
    if (!impar) {
      int tmp = (numero_[i] - '0') << 1; //Multiplicamos por 2 si es impar
      suma += (tmp >= 10) ? tmp - 9 : tmp;
    } else
      suma += (numero_[i] - '0');
    impar = !impar;
  }
  return (suma % 10) ? false : true;
}

bool operator < (const Numero& numero1, const Numero& numero2) {
  return atoll(numero1) < atoll(numero2);
}

bool operator < (const Tarjeta& t1, const Tarjeta& t2) {
  return t1.numero() < t2.numero();
}

std::ostream& operator << (std::ostream& output, const Numero& num) {
  output << (const char*) num;
  return output;
}


CLASE ARTICULO Y SU IMPLEMENTACION

Código (cpp) [Seleccionar]
#ifndef _ARTICULO_H_
#define _ARTICULO_H_

#include "cadena.h"
#include "fecha.h"

class Articulo {
public:
  Articulo (const Cadena&, const Cadena&, const Fecha&, const double&, const unsigned&);

  Cadena referencia() const { return codigo_Referencia; }
  Cadena titulo() const { return titulo_; }
  Fecha f_publi() const { return publicacion_; }
  double precio() const { return precio_; }
  unsigned stock() const { return ejemplares_; }

  double& precio() { return precio_; }
  unsigned& stock() { return ejemplares_; }

  friend std::ostream& operator << (std::ostream&, const Articulo&);
private:
  Cadena codigo_Referencia;
  Cadena titulo_;
  Fecha publicacion_;
  double precio_;
  unsigned ejemplares_;
};#endif


Código (cpp) [Seleccionar]
#include "articulo.h"
#include <iomanip>

using namespace std;

Articulo::Articulo (const Cadena& ref, const Cadena& title, const Fecha& fecha, const double& price, const unsigned& numero) : codigo_Referencia(ref), titulo_(title), publicacion_(fecha), precio_(price), ejemplares_(numero) {}

ostream& operator << (ostream& output, const Articulo& art) {
  output << "[" << art.referencia() << "] \"" << art.titulo() << "\", " << art.f_publi().anno() << ". " << setprecision(2) << setfill('0') << fixed << art.precio()
<< "\xE2\x82\xAC";
  return output;
}


Ahora bien la razón por la que el proyecto tiene esta implementación, es porque es un trabajo para la universidad.