Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.75/16: Рейтинг темы: голосов - 16, средняя оценка - 4.75
0 / 0 / 0
Регистрация: 16.05.2016
Сообщений: 45
1

Передача по ссылке

01.08.2019, 12:45. Показов 2995. Ответов 31

Задание №8 из книги "Объектно-ориентированное программирование в С++", 4-е издание, Роберт Лафоре, 2004г.
В некоторых компьютерных языках, таких, как Visual Basic, есть операции, с помощью которых можно выделить
часть строки и присвоить её другой строке. (В стандартном классе string предложены различные подходы.)
Используя наследование, добавьте такую возможность в класс Pstring из упражнения 2. В новом производном
классе Pstring2 разместите три новых функции: left(), mid() и right().

C++
1
2
3
4
5
6
s2.lef( s1, n )    // в строку s2 помещаются n самых левых
           // символов строки s1
s2.mid( s1, s, n ) // в строку s2 помещаются n символов из 
                   // строки, начиная с символа номер s
s2.right( s1, n )  // в строку s2 помещаются n самых правых
           // символов строки s1
Вы можете использовать цикл for для копирования символ за символом подходящих частей строки s1 во
временный объект класса Pstring2, который затем их возвратит. Для получения лучшего результата используйте
в этих функциях возврат по ссылке, чтобы они могли быть использованы с левой стороны знака "равно" для
изменения существующей строки.

Мой код:
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
// task8.1.cpp
// date: Thu 04 Jul 2019 08:36:36 PM EEST
// source: page 409 from Lafore handbook, part 9
#include <iostream>
#include <string.h> // for "str*" functions
using namespace std;
////////////////////
enum { SZ = 80 };
class String
{
protected:    
    char str [ SZ ];
public:
    String()
    { str[ 0 ] = '\x0'; }
    String( char s [] )
    { strcpy( str, s ); }
    void display() const
    { cout << str; }
    operator char*()
    { return str; }
};
////////////////////
class Pstring : public String
{
public:
    Pstring(): String()
    { }
        Pstring( const char st [] )
        {
            if( strlen(st) < SZ ){
               // String::String( st );
                strcpy( str, st );
            }
            else{
                for(size_t i = 0; i < SZ-2; i++ ){
                    str[i] = st[i];
                    str[ SZ-1 ] == '\0';
                }
            }
        }
};
//////////////////////
class Pstring2 : public Pstring
{
    private:
    public:
        Pstring2(): Pstring()
        { }
        Pstring2( const char st []): Pstring(st)
        { }
        char*  left( Pstring2 sourceString, size_t number)
        {
            size_t begin = strlen(str);
        // check if size of copying string correspond to 
        // free place in old string
            if( SZ - 2 - begin > number){
        // then copy
                for(size_t i=0; i < number; begin++, i++){
                    str[begin] = sourceString.str[i];
                }
                str[begin+number] == '\0';
            }else{
                cout << "\n Your string "
                     << "does not tuck on "
                     << "initial string."
                     << "\nError!\n";
            }
            return str;
        }
        char* mid(Pstring2 obj, size_t beg, size_t number)
        {
            size_t begin = strlen(str);
            if(SZ - 1 - begin > number){
                for(size_t i = begin, j = beg; i < number; i++, j++){
                    str[i] = obj.str[j];
                }
                str[number] = '\0';
            }
            else{
                cout << "\n Your string "
                     << "does not tuck on "
                     << "initial string."
                     << "\nError!\n";
            }
            return str;
        }
        char* right(Pstring2 obj, size_t num)
        {
            size_t tmpSize = strlen(obj.str);
            size_t begin = strlen(str);
            size_t theEnd = begin+num;
            size_t start = tmpSize - 1 - num;
            if( SZ - 2 - begin > num){
                for(begin, start; begin < theEnd; begin++, start++){
                    str[begin] = obj.str[start];
                    tmpSize--;
                }
                str[begin+num] == '\0';
            }else{
                cout << "\n Your string "
                     << "does not tuck on "
                     << "initial string."
                     << "\nError!\n";
            }
 
            return str;
        }
        void clear()
        {
            for(size_t i = 0; i < SZ; i++){
                str[i] = '\0';
            }
        }
        size_t getStrSize()
        {
            return strlen(str);
        }
};
//////////////////////
int main()
{
    Pstring ps1("New constructorFrom inheritance class will copy to string SZ-1 characters onlyBut this is not a rule.");
    Pstring obj1("There is a very long string which must be "
"copied to the char array. And then suddenly arise a buffer overflow "
"error.");
    Pstring obj2("Kurz Sentenzen (de).");
     
    cout << endl;
    //////////////////
    Pstring2 obj3("This object of class Pstring2 demonstrate us a long string.");
    Pstring2 obj4("Not so long string.");
    Pstring2 obj6("Object6 very VEry VERy VERY long string could not tuck on initial string and you will have stack overflow if you will try to copy it there...");
 
    //////////////////
    cout << "\nObj3: ";
    obj3.display();
    cout << "\nObj3 size: " <<
    obj3.getStrSize();
    Pstring2 obj5;
    obj5 = obj3.left(obj6, 13);
    cout << "\nobj3.left(obj6, 30) results >> \n";
    obj5.display();
    cout << "\nClearing obj5...\n";
    obj5.clear();
    obj5.display();
    obj3.clear();
    obj3.display();
    cout << '\n';
    obj5 = obj3.mid(obj6, 18, 78);
    obj5.display();
    obj5.clear();
    cout << "\n test right...\n";
    cout << "\nClearing obj5...\n";
    obj5.clear();
    cout << "\nObj5: ";
    obj5.display();
    obj5 = obj4.right(obj6, 15);
    cout << "\nobj4.right(obj6, 15) results >> \n";
    obj5.display();
    cout << "\nClearing obj5...\n";
    obj5.clear();
    obj5 = obj4.right(obj6, 65);
    // test functions on the left side of "=" sign
    cout << "\ntest functions on the left side of \"=\" sign\n";
    obj5.clear();
/*    % g++ task8.1.cpp -o task8.1.exe 
        task8.1.cpp: In function ‘int main()’:
        task8.1.cpp:169:28: error: lvalue required as left operand of assignment
            obj5.right(obj6, 30) = obj4; // does not compile, want lvalue
    */
//    obj5.right(obj6, 30) = obj4; // does not compile, want lvalue
    obj5.display();
 
    return 0;
}
Повторно прочитал задание и теперь у меня появились сомнения, что мой код соответствует заданию.
Если делать через временный объект:

