Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Использование собственного класса строк 
:(
    Опции темы
YourLastSong
Дата 15.1.2012, 22:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 17.12.2011

Репутация: нет
Всего: нет



Здравствуйте, уважаемые господа.

Есть реализация собственного класса строк:

Код

class MyString
{
    private:
        size_t length;
        char *str;

    public:
        MyString ();
        MyString (const char *c);
        MyString (const MyString& t);
        ~MyString ();

        MyString& operator= (const MyString& t);
        MyString operator+ (const MyString& t) const;
        MyString operator+ (const char *c) const;
        bool operator== (const MyString& t) const;
        bool operator!= (const MyString& t) const;
        void operator+= (const MyString& t);
        char& operator[] (size_t i);

        char& at (size_t i);
        void get_input (std::istream& in);
        size_t size () const;
        size_t get_length () const;

        friend std::ostream& operator<< (std::ostream& out, const MyString& t);
        friend std::istream& operator>> (std::istream& in, MyString& t);
};

MyString::MyString ()
{
    length = 0;
    str = NULL;
}

MyString::MyString (const char *c)
{
    length = strlen (c) + 1;
    str = new char[length];
    strcpy (str, c);
    str[length-1] = '\0';
}

MyString::MyString (const MyString& t)
{
    length = strlen (t.str) + 1;
    str = new char[length];
    strcpy (str, t.str);
    str[length-1] = '\0';
}

MyString::~MyString ()
{
    if (str != NULL)
    {
        delete[] str;
    }
}

MyString& MyString::operator= (const MyString& t)
{
    length = strlen (t.str) + 1;
    str = new char[length];
    strcpy (str, t.str);
    str[length-1] = '\0';

    return *this;
}

MyString MyString::operator+ (const MyString& t) const
{
    char* newStr = new char[strlen (str) + strlen (t.str) + 1];
    strcpy (newStr, str);
    strcat (newStr, t.str);
    newStr[length-1] = '\0';

    MyString returnObj (newStr);
    delete[] newStr;

    return returnObj;
}

bool MyString::operator== (const MyString& t) const
{
    return (strcmp(str, t.str) == 0);
}

bool MyString::operator!= (const MyString& t) const
{
    return (strcmp(str, t.str) != 0);
}

void MyString::operator+= (const MyString& t)
{
    length = strlen (str) + strlen (t.str) + 1;
    char *newStr = new char[length];
    strcpy (newStr, str);
    strcat (newStr, t.str);
    strcpy (str, newStr);
    str[length-1] = '\0';
    delete[] newStr;
}

char& MyString::operator[] (size_t i)
{
    return str[i];
}

char& MyString::at (size_t i)
{
    if (i >= 0 && i < length)
    {
        return str[i];
    }
}

void MyString::get_input (std::istream& in)
{
    while (true)
    {
        char c = in.get ();

        if (c == '\n')
        {
            break;
        }

        if (length == 0)
        {
            length = 2;
        }
        else
        {
            ++length;
        }

        char* newStr = new char[length];
        if (str != NULL)
        {
            strcpy (newStr, str);
        }
        newStr[length-2] = c;
        newStr[length-1] = '\0';

        delete[] str;

        str = newStr;
    }
}

size_t MyString::size () const
{
    return length;
}

size_t MyString::get_length () const
{
    if (length == 0)
    {
        return 0;
    }
    else
    {
        return (length - 1);
    }
}

std::ostream& operator<< (std::ostream& out, const MyString& t)
{
    out << t.str;
    return out;
}

std::istream& operator>> (std::istream& in, MyString& t)
{
    t.get_input (in);
    return in;
}


Всё ли здесь так, как надо?

Что бы вы предложили добавить сюда и каким образом?

Заранее благодарю за возможные ответы.
PM MAIL   Вверх
boostcoder
Дата 15.1.2012, 22:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
MyString& MyString::operator= (const MyString& t)
{
    length = strlen (t.str) + 1;
    str = new char[length];
    strcpy (str, t.str);
    str[length-1] = '\0';
    return *this;
}

нет защиты от присваивания себя же.

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
MyString MyString::operator+ (const MyString& t) const
{
    char* newStr = new char[strlen (str) + strlen (t.str) + 1]; // 1
    strcpy (newStr, str);
    strcat (newStr, t.str);
    newStr[length-1] = '\0';
    MyString returnObj (newStr); // 2
    delete[] newStr;
    return returnObj; // 3
}

три выделения памяти.

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
bool MyString::operator== (const MyString& t) const
{
    return (strcmp(str, t.str) == 0);
}

сначала сравни this`ы. и если не равны - strcmp

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
bool MyString::operator!= (const MyString& t) const
{
    return (strcmp(str, t.str) != 0);
}

{ return !(operator==(t)); }

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
void MyString::operator+= (const MyString& t)
{
    length = strlen (str) + strlen (t.str) + 1;
    char *newStr = new char[length];
    strcpy (newStr, str);
    strcat (newStr, t.str);
    strcpy (str, newStr);
    str[length-1] = '\0';
    delete[] newStr;
}

портишь кучу.

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
char& MyString::operator[] (size_t i)
{
    return str[i];
}

нет проверки на диапазон.

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
char& MyString::operator[] (size_t i)
{
    return str[i];
}
char& MyString::at (size_t i)
{
    if (i >= 0 && i < length)
    {
        return str[i];
    }
}

нет одноименных константных методов.

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
void MyString::get_input (std::istream& in)

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
size_t MyString::get_length () const

это вообще лишнее.

Это сообщение отредактировал(а) boostcoder - 15.1.2012, 23:02
PM WWW   Вверх
feodorv
Дата 15.1.2012, 23:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
MyString& MyString::operator= (const MyString& t)
{
    length = strlen (t.str) + 1;
    ....
}

Вы не доверяете t.length? И нет проверки t.str на NULL. Тоже в других местах.


Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
void MyString::get_input (std::istream& in)
{
    while (true)
    {
        char c = in.get ();
       
        ....
        char* newStr = new char[length];
        ....
        delete[] str;
        str = newStr;
    }
}

Круто Вы так побайтно прибавляетесь...


Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
MyString::MyString (const char *c)
{
    ....
    strcpy (str, c);
    str[length-1] = '\0';
}

strcpy и так ноль вставляет...


Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
char& MyString::at (size_t i)
{
    if (i >= 0 && i < length)
    {
        return str[i];
    }
}

А если i не попадает в указанный интервал, то что возвращается? Опять же, где проверка на NULL? Тогда уж инициализируйтесь в конструкторе пустой сторокой, что ли...


Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
bool MyString::operator!= (const MyString& t) const
{
    return (strcmp(str, t.str) != 0);
}

Сначала сравнить на NULL, потом на length, и уж потом strcmp...


И зачем в length прибавлять лишнюю единичку (тогда уж по смыслу size)...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
boostcoder
Дата 15.1.2012, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 20
Всего: 110



Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)

size_t length;
char *str;

вообще-то, такая архитектура не очень хороша, ибо для того чтоб узнать длину содержащейся строки тебе нужно постоянно использовать strlen(). а если учесть что операций чтения строки всегда больше, и они не могут изменить данные класса - то это вообще сплошной оверхэд!
есть два способа:
1. ptr, len, capacity.
2. ptr_beg, ptr_end, ptr_cur.
я бы выбрал второй.

далее...
нет счетчика ссылок.
представь ситуацию: у тебя есть одна исходная строка. далее, в коде программы, в алгоритмах, у тебя есть огромное кол-во строк которые инициализируются этой строкой. что происходит? - все кто ссылаются на твою строку, копирует ее. примеряем это к тому правилу то, что читают строку чаще чем изменяют - то копии лишние. они попросту съели память и нагородили оверхэда.
читать copy-on-write.

Это сообщение отредактировал(а) boostcoder - 15.1.2012, 23:16
PM WWW   Вверх
borisbn
Дата 16.1.2012, 13:23 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)

    if (str != NULL)    
    {        
        delete[] str;
    }

Для "порядку" проверять, конечно, можно, но delete нормально отрабатывает, если ему дали NULL (вернее - ничего не делает).
И ещё: у Вас много повторения кода, от этого лучше избавляться. Например, можно создать private-функцию
Код
void from_c_str( const char * other );

и вызывать её как минимум в трёх местах:
Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
MyString::MyString (const char *c)

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
MyString::MyString (const MyString& t)

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
MyString& MyString::operator= (const MyString& t)




--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
baldina
Дата 16.1.2012, 16:19 (ссылка) |    (голосов:2) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 15
Всего: 101



Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
 void operator+= (const MyString& t);

нехорошо, что он void
должно быть
Код

MyString& operator+= (const MyString& t) {
 ....
 return *this;
}

иначе нельзя использовать в выражениях типа a = (b+=c), что отличается от поведения стандартных типов. 
кроме того см. пример ниже

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
 MyString operator+ (const char *c) const;

излишен, если есть  operator+ (const MyString& t) и конструктор из с-строки (а он есть)

Цитата(YourLastSong @  15.1.2012,  22:22 Найти цитируемый пост)
MyString operator+ (const MyString& t) const;

это позволяет писать
Код

MyString str1("bla-bla");
MyString str2 = str1 + "bla-bla";

но не позволяет 
Код

MyString str1("bla-bla");
MyString str2 = "bla-bla" + str;


лучше сделать operator+ свободной функцией, реализованной через operator+=, возвращающий строку
Код

MyString operator+(const MyString& str1, const MyString& str2) {
  MyString temp (str1);
  return temp += str2;
}

таким образом избавляемся от повторного кода и даем возможность писать  "bla-bla" + str

Добавлено через 2 минуты и 55 секунд
А вообще лучше взять какой-нить промышленный интерфейс строки, например std::string, и рассмотреть его как основу. А в случаях, когда непонятно, почему интерфейс устроен так а не иначе задать вопросы.
PM MAIL   Вверх
YourLastSong
Дата 16.1.2012, 17:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 17.12.2011

Репутация: нет
Всего: нет



Спасибо.

Класс нужен лишь для собственного изучения и прекрасно знаю о том, что такие вещи уже давно реализовали другие люди, причём гораздо более умные. Сам лично использую std::string.

Итак, попытался исправить лишь часть недочётов и ошибок:

Код

class MyString
{
    private:
        size_t length;
        char *str;

    public:
        MyString ();
        MyString (const char *c);
        MyString (const MyString& t);
        ~MyString ();

        MyString& operator= (const MyString& t);
        MyString& operator= (const char *c);
        MyString operator+ (const MyString& t) const;
        MyString& operator+= (const MyString& t);
        char& operator[] (size_t i);
        const char& operator[] (size_t i) const;

        char& at (size_t i);
        const char& at (size_t i) const;
        void get_input (std::istream& in);
        size_t get_length () const;
        void from_c_str (const char *other);

        friend std::ostream& operator<< (std::ostream& out, const MyString& t);
        friend std::istream& operator>> (std::istream& in, MyString& t);
        friend bool operator== (const MyString& t, char *c);
        friend bool operator== (const MyString& t, const MyString& t1);
        friend bool operator!= (const MyString& t, char *c);
        friend bool operator!= (const MyString& t, const MyString& t1);
};

MyString::MyString ()
{
    length = 1;
    str = '\0';
}

MyString::MyString (const char *c)
{
    from_c_str (c);
}

MyString::MyString (const MyString& t)
{
    from_c_str (t.str);
}

MyString::~MyString ()
{
    delete[] str;
}

MyString& MyString::operator= (const MyString& t)
{
    from_c_str (t.str);

    return *this;
}

MyString& MyString::operator= (const char *c)
{
    from_c_str (c);

    return *this;
}

MyString MyString::operator+ (const MyString& t) const
{
    return (MyString(str) += t.str);
}

bool operator== (const MyString& t, char *c)
{
    return (strcmp(t.str, c) == 0);
}

bool operator== (const MyString& t, const MyString& t1)
{
    return (strcmp(t.str, t1.str) == 0);
}

bool operator!= (const MyString& t, char *c)
{
    return !(operator== (t, c));
}

bool operator!= (const MyString& t, const MyString& t1)
{
    return !(operator== (t, t1.str));
}

MyString& MyString::operator+= (const MyString& t)
{
    length = strlen (str) + strlen (t.str) + 1;
    char *newStr = new char[length];
    strcpy (newStr, str);
    strcat (newStr, t.str);
    strcpy (str, newStr);
    str[length-1] = '\0';
    delete[] newStr;

    return *this;
}

char& MyString::operator[] (size_t i)
{
    return str[i];
}

const char& MyString::operator[] (size_t i) const
{
    return str[i];
}

char& MyString::at (size_t i)
{
    if (str != NULL && i >= 0 && i < length)
    {
        return str[i];
    }
    else
    {
        throw std::exception ("wrong index");
    }
}

const char& MyString::at (size_t i) const
{
    if (str != NULL && i >= 0 && i < length)
    {
        return str[i];
    }
    else
    {
        throw std::exception ("wrong index");
    }
}

void MyString::get_input (std::istream& in)
{
    while (true)
    {
        char c = in.get ();

        if (c == '\n')
        {
            break;
        }

        if (length == 0)
        {
            length = 2;
        }
        else
        {
            ++length;
        }

        char* newStr = new char[length];
        if (str != NULL)
        {
            strcpy (newStr, str);
        }
        newStr[length-2] = c;
        newStr[length-1] = '\0';

        delete[] str;

        str = newStr;
    }
}

size_t MyString::get_length () const
{
    return (length - 1);
}

void MyString::from_c_str (const char *c)
{
    length = strlen (c) + 1;
    str = new char[length];
    strcpy (str, c);
}

std::ostream& operator<< (std::ostream& out, const MyString& t)
{
    out << t.str;
    return out;
}

std::istream& operator>> (std::istream& in, MyString& t)
{
    t.get_input (in);
    return in;
}


Есть уже здесь какие-то недочёты, кроме тех, что вы уже назвали?

Извиняюсь, если уже надоел.
PM MAIL   Вверх
feodorv
Дата 16.1.2012, 18:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 12
Всего: 45



37-я строка:
Код

    str = '\0';

Что это?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1023 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.