Tengo un problema con operator>> cuando intento usarlo en mi clase String. Necesito hacer una cadena desde el teclado, pero todos mis intentos fallan. Ayudame por favor.

Cuando trato de entregar este código, siempre tengo un bloqueo.

#include<iostream>
#include<fstream>

using namespace std;

class myString
{
public:

    friend std::ostream& operator<< (std::ostream& out, const myString& other);
    friend std::istream& operator>> (std::istream& in, myString& other);

    myString()
    {
        str = nullptr;
        length = 0;
    }

    myString(const char* str)
    {

        length = strlen(str);

        this->str = new char[length + 1];

        for (int i = 0; i < length; i++)
        {
            this->str[i] = str[i];
        }

        this->str[length] = '\0';

    }

    ~myString()
    {
        delete[] this->str;
    }

    myString(const myString& other)
    {
        length = strlen(other.str);
        this->str = new char[length + 1];

        for (int i = 0; i < length; i++)
        {
            this->str[i] = other.str[i];
        }

        this->str[length] = '\0';
    }

    myString& operator =(const myString& other)
    {

        if (this->str != nullptr)
        {
            delete[] str;
        }

        length = strlen(other.str);
        this->str = new char[length + 1];

        for (int i = 0; i < length; i++)
        {
            this->str[i] = other.str[i];
        }

        this->str[length] = '\0';

        return *this;

    }
    myString& operator =(const char* other)
    {

        if (this->str != nullptr)
        {
            delete[] str;
        }

        length = strlen(other);
        this->str = new char[length + 1];

        for (int i = 0; i < length; i++)
        {
            this->str[i] = other[i];
        }

        this->str[length] = '\0';

        return *this;

    }

    myString& operator +=(myString const& other) {
        return (this->operator=(this->operator+(other)));
    }

    myString operator +(const myString& other)
    {

        myString newStr;

        int thisLength = strlen(this->str);
        int otherLength = strlen(other.str);

        newStr.length = thisLength + otherLength;

        newStr.str = new char[thisLength + otherLength + 1];

        int i = 0;
        for (; i < thisLength; i++)
        {
            newStr.str[i] = this->str[i];
        }

        for (int j = 0; j < otherLength; j++, i++)
        {
            newStr.str[i] = other.str[j];
        }

        newStr.str[thisLength + otherLength] = '\0';

        return newStr;
    }

    void Print()
    {
        cout << str;
    }

    int Length()
    {
        return length;
    }

    bool operator ==(const myString& other)
    {
        if (this->length != other.length)
        {
            return false;
        }

        for (int i = 0; i < this->length; i++)
        {
            if (this->str[i] != other.str[i])
            {
                return false;
            }
        }
        return true;
    }

    bool operator !=(const myString& other)
    {
        return !(this->operator==(other));
    }

    char& operator [](int index)
    {
        return this->str[index];
    }

private:
    char* str;
    int length;

};

ostream& operator<< (ostream& out, const myString& other)
{
    out << other.str;

    return out;
}

istream& operator >> (istream& in, myString& other)
{
    in.getline(other.str, sizeof(other.str));
    return in;
}

int main()
{

    myString str_3;
    cin >> str_3;
    cout << str_3;

    return 0;
}
c++
0
Alexey Petrenko 15 may. 2020 a las 17:05

3 respuestas

La mejor respuesta

Está intentando leer en un puntero inicializado con nullptr y usa sizeof() de ese puntero cuando tiene un miembro de datos length. Como ya definió el operador de asignación para la matriz de caracteres, puede usarlo:

istream& operator >> (istream& in, myString& other)
{
    char buffer[256];
    in.getline(buffer, sizeof(buffer));
    other = buffer;
    return in;
}

Tenga en cuenta que el tamaño del búfer es arbitrario aquí, la aplicación real debe manejar diferentes tamaños y crecer según la necesidad, pero eso requeriría una implementación de cadena más avanzada que la suya. Para su solución simplificada que se parece a la tarea del estudiante, esto podría estar bien.

Nota: su operator<< también tiene problemas, si lo llama en un objeto construido por defecto, esto conduciría a UB, ya que std::ostream no acepta nullptr en const char *. Una verificación simple para nullptr sería suficiente allí:

ostream& operator<< (ostream& out, const myString& other)
{
    if(other.str)
        out << other.str;

    return out;
}

Irónicamente, verificó nullptr para delete[], lo cual no es necesario.

0
Slava 15 may. 2020 a las 14:52

sizeof(other.str) no es el tamaño del búfer asignado sino el tamaño del puntero.

other.str se inicializa a nullptr en el constructor, por lo que intentará leer en un lugar no válido y conducirá a una falla de segmentación.

Cambiar el constructor a

    myString()
    {
        str = new char[1];
        length = 0;
    }

Para mantener el tamaño del búfer siempre length + 1 y cambiar el operator>> a

istream& operator >> (istream& in, myString& other)
{
    in.getline(other.str, other.length + 1);
    return in;
}

Evitará que se produzca un fallo de segmentación.

Esto no resolverá el problema de que la lectura se limitará a la longitud de la cadena ya asignada. Mejorar el comportamiento requerirá otras modificaciones, como leer los caracteres uno por uno y asignar el búfer de acuerdo con el tamaño leído.

1
MikeCAT 15 may. 2020 a las 14:13

No asigna espacio para su miembro de datos str en el constructor predeterminado. Entonces cuando escribes

myString str_3;
cin >> str_3;

Entonces su código en operator>> (es decir, in.getline(other.str, sizeof(other.str));) escribirá en la memoria que no asignó antes).

Asegúrese de que str proporcione suficiente memoria asignada antes de escribir en ella, p. utilizando alloc o realloc.

0
Stephan Lechner 15 may. 2020 a las 14:11