C++ String Class Implementation: Cadena.hpp and Cadena.cpp
Posted on Jan 28, 2025 in Other university degrees and diplomas
C++ String Class Implementation: Cadena
cadena.hpp
#ifndef CADENA_HPP_
#define CADENA_HPP_
#include <iostream>
#include <cstring>
#include <stdexcept>
#include <cctype>
#include <iterator>
class Cadena {
private:
static char vacia[1];
size_t tam_;
char* s_;
public:
// Constructors
explicit Cadena(int t = 0, char s = ' ');
Cadena(const char* c);
Cadena(const Cadena& c);
Cadena(Cadena&& c);
// Operator Overloading
Cadena& operator=(const Cadena& c);
Cadena& operator=(Cadena&& c);
Cadena& operator=(const char*);
explicit operator const char*() const noexcept;
Cadena& operator+=(const Cadena& c);
char& operator[](const size_t a);
const char& operator[](const size_t a) const;
// Accessors
inline size_t length() const noexcept { return tam_; }
const char& at(int i) const;
char& at(int i);
Cadena substr(int indice, int size) const;
// Iterators
typedef char* iterator;
typedef const char* const_iterator;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
// Iterator Functions
inline iterator begin() noexcept { return s_; }
inline const_iterator begin() const noexcept { return const_iterator(s_); }
inline iterator end() noexcept { return s_ + tam_; }
inline const_iterator end() const noexcept { return const_iterator(s_ + tam_); }
inline const_iterator cbegin() const noexcept { return const_iterator(s_); }
inline const_iterator cend() const noexcept { return const_iterator(s_ + tam_); }
inline reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
inline const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
inline reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
inline const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
inline const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
inline const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
// Destructor
~Cadena();
};
// External Operator Overloads
Cadena operator+(const Cadena& c1, const Cadena& c2);
bool operator==(const Cadena& c1, const Cadena& c2);
bool operator!=(const Cadena& c1, const Cadena& c2);
bool operator<(const Cadena& c1, const Cadena& c2);
bool operator>(const Cadena& c1, const Cadena& c2);
bool operator<=(const Cadena& c1, const Cadena& c2);
bool operator>=(const Cadena& c1, const Cadena& c2);
std::ostream& operator<<(std::ostream& os, const Cadena& c) noexcept;
std::istream& operator>>(std::istream& is, Cadena& c);
#endif
cadena.cpp
#include "cadena.hpp"
char Cadena::vacia[1] = { '\0' };
// Constructors
Cadena::Cadena(int tam, char s) : tam_((size_t)tam) {
if (tam < 0) throw std::length_error("tamaño negativo");
if (tam_ == 0) {
s_ = &vacia[0];
} else {
s_ = new char[tam_ + 1];
for (size_t i = 0; i < tam_; i++) s_[i] = s;
s_[tam_] = vacia[0];
}
}
Cadena::Cadena(const char* c) : tam_(strlen(c)) {
if (tam_ == 0) {
s_ = &vacia[0];
} else {
s_ = new char[tam_ + 1];
strcpy(s_, c);
s_[tam_] = vacia[0];
}
}
Cadena::Cadena(const Cadena& c) : tam_(c.tam_) {
if (tam_ == 0) {
s_ = &vacia[0];
} else {
s_ = new char[tam_ + 1];
strcpy(s_, c.s_);
}
}
Cadena::Cadena(Cadena&& c) : tam_(c.tam_), s_(c.s_) {
c.tam_ = 0;
c.s_ = &vacia[0];
}
// Operator Overloads
Cadena& Cadena::operator=(const Cadena& c) {
if (*this != c) {
if (0 != tam_) delete[] s_;
tam_ = c.tam_;
if (c.tam_ == 0) {
s_ = &vacia[0];
} else {
s_ = new char[tam_ + 1];
for (size_t i = 0; i <= tam_; i++) {
s_[i] = c.s_[i];
}
}
}
return *this;
}
Cadena& Cadena::operator=(Cadena&& c) {
if (this != &c) {
if (0 != tam_) delete[] s_;
tam_ = c.tam_;
s_ = c.s_;
c.tam_ = 0;
c.s_ = &vacia[0];
}
return *this;
}
Cadena& Cadena::operator=(const char* c) {
if (s_ != c) {
if (0 < tam_) delete[] s_;
tam_ = strlen(c);
if (tam_ == 0) {
s_ = &vacia[0];
} else {
s_ = new char[strlen(c) + 1];
strcpy(s_, c);
}
}
return *this;
}
Cadena::operator const char*() const noexcept { return s_; }
Cadena& Cadena::operator+=(const Cadena& c) { //dudo ,mejorable
size_t tam = tam_ + c.tam_;
char* aux = new char[tam + 1];
for (size_t i = 0; i < tam_; i++) {
aux[i] = s_[i];
}
for (size_t i = tam_, j = 0; i < tam; i++, j++) {
aux[i] = c.s_[j];
}
aux[tam] = vacia[0];
if (tam_ != 0) delete[] s_;
tam_ = tam;
s_ = new char[tam + 1];
strcpy(s_, aux);
delete[] aux;
return *this;
}
char& Cadena::operator[](const size_t i) {
return s_[i];
}
const char& Cadena::operator[](const size_t i) const {
return s_[i];
}
// Accessors
char& Cadena::at(int i) {
if (i < 0 || (int)tam_ <= i) throw std::out_of_range("Fuera del rango de la cadena");
return s_[i];
}
const char& Cadena::at(int i) const {
if (i < 0 || (int)tam_ <= i) throw std::out_of_range("Fuera del rango de la cadena");
return s_[i];
}
Cadena Cadena::substr(int indice, int size) const {
if (indice < 0 || size < 0) throw std::out_of_range("indice o tamaño negativos");
if ((int)tam_ < indice) throw std::out_of_range("posicion inicial superior al tamaño");
if ((int)tam_ < indice + size) throw std::out_of_range("indice + tamaño sale de rango");
Cadena subs(size);
for (int i = indice, j = 0; i < indice + size; i++, j++) {
subs.s_[j] = s_[i];
}
return subs;
}
// Destructor
Cadena::~Cadena() {
if (tam_ != 0) delete[] s_;
tam_ = 0;
s_ = nullptr;
}
// External Operator Overloads
Cadena operator+(const Cadena& c1, const Cadena& c2) {
Cadena c(c1);
c += c2;
return c;
}
bool operator==(const Cadena& c1, const Cadena& c2) {
return (strcmp((const char*)c1, (const char*)c2) == 0);
}
bool operator!=(const Cadena& c1, const Cadena& c2) {
return !(c1 == c2);
}
bool operator<(const Cadena& c1, const Cadena& c2) {
return (strcmp((const char*)c1, (const char*)c2) < 0);
}
bool operator>(const Cadena& c1, const Cadena& c2) {
return c2 < c1;
}
bool operator<=(const Cadena& c1, const Cadena& c2) {
return !(c2 < c1); // == !(c1 > c2)
}
bool operator>=(const Cadena& c1, const Cadena& c2) {
return !(c1 < c2);
}
std::ostream& operator<<(std::ostream& os, const Cadena& c) noexcept {
os << (const char*)c;
return os;
}
std::istream& operator>>(std::istream& is, Cadena& cadena) {
char cad[33] = "";
is.width(33);
is >> cad;
cadena = cad;
return is;
}