Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/6: Рейтинг темы: голосов - 6, средняя оценка - 5.00
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
1

Организация ввода собственного типа

16.10.2016, 21:03. Показов 1174. Ответов 23
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте, создаю собственный класс для работы со строками. Так вот, встал такой вопрос: как ввести строку произвольного размера? Перегружаю оператор ">>" вот код:
C++
1
2
3
4
5
istream& operator>>(istream& os, const strings& obj)
{
    os >> obj.s;
    return os;
}
Так вот, если прописать в main что-то вроде
C++
1
2
3
4
5
6
7
#include "strings.h"
void main()
{
    strings  s(10);
    cin >> s;
    cout << s;
}
Все работает. Если же вот так:
C++
1
2
3
4
5
6
7
#include "strings.h"
void main()
{
    strings  s;
    cin >> s;
    cout << s;
}
То выскакивает ошибка, что строка пишется за пределами буфера.
Оно и понятно, ведь строки как таковой не создано.
Вопрос вот в чем:
Как сделать возможность объявлять переменную
C++
1
strings s;
И иметь возможность вводить строку произвольного размера?
Помогите, пожалуйста
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
16.10.2016, 21:03
Ответы с готовыми решениями:

Обработка исключение от собственного типа
Всем привет. Я бы хотел реализовать стек и использовать свои классы исключения для обработки...

Как вывести элементы контейнера set с ключами собственного типа?
Есть класс, который является типом ключа set. Класс и предикат к нему #include &lt;string&gt; using...

Организация ввода с использование do while
Не понимаю в чём ошибка, если ввод не удаётся, то программа почему-то зацикливается: #include...

Организация посимвольного ввода с клавиатуры
Каким образом организовать эту деятельность?)

23
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
16.10.2016, 21:09 2
Класс покажи.
0
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
16.10.2016, 21:11  [ТС] 3
Прототипы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
class strings
{
private:
    char *s;
public:
    strings();
    explicit strings(int n);
    strings(char *str);
    strings(const strings&);
    ~strings();
    strings operator= (strings &obj);
    strings operator= (char *str);
    strings operator+ (strings obj);
    strings operator+ (char *str);
    strings operator+= (strings obj);
    strings operator+= (char *str);
    strings operator- (strings obj);
    strings operator- (char *str);
    strings operator-= (strings obj);
    strings operator-= (char *str);
    bool operator> (strings obj);
    bool operator> (char *str);
    bool operator< (strings obj);
    bool operator< (char *str);
    bool operator== (strings obj);
    bool operator== (char *str);
    strings operator++ ();
    strings operator-- ();
    strings operator() (int, int);
    char operator [] (int);
    friend ostream& operator<<(ostream& os, const strings&);
    friend istream& operator>>(istream& os, const strings&);
};
Реализация:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
#include "strings.h"
strings::strings()
{
    s = new char[1];
    s[0] = '\0';
}
strings::strings(int n)
{
    s = new char[n];
}
strings::strings(char *str)
{
    s = new char[strlen(str)+1];
    strcpy(s, str);
}
strings::~strings()
{
    delete [] s;
}
strings::strings(const strings& copy)
{
    s = new char[strlen(copy.s) + 1];
    strcpy(s, copy.s);
}
strings strings::operator= (strings &obj)
    {
        if (&obj != this)
        {
            delete[] s;
            s = new char[strlen(obj.s) + 1];
            strcpy(s, obj.s);
        }
        return *this;
    }