C++
1
2
3
4
5
6
7
8
9
10
11
...
Pstring2& left(Pstring2 obj, int num)
{
        Pstring2 tmp;
        tmp.str = str;
        ...
        for(size_t i=0; i < number; begin++, i++){
                    tmp.str[begin] = sourceString.str[i];
        ...
        return tmp;
}
То после выхода из функции left() по ссылке будет возвращать мусор. В моем же коде не используется
временный объект. И эти функции я не могу использовать слева от знака равно "=". Можно еще создать
глобальный объект класса Pstring2. Тогда будет работать передача по ссылке, можно использовать
слева от знака равно, но глобальный объект != временный объект.
Заранее спасибо.
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
01.08.2019, 12:45
Ответы с готовыми решениями:

Передача по ссылке
С помощью функции rand() округлить значение double и передать его по ссылке.

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

Передача по ссылке
Здравствуйте. 1.typedef struct { MATRIXX_LENTA&lt;double&gt;* MATR; //Ленточная матрица }...

Передача массива по ссылке
Как правильно передавать двумерный статический массив в мои функции? #include &lt;iostream&gt; #include...

31
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
01.08.2019, 16:03 21
Лучший ответ Сообщение было отмечено НовыйПетрович как решение

Решение

Цитата Сообщение от НовыйПетрович Посмотреть сообщение
Нигде до этого задания в книге автор не объясняет указатели *this -> мы такое не изучали... Поэтому вопрос
Тогда вот так
C++
1
Pstring &left(Pstring &s,  ......) {.....; return s;}
Других способов нет
1
0 / 0 / 0
Регистрация: 16.05.2016
Сообщений: 45
01.08.2019, 16:17  [ТС] 22
Походу это будет лучший вариант. Мой код нельзя использовать слева от знака равно.
С этим разобрались.
Тогда какую другую книгу посоветуете? Имеет ли смысл бросать эту или сделать это задание как вы посоветовали и идти дальше. Все-таки здесь 9 глав закончил.

Добавлено через 4 минуты
Объясните почему здесь https://en.wikipedia.org/wiki/Most_vexing_parse
TimeKeeper time_keeper(Timer());
Вызывается конструктор чужого, никак не связанного класса?
0
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
01.08.2019, 16:22 23
Цитата Сообщение от НовыйПетрович Посмотреть сообщение
TimeKeeper time_keeper(Timer());
Вызывается конструктор чужого, никак не связанного класса?
Это не конструктор вызывается, это создаётся экземпляр класса Timer и передаётся параметром в конструктор TimeKeeper

Цитата Сообщение от НовыйПетрович Посмотреть сообщение
Имеет ли смысл бросать эту или сделать это задание как вы посоветовали и идти дальше. Все-таки здесь 9 глав закончил.
Чувствую, лучше бросать. Слабовато как-то для 9-ти глав (Хотя, я уже и не помню когда последний раз эти книги читал).
0
0 / 0 / 0
Регистрация: 16.05.2016
Сообщений: 45
01.08.2019, 16:27  [ТС] 24
А есть такие книги, которые вы читали, и можете сказать, что там минимум ошибок?
0
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
01.08.2019, 16:30 25
Цитата Сообщение от НовыйПетрович Посмотреть сообщение
А есть такие книги, которые вы читали, и можете сказать, что там минимум ошибок?
Есть, наверное. Сам я читал их 20 лет назад, поэтому мне сложно что-то посоветовать.
Литература C++
0
0 / 0 / 0
Регистрация: 16.05.2016
Сообщений: 45
01.08.2019, 16:36  [ТС] 26
Мне не сложно взять любую другую. Но именно так я выбрал Лафоре. И сейчас вы мне говорите, что автор учит плохому (это слышу не в первый раз, но во второй - повод задуматься). Где гарантия, что следующий случайно выбранный автор в своей книге допустил меньше ошибок, чем Лафоре?
0
6738 / 4537 / 1839
Регистрация: 07.05.2019
Сообщений: 13,725
Записей в блоге: 1
01.08.2019, 16:40 27
Цитата Сообщение от НовыйПетрович Посмотреть сообщение
Мне не сложно взять любую другую. Но именно так я выбрал Лафоре. И сейчас вы мне говорите, что автор учит плохому (это слышу не в первый раз, но во второй - повод задуматься). Где гарантия, что следующий случайно выбранный автор в своей книге допустил меньше ошибок, чем Лафоре?
Это не я говорил, это DrOffset.

Начни со Страуструпа что-ли.
1
4340 / 2398 / 995
Регистрация: 07.02.2019
Сообщений: 6,289
01.08.2019, 16:44 28
НовыйПетрович, советую "Базовый курс" Липпмана. Очень грамотно в плане преподнесения информации, все по полочкам разложено. Сам её сейчас читаю, что бы закрепить и дополнить знания, полученные после прочтения
"Programming: Principles and Practice Using C++" Страуструпа и из др. источников. Вторая довольно сумбурная и местами тяжеловата для новичка, но автор не абы кто(хотя все же не преподаватель), тоже очень полезная. Дальше Мейерса планирую читать.
1
Azazel-San
01.08.2019, 16:57
  #29

Не по теме:

Цитата Сообщение от DrOffset Посмотреть сообщение
Если автор книги (с учетом предоставленных материалов оригинала(!) книги на английском) имел в виду что-то другое, то он просто бредит.
Эт получается у Лафоре плохая книжка?
А ее еще многим советуют..

0
zayats80888
01.08.2019, 17:05
  #30

Не по теме:

Цитата Сообщение от Azazel-San Посмотреть сообщение
Эт получается у Лафоре плохая книжка?
Помимо упомянутого он в том же конструкторе строчкой выше пишет str[j] = '\0'; в то время когда j уже не доступна.

0
15133 / 8128 / 1964
Регистрация: 30.01.2014
Сообщений: 13,814
01.08.2019, 21:32 31
Цитата Сообщение от НовыйПетрович Посмотреть сообщение
Вы согласны, что это правильно?
Это правильно.

Цитата Сообщение от НовыйПетрович Посмотреть сообщение
огда объясните мне, почему, когда мы добавляем проверку, то "создается временный безымянный объект, который нельзя использовать"? Чем это не возвращение к предыдущему варианту инициализации?
Тем, что вы пишете выражение String(s) не в списке инициализации (не после двоеточия и не до открывающей скобки).
В С++ много контекстно-зависимых семантик. Поэтому выражениеString(s) может иметь совершенно разный смысл в зависимости от того, где вы его напишете и чем при этом будут являться String и s.

Цитата Сообщение от НовыйПетрович Посмотреть сообщение
Все запустилось, но никакого текста нет.
Именно так. Текста нет. Потому что нужная инициализация базового класса не была запущена.

Цитата Сообщение от НовыйПетрович Посмотреть сообщение
Я бы хотел посмотреть как удаляется этот объект.
Можете объявить деструктор и поставить там точку останова.
Я также хочу заметить, что в данном случае, из-за most vexing parse объект будет не безымянный, а именованный. String(s); в данном контексте полностью эквивалентно String s;, правда на неправильность происходящего это не влияет.

Добавлено через 1 минуту
Цитата Сообщение от Azazel-San Посмотреть сообщение
Эт получается у Лафоре плохая книжка?
А ее еще многим советуют..
Да, плохая. На форуме есть по крайней мере еще 4 разных темы, где выяснилось, что в книге подается откровенная дезинформация.

Добавлено через 1 минуту
Цитата Сообщение от НовыйПетрович Посмотреть сообщение
Мне не сложно взять любую другую.
Здесь есть целая прикрепленная тема. Выберите там, что понравится. Липпман - отличный вариант.

Добавлено через 3 часа 33 минуты
НовыйПетрович, вообще странно читать от вас удивление по поводу этого, когда вы уже с таким сталкивались:
Точка с запятой после структуры, перечисления, класса
1
Комп_Оратор)
Эксперт по математике/физике
8719 / 4428 / 598
Регистрация: 04.12.2011
Сообщений: 13,276
Записей в блоге: 16
02.08.2019, 14:21 32
НовыйПетрович, очень мутно, написано. Я бы (без проверок и пр.) что-то такое наваял:
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
#include <iostream>
#include <string.h>
using namespace std;
 
enum { SZ = 80 };
class String
{
protected:
    char str [ SZ ];
public:
    String()
    { str[ 0 ] = '\x0'; }
    String( char s [] )
    { strcpy( str, s ); }
 
    void display() const
    { cout << str; }
    operator char*()
    { return str; }
};
class Pstring : public String
{
  public:
Pstring()
:String()
{}
Pstring(char *s)
:String(s)
{}
Pstring(const Pstring &rhs)
{strcpy( str, rhs.str);}
 
Pstring &left(const Pstring &rhs, int n)
{
    Pstring tmp(rhs);
    tmp.str[n]='\0';
    strcat(tmp.str, str);
swap(*this, tmp);
return *this;
}
};
 
using namespace std;
 
int main()
{
   Pstring ptarg("world!"), source("Hello friend");
   ptarg.left(source, 6).left(source, 6);
   ptarg.display();
 
    return 0;
}
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.08.2019, 14:21

Передача объекта по ссылке
В книге Шилдта есть задание: #include &lt;iostream&gt; #include &lt;cstring&gt; #include &lt;cstdlib&gt; ...

Передача вектора по ссылке
Делаю задание Страуструпа на шаблоны, но столкнулся с тем что передавая вектор по ссылке он...

Передача объекта по ссылке
Не работает передача константы по ссылке. Ошибка: &quot;error: passing ‘const std::allocator&lt;int&gt;’ as...

Передача параметра по ссылке
Здравствуйте! Подскажите пожалуйста! Делаю пример из книги: #include &lt;iostream&gt; #include...


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

Или воспользуйтесь поиском по форуму:
32
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.