Почему в методе класса String append () произошла ошибка? - PullRequest
0 голосов
/ 08 апреля 2020

Я пытаюсь реализовать класс String и обнаружил ошибку с помощью моего метода append(). Не могли бы вы сказать мне, что я сделал с этим не так? Мне не разрешено использовать какие-либо стандартные функции библиотеки. Я просто добавил <iostream> к выводу на печать, чтобы я мог проверить ответ.

Вот append():

void append(const String& s){
    char* temp;
    temp = new char[len+s.len];
    for(int i = 0; i < len; i++){
        temp[i] = str[i];
    }
    for(int i = 0; i < s.len; i++){
        temp[len + 1] = s.str[i];
    }
    str = temp;
}

Вот мой полный код:

#include <iostream>

using namespace std;

class String{
    public:
        char* str = nullptr;
        unsigned int len = 0;

        String() = default;

        String(const char* chars){
            if(chars){
                unsigned int i = 0;
                while(chars[i]){
                    i++;
                }
                len = i;
                str = new char[len];
                for(int j = 0; j < len; j++){
                    str[j] = chars[j];
                }
            }
        };

        String(const String& s){
            if(!s.isEmpty()){
                len = s.len;
                str = new char[len];
                for(int i = 0; i < len; i++){
                    str[i] = s.str[i];
                }
            }
        };

        ~String() noexcept{
            delete[] str;
        };

        String& operator=(const String &s) {
            if (&s != this) {
                String tmp(s);
                char *tmpstr = tmp.str;
                unsigned int tmplen = tmp.len;
                tmp.str = str;
                tmp.len = len;
                str = tmpstr;
                len = tmplen;
            }
            return *this;
        }

        void append(const String& s){
            char* temp;
            temp = new char[len+s.len];
            for(int i = 0; i < len; i++){
                temp[i] = str[i];
            }
            for(int i = 0; i < s.len; i++){
                temp[len + 1] = s.str[i];
            }
            str = temp;
        }

        bool isEmpty() const noexcept{
            return(len == 0);
        }

        unsigned int length() const noexcept{
            return len;
        }

        bool contains(const String& substring) const noexcept{
            if(find(substring)){
                return true;
            }
            return false;
        }

        int find(const String& substring) const noexcept{
            for(int i = 0; i < len - substring.len + 1; i++){
                if(str[i] == substring.str[0]){
                    for(int j = 1; j < substring.len;){
                        if(str[i + j] == substring.str[j]){
                            j++;
                            if(j == substring.len){
                                return i;
                            }
                        }
                        else{
                            break;
                        }
                    }
                }
            }
            return -1;
        }

        const char* toChars() const noexcept{
            char* temp = new char[len + 1];
            for(unsigned int c = 0; c < len; ++c) {
                temp[c] = str[c];
            }
            temp[len] = '\0';
            return temp;
        }
};

int main()
{
    const char* chars = "Boo is snoring1";
    const char* morechars = " and running";

    String s(chars);
    String more(morechars);
    s.append(more);

    cout << s.str << endl;

    return 0;
}

Ответы [ 3 ]

3 голосов
/ 08 апреля 2020

Для начала функция append имеет утечку памяти, поскольку предыдущий указатель не удален. И новое значение элемента данных len не установлено.

void append(const String& s){
            char* temp;
            temp = new char[len+s.len];
            for(int i = 0; i < len; i++){
                temp[i] = str[i];
            }
            for(int i = 0; i < s.len; i++){
                temp[len + 1] = s.str[i];
            }
            str = temp;
        }

Во втором l oop

        for(int i = 0; i < s.len; i++){
            temp[len + 1] = s.str[i];
        }

есть опечатка. Вы имеете в виду

temp[len + i] = s.str[i];
          ^^^

В-третьих, вы выводите строку как C string

cout << s.str << endl

Это означает, что указанная строка должна иметь завершающий нулевой символ.

Элементы данных str и len должны быть частными элементами данных. И элемент данных len должен иметь тип size_t.

    char* str = nullptr;
    unsigned int len = 0;

Более того, в циклах вы используете индекс типа int вместо типа unsigned int.

Так что на самом деле определение класса в целом неверно.

Что касается функции append, то она должна быть определена как минимум следующим образом. Я предполагаю, что указанные массивы содержат строки.

String & append( const String &s )
{
    char* temp = new char[len + s.len + 1];

    size_t i = 0;

    for ( ; i < len; i++ ) temp[i] = str[i];
    while ( ( temp[i] = s.str[i-len] ) != '\0' ) i++;

    delete [] str;

    str = temp;
    len = len + s.len;

    return *this; 
}

Обратите внимание, что конструктор по умолчанию должен выделить память размером 1 и установить выделенный байт на '\0'. В этом случае элемент данных len должен быть установлен на 0.

Поэтому проверьте все остальные функции-члены. Например, функция-член find будет иметь неопределенное поведение, когда переданная строка имеет элемент данных len, равный 0.

2 голосов
/ 08 апреля 2020

Ваш второй л oop должен temp[len + i] не temp[len + 1]

1 голос
/ 08 апреля 2020

Ваш второй l oop неправильно обращается к temp. Вы используете temp[len + 1], но вместо этого вам нужно использовать temp[len + i]. Вот почему вы должны использовать более значимые имена для ваших переменных. 1 и i не являются взаимозаменяемыми, но они очень близки визуально, так что их легко спутать друг с другом.

Кроме того, вы не освобождаете предыдущий str перед его заменой на новые данные. И вы не обновляете len после замены str.

Попробуйте вместо этого:

void append(const String& s){
    char* temp = new char[len + s.len];
    for(int idx = 0; idx < len; ++idx){
        temp[idx] = str[idx];
    }
    for(int idx = 0; idx < s.len; ++idx){
        temp[len + idx] = s.str[idx];
    }
    delete[] str;
    str = temp;
    len += s.len;
}

Помимо этого, вы изменили свой main() с момента последнего вопрос для распечатки str напрямую, но str не заканчивается нулем. Поэтому вам нужно будет распечатать его следующим образом:

int main()
{
    String s("Boo is snoring1");
    s.append(" and running");

    cout.write(s.str, s.len);
    cout << endl;

    return 0;
}

В противном случае go вернуться к распечатке результата toChars(), как я показал вам ранее:

const char *chars = s.toChars();
cout << chars << endl; 
delete[] chars;

Или же вы должны определить свой собственный operator<<, чтобы распечатать String объект:

std::ostream& operator<<(std::ostream &os, const String &s)
{
    return os.write(s.str, s.len);
}

...

cout << s << endl; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...