strings strings::operator= (char *str)
{
    delete[] s;
    s = new char[strlen(str) + 1];
    strcpy(s, str);
    return *this;
}
strings strings::operator+ (strings obj)
{
    strings temp(strlen(this->s) + strlen(obj.s) + 1);
    strcat(strcpy(temp.s,this->s), obj.s);
    return temp;
}
strings strings::operator+ (char *s)
{
    strings temp(strlen(this->s) + strlen(s) + 1);
    strcat(strcpy(temp.s, this->s), s);
    return temp;
}
strings strings::operator+= (char *str)
{
    char *s = new char[strlen(this->s) + 1];
    strcpy(s, this->s);
    delete[] this->s;
    this->s = new char[strlen(str) + strlen(this->s) + 1];
    strcat(strcpy(this->s, s), str);
    delete[] s;
    return *this;
}
strings strings::operator+= (strings obj)
{
    char *s = new char[strlen(this->s) + 1];
    strcpy(s, this->s);
    delete[] this->s;
    this->s = new char[strlen(obj.s) + strlen(this->s) + 1];
    strcat(strcpy(this->s, s), obj.s);
    delete[] s;
    return *this;
}
strings strings::operator- (strings obj)
{
    if (strstr(s, obj.s) != NULL)
    {
        strings temp(strlen(s) - strlen(obj.s) + 1);
        strncpy(temp.s, s, strstr(s, obj.s)-s);
        temp.s[strstr(s, obj.s) - s] = '\0';
        strcat(temp.s, (strstr(s, obj.s) + strlen(obj.s)));
        return temp;
    }
    else return *this;
}
strings strings::operator- (char *str)
{
    if (strstr(s, str) != NULL)
    {
        strings temp(strlen(s) - strlen(str) + 1);
        strncpy(temp.s, s, strstr(s, str) - s);
        temp.s[strstr(s, str) - s] = '\0';
        strcat(temp.s, (strstr(s, str) + strlen(str)));
        return temp;
    }
    else return *this;
}
strings strings::operator-= (strings obj)
{
    if (strstr(s, obj.s) != NULL)
    {
        char *temp = new char[strlen(this->s) + 1];
        strcpy(temp, this->s);
        delete[] this->s;
        s = new char[strlen(temp) - strlen(obj.s) + 1];
        strncpy(s, temp, strstr(temp, obj.s) - temp);
        s[strstr(temp, obj.s) - temp] = '\0';
        strcat(s, (strstr(temp, obj.s) + strlen(obj.s)));
        delete[] temp;
    }
    return *this;
}
strings strings::operator-= (char *str)
{
    if (strstr(s, str) != NULL)
    {
        char *temp = new char[strlen(this->s) + 1];
        strcpy(temp, this->s);
        delete[] this->s;
        s = new char[strlen(temp) - strlen(str) + 1];
        strncpy(s, temp, strstr(temp, str) - temp);
        s[strstr(temp, str) - temp] = '\0';
        strcat(s, (strstr(temp, str) + strlen(str)));
        delete[] temp;
    }
    return *this;
}
bool strings::operator> (strings obj)
{
    if (strcmp(s, obj.s) > 0)
        return true;
    else return false;
}
bool strings::operator> (char *str)
{
    if (strcmp(s, str) > 0)
        return true;
    else return false;
}
bool strings::operator< (strings obj)
{
    if (strcmp(s, obj.s) < 0)
        return true;
    else return false;
}
bool strings::operator< (char *str)
{
    if (strcmp(s, str) < 0)
        return true;
    else return false;
}
bool strings::operator== (strings obj)
{
    if (strcmp(s, obj.s) == 0)
        return true;
    else return false;
}
bool strings::operator== (char *str)
{
    if (strcmp(s, str) == 0)
        return true;
    else return false;
}
strings strings::operator++()
{
    for (int i = 0; i < strlen(s); i++)
        s[i]++;
    return *this;
}
strings strings::operator--()
{
    for (int i = 0; i < strlen(s); i++)
        s[i]--;
    return *this;
}
strings strings::operator()(int n, int m)
{
    strings temp(n+m+3);
    int p = 0;
    for (int i = n; i < (m-1); i++, p++)
        temp.s[p] = s[i];
    temp.s[m-n-1] = '\0';
    return temp;
}
char strings::operator[] (int n)
{
    return s[n];
}
ostream& operator<<(ostream& os, const strings& obj)
{
    os << obj.s;
    return os;
}
istream& operator>>(istream& os, const strings& obj)
{
    strings ob;
    os >> obj.s;
    return os;
}
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
16.10.2016, 21:14 4
Цитата Сообщение от TheTangro Посмотреть сообщение
Как сделать возможность объявлять переменную
C++
1
strings s;
И иметь возможность вводить строку произвольного размера?
Выделять в конструкторе по умолчанию память произвольного размера.
0
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
16.10.2016, 21:15  [ТС] 5
А как это? Простите за невеждество
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
16.10.2016, 21:17 6
Цитата Сообщение от TheTangro Посмотреть сообщение
C++
1
2
3
4
5
strings::strings()
{
* * s = new char[1];
* * s[0] = '\0';
}
Цитата Сообщение от TheTangro Посмотреть сообщение
А как это? Простите за невеждествo
C++
3
s = new char[16];
0
Эксперт С++
8739 / 4317 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
16.10.2016, 21:21 7
Цитата Сообщение от TheTangro Посмотреть сообщение
istream& operator>>(istream& os, const strings& obj)
C++
1
istream& operator>>(istream& os, strings& obj)
Добавлено через 52 секунды
Цитата Сообщение от TheTangro Посмотреть сообщение
os >> obj.s;
это не будет работать.

вместо char* s используйте std::string
0
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
16.10.2016, 21:22  [ТС] 8
Понятно, что можно прописать по умолчанию new char[100500]. Но разве это рациональное использование оперативной памяти? Пока на ум приходит только на вводе считывать каждый символ и забивать его в FIFO очередь. Потом же из этого формировать строку, точно зная сколько символов считалось
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
16.10.2016, 21:25 9
Цитата Сообщение от TheTangro Посмотреть сообщение
Но разве это рациональное использование оперативной памяти?
А std::string что делает?
0
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
16.10.2016, 21:27  [ТС] 10
Мне не нужно использовать встроенный класс. Мне нужно написать свой. А что он делает?
0
Любитель чаепитий
3742 / 1798 / 566
Регистрация: 24.08.2014
Сообщений: 6,016
Записей в блоге: 1
16.10.2016, 21:29 11
Хотя нет, std::string изначально 0 символов хранит.
Ресайзится при надобности.
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
16.10.2016, 21:35 12
Лучший ответ Сообщение было отмечено GbaLog- как решение

Решение

Цитата Сообщение от TheTangro Посмотреть сообщение
Но разве это рациональное использование оперативной памяти?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
istream& operator>>(istream& os, strings& obj)
{
    char ch;
    os.get(ch);
    if(cin)
    {
        os.putback(ch);
        int count = os.rdbuf() ->in_avail(); 
        char* str = new char[count];
        
        os.getline(str, count);
       
        if (os)
        {
            delete [] obj.s;
            obj.s = str;
        }
        else
        {
            delete [] str;
            os.clear();
            os.ignore(os.rdbuf() ->in_avail());
        }
    }
    return os;
}
2
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
16.10.2016, 22:01  [ТС] 13
Ураа!!!! Работает!!!!! Простите за наглость, а не могли бы вы,если вас это не затруднит, немного пояснить код?

Добавлено через 10 минут
Для будущих читателей темы. Вот немного подправленный, правильный код. (str - все же просто указатель, а строки нельзя присваивать друг другу простым "=" )
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
    char ch;
    os.get(ch);
    if (cin)
    {
        os.putback(ch);
        int count = os.rdbuf()->in_avail();
        char* str = new char[count];
 
        os.getline(str, count);
 
        if (os)
        {
            delete[] obj.s;
            obj.s = new char[strlen(str)+1];
            strcpy(obj.s, str);
        }
        else
        {
            delete[] str;
            os.clear();
            os.ignore(os.rdbuf()->in_avail());
        }
    }
    return os;
}
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
16.10.2016, 22:05 14
Цитата Сообщение от nd2 Посмотреть сообщение
if(cin)
* * {
Тут я не заменил. Так нужно:
C++
1
2
if(os)
    {
Цитата Сообщение от TheTangro Посмотреть сообщение
Вот немного подправленный, правильный код.
Не порти код.
Добавлено через 1 минуту
Цитата Сообщение от TheTangro Посмотреть сообщение
а строки нельзя присваивать друг другу простым "="
Там строки никто и не присваивает, указатели присваиваются.
0
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
16.10.2016, 22:08  [ТС] 15
А нельзя ведь указатели присваивать, он же удаляться должен. А получается, что создать-то его мы создали, а удалить не удалили.

Добавлено через 1 минуту
В итоге получим:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
    char ch;
    os.get(ch);
    if (os)
    {
 
        os.putback(ch);
        int count = os.rdbuf()->in_avail();
        char* str = new char[count];
 
        os.getline(str, count);
 
        if (os)
        {
            delete[] obj.s;
            obj.s = new char[strlen(str)+1];
            strcpy(obj.s, str);
        }
        else
        {
            os.clear();
            os.ignore(os.rdbuf()->in_avail());
        }
        delete[] str;
    }
    return os;
}
Ведь str мы удаляли только в одной ветке условия
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
16.10.2016, 22:11 16
Цитата Сообщение от TheTangro Посмотреть сообщение
А нельзя ведь указатели присваивать, он же удаляться должен. А получается, что создать-то его мы создали, а удалить не удалили.
Не путай указатели, и то, на что они указывают. Ничего в моём коде добавлять и исправлять не нужно, там всё правильно сделано.

Добавлено через 1 минуту
Цитата Сообщение от TheTangro Посмотреть сообщение
В итоге получим:
В итоге получили, что два раза одно и то же делаем.
0
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
16.10.2016, 22:13  [ТС] 17
Я не путаю. В коде, который указали вы в ветке if строка не удалялась. Она висела в динамической памяти и все работало.
Но:
1. Выделенную память всегда нужно очищать.
2. Строки так присваивать нельзя, точнее можно, но тогда мы будем обращаться к одному и тому же участку памяти. И изменив одну строку - изменится и вторая.
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
16.10.2016, 22:13 18
Цитата Сообщение от TheTangro Посмотреть сообщение
char* str = new char[count];
os.getline(str, count);
Один раз выделили память, прочитали туда строку.
Цитата Сообщение от TheTangro Посмотреть сообщение
obj.s = new char[strlen(str)+1];
* * * * * * strcpy(obj.s, str);
Второй раз выделили память, скопировали туда строку. И смысл?
0
-3 / 2 / 4
Регистрация: 24.09.2015
Сообщений: 98
16.10.2016, 22:15  [ТС] 19
Эм, но ведь в первом случае выделяется память под str, а в другом под строку в объекте obj.
0
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
16.10.2016, 22:20 20
Цитата Сообщение от TheTangro Посмотреть сообщение
Я не путаю. В коде, который указали вы в ветке if строка не удалялась. Она висела в динамической памяти и все работало.
Но:
1. Выделенную память всегда нужно очищать.
2. Строки так присваивать нельзя, точнее можно, но тогда мы будем обращаться к одному и тому же участку памяти.
TheTangro, ты если не понимаешь, как код работает, то не спорь, а сначала разберись.

Добавлено через 55 секунд
Цитата Сообщение от TheTangro Посмотреть сообщение
Эм, но ведь в первом случае выделяется память под str, а в другом под строку в объекте obj.
Это я вижу. Вопрос: зачем второй раз выделяется?

Добавлено через 4 минуты
Смотри: память выделена, строка прочитана. Теперь просто достаточно, указателю в объекте, присвоить адрес памяти, куда была прочитана строка(предварительно освободив старую память). Можно было сразу выделить память под указатель в объекте, но тут обрабатываются возможные ошибки при чтении.
Никаких утечек памяти в моём коде нет.
0
16.10.2016, 22:20
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
16.10.2016, 22:20
Помогаю со студенческими работами здесь

Организация вычислений во время ввода данных
Известны оценки каждого из учеников класса по физике. Посчитать количество пятерок, количество...

Организация вычислений во время ввода данных
Дано натуральное число. Верно ли, что произведение его цифр меньше а, а само число делить на в?

Организация вычислений во время ввода данных
Известны оценки каждого из учеников класса по физике. Посчитать количество пятерок, количество...

Организация ввода и вывода одномерных массивов в турбо С
При поступлении в вуз абитуриенты, получившие двойку на первом экзамене, ко второму не...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru