Форум программистов, компьютерный форум CyberForum.ru

Классы строк, массивы преобразование и т.д - C++

Восстановить пароль Регистрация
 
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
09.06.2013, 17:53     Классы строк, массивы преобразование и т.д #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
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
#include <iostream> 
 #include <string.h> 
 using namespace std; 
 
 // Rudimentary string class 
 class String 
 { 
 public: 
 // constructors 
 String(); 
 String(const char *const); 
 String(const String &); 
 ~String(); 
 
 // overloaded operators 
 char & operator[](unsigned short offset); 
 char operator[](unsigned short offset) const; 
 String operator+(const String&); 
 void operator+=(const String&); 
 String & operator= (const String &); 
 
 // General accessors 
 unsigned short GetLen()const { 
 return itsLen; 
} 
 const char * GetString() const { 
 return itsString; 
} 
 
 private: 28: String (unsigned short); // private constructor 
 char * itsString; 
 unsigned short itsLen; 
}; 
 // default constructor creates string of 0 bytes 
 String::String() 
 { 
 itsString = new char[1]; 
 itsString[0] = '\0'; 
 itsLen=0; 
} 
 // private (helper) constructor, used only by 
 // class methods for creating a new string of 
 // required size. Null filled. 
 String::String(unsigned short len) 
 { 
 itsString = new char[len+1]; 
 for (unsigned short i = 0; i<=len; i++) 
 itsString[i] = '\0'; 
 itsLen=len; 
} 
 // Converts a character array to a String 
 String::String(const char * const cString) 
 { 
 itsLen = strlen(cString); 
 itsString = new char[itsLen+1]; 
 for (unsigned short i = 0; i itsString[i] = cString[i]; 
 itsString[itsLen]='\0'; 
} 
 63:// copy constructor 
 String::String (const String & rhs) 
 { 
 itsLen=rhs.GetLen(); 
 itsString = new char[itsLen+1]; 
 for (unsigned short i = 0; i itsString[i] = rhs[i]; 
 itsString[itsLen] = '\0'; 
} 
 // destructor, frees allocated memory 
 String::~String () 
 { 
 delete [] itsString; 
 itsLen = 0; 
} 
 // operator equals, frees existing memory 
 // then copies string and size 
 String& String::operator=(const String & rhs) 
 { 
 if (this == &rhs) 
 return *this; 
 delete [] itsString; 
 itsLen=rhs.GetLen(); 
 itsString = new char[itsLen+1]; 
 for (unsigned short i = 0; i itsString[i] = rhs[i]; 
 itsString[itsLen] = '\0'; 
 return *this; 
} 
 //nonconstant offset operator, returns 
 // reference to character so it can be 
 // changed! 
 char & String::operator[](unsigned short offset) 
 { 
 if (offset > itsLen) 
 return itsString[itsLen-1]; 
 else 
 return itsString[offset]; 
} 
 // constant offset operator for use 
 // on const objects (see copy constructor!) 
 char String::operator[](unsigned short offset) const 
 { 
 if (offset > itsLen) 
 return itsString[itsLen-1]; 
 else 
 return itsString[offset]; 
} 
 // creates a new string by adding current 
 // string to rhs 
 String String::operator+(const String& rhs) 
 { 
 unsigned short totalLen = itsLen + rhs.GetLen(); 
 String temp(totalLen); 
 unsigned short i; 
 for ( i= 0; i temp[i] = itsString[i]; 
 for (unsigned short j = 0; j temp[i] = rhs[j]; 
 temp[totalLen]='\0'; 
 return temp; 
} 
 // changes current string, returns nothing 
 void String::operator+=(const String& rhs) 
 { 
 unsigned short rhsLen = rhs.GetLen(); 
 unsigned short totalLen = itsLen + rhsLen; 
 String temp(totalLen); 
 unsigned short i; 
 for (i = 0; i temp[i] = itsString[i]; 
 for (unsigned short j = 0; j temp[i] = rhs[i-itsLen]; 
 temp[totalLen]='\0'; 
 *this = temp; 
} 
 int main() 
 { 
 String s1("initial test"); 
 cout << "S1:\t" << s1.GetString() << endl; 
 
 char * temp = "Hello World"; 
 s1 = temp; 
 cout << "S1:\t" << s1.GetString() << endl; 
 
 char tempTwo[20]; 
 strcpy(tempTwo, "; nice to be here!"); 
 s1 += tempTwo; 
 cout << "tempTwo:\t" << tempTwo << endl; 
 cout << "S1:\t" << s1.GetString() << endl; 
 
 cout << "S1[4]:\t" << s1[4] << endl; 
 s1[4]='x'; 
 cout << "S1:\t" << s1.GetString() << endl; 
 
 cout << "S1[999]:\t" << s1[999] << endl; 
 
 String s2(" Another string"); 
 String s3; 
 s3 = s1+s2; 
 cout << "S3:\t" << s3.GetString() << endl; 
 
 String s4; 
 s4 = "Why does this work?"; 
 cout << "S4:\t" << s4.GetString() << endl; 
 return 0; 
}


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

Кликните здесь для просмотра всего текста
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
#include <iostream> 
 
class LINE
 
{
public:
LINE()
{
stroka = new char[1];
stroka[0] = '\0';
dlinna_stroki = 0;
}
 
LINE(char *massiv)
{
dlinna_stroki = strlen(massiv);
stroka = new char[dlinna_stroki + 1];
 
for (int a = 0; a < dlinna_stroki; a++)
{ stroka[a] = massiv[a]; }
stroka[dlinna_stroki] = '\0';
}
 
~LINE()
{
delete[] stroka;
dlinna_stroki = 0;
}
 
int get_dlinna_stroki() const 
{  
return dlinna_stroki;
}
 
char *get_stroka() const 
{ 
return stroka; 
}
 
LINE operator= (const LINE & rhs)
{
delete[] stroka;
int w = rhs.get_dlinna_stroki();
stroka = new char[w];
for(int i=0; i < w; i++)
{
stroka[i] = rhs.stroka[i];
}
return stroka;
}
 
 
private:
 
char *stroka;
int dlinna_stroki;
 
};
 
 
 
int main()
 
{
LINE strOne("Hello world");
 
std::cout << strOne.get_stroka() << "\n";
 
LINE strTwo("Nice day");
std::cout << strTwo.get_stroka() << "\n";
strTwo = strOne;
std::cout << strTwo.get_stroka() << "\n";
 
system("pause");
return 0;
}


Проблема у меня возникла с operator=, сам метод описан в строках 40-50, а применяется он в строках 69-72.
По моему разумению мой operator= работает следующим образом:

42. Удаляется существующий массив stroka т.е. массив stroka объекта strOne
43. Создаем переменную и присваиваем ей значение равное длине элементов во втором массиве, т.е. в массиве stroka объекта strTwo
44. Выделяем память под новый массив stroka объекта strOne, длинна этого массива равна длине массива stroka объекта strTwo
45-48. Мы копируем из массива stroka объекта strTwo в новый массив stroka объекта strOne каждый элемент.
49. Возвращаем новый массив.

Программа работает, но не совсем корректно, после Hello world появляются какие то непонятные символы, вот скриншот:

Классы строк, массивы преобразование и т.д

я менял метод operator= на вот такое:

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
LINE &operator= (const LINE & rhs)
{
delete[] stroka;
int w = rhs.get_dlinna_stroki();
stroka = new char[w];
for(int i=0; i < w; i++)
{
stroka[i] = rhs.stroka[i];
}
return *this;
}


результат тот же, в чем проблема?

PS я не силен в терминах, если можно объясните пожалуйста попроще.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
rangerx
1908 / 1517 / 139
Регистрация: 31.05.2009
Сообщений: 2,876
09.06.2013, 19:16     Классы строк, массивы преобразование и т.д #2
Вы забываете про символ '\0' при копировании строки(то, что вы сделали во второй версии конструктора). А вообще, более корректно было бы сделать так
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
LINE& operator= (const LINE& rhs)
{
    // проверяем не присваивается ли объект самому себе
    if(&rhs == this)
        return *this;
 
    // сначала пробуем выделить память
    // (Здесь может возникнуть исключение(ошибка). До этого момента важно не менять состояние(поля) объекта...
    // ...чтобы после обработки исключения он не оказался в некоррекном состоянии)
    char* tmp = new char[rhs.dlinna_stroki + 1]; 
 
    // если предыдущая строка выполнилась нормально, освобождаем память
    delete[] stroka; 
 
    // копируем новое содержимое в только что выделенную область памяти...
    // ...и присваиваем указатель на неё указателю strokа
    stroka = strcpy(tmp, rhs.stroka);
 
    dlinna_stroki = rhs.dlinna_stroki;
 
    // возвращаем ссылку на самого себя(стандартное поведение оператора =)
    return *this; 
}
И исправьте
C++
1
LINE(char *massiv)
C++
1
char *get_stroka() const
на
C++
1
LINE(const char *massiv)
C++
1
const char *get_stroka() const
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
09.06.2013, 19:41  [ТС]     Классы строк, массивы преобразование и т.д #3
C++
1
2
3
4
int w = 1 + rhs.get_dlinna_stroki();
stroka = new char[w];
...
stroka[w-1] = '\0';
Спасибо, помогло

Добавлено через 3 минуты
Цитата Сообщение от rangerx Посмотреть сообщение
И исправьте
...
на
До этого скоро дело дойдет и я создам тему т.к. я не сильно понимаю в чем разница между

C++
1
2
3
void const fun();
const void fun2();
void fun3() const;
и тоже самое с * и &, что будет от перемены мест этих "символов"
MrGluck
Ворчун
Эксперт С++
 Аватар для MrGluck
4920 / 2663 / 243
Регистрация: 29.11.2010
Сообщений: 7,404
09.06.2013, 21:18     Классы строк, массивы преобразование и т.д #4
Цитата Сообщение от VLK Посмотреть сообщение
void const fun();
const void fun2();
void fun3() const;
1 и 2 идентичны, в 3 функция не изменяет состояние объекта (накладывается const на this).
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
10.06.2013, 23:40  [ТС]     Классы строк, массивы преобразование и т.д #5
Новый вопрос по этой же программе:

Кликните здесь для просмотра всего текста
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
#include <iostream> 
 
class LINE
{
public:
LINE()
{
stroka = new char[1];
stroka[0] = '\0';
dlinna_stroki = 0;
}
 
LINE(char *massiv)
{
dlinna_stroki = strlen(massiv);
stroka = new char[dlinna_stroki + 1];
 
for (int a = 0; a < dlinna_stroki; a++)
{ stroka[a] = massiv[a]; }
stroka[dlinna_stroki] = '\0';
}
 
~LINE()
{
delete[] stroka;
dlinna_stroki = 0;
}
 
int get_dlinna_stroki() const 
{  
return dlinna_stroki;
}
 
char *get_stroka() const 
{ 
return stroka; 
}
 
char operator[] (int b) const
{
if (b > dlinna_stroki)
{ return stroka[dlinna_stroki - 1];  }
else
{ return stroka[b]; }
 
}
 
char & operator[] (int e)
{
if (e > dlinna_stroki)
{ return stroka[dlinna_stroki - 1];  }
else
{ return stroka[e]; }
 
}
 
LINE & operator= (const LINE & rhs)
{
if (this == &rhs)
{ return *this; }
else
{
delete[] stroka;
int w = 1 + rhs.get_dlinna_stroki();
stroka = new char[w];
for(int i=0; i < w; i++)
{
stroka[i] = rhs.stroka[i];
}
stroka[w-1] = '\0';
return *this;
}
}
 
LINE operator+ (const LINE & rhs)
{
int obsh_dlinna = dlinna_stroki + rhs.get_dlinna_stroki();
LINE temp(obsh_dlinna + 1);
int n;
for (n = 0; n < dlinna_stroki; n++)
{ temp[n] = stroka[n]; }
 
for (int v = 0; v < rhs.get_dlinna_stroki(); v++, n++)
{ temp[n] = rhs[v]; } 
temp[obsh_dlinna] = '\0';
return temp;
}
 
private:
LINE(int k)
{
stroka = new char[k + 1];
for (int i = 0; i < k; i++)
{
stroka[i] = '\0';
}
dlinna_stroki = k;
}
 
char *stroka;
int dlinna_stroki;
};
 
 
int main()
{
LINE strOne("Hello world");
 
std::cout << strOne.get_stroka() << "\n";
 
LINE strTwo("Nice day");
std::cout << strTwo.get_stroka() << "\n";
    
LINE strThree;
strThree = strOne + strTwo;
 
std::cout << strThree.get_stroka() << "\n";
    
system("pause");
return 0;
}


подскажите в чем косяк, строка 115 не выполняется, а точнее программа запускается потом критическая ошибка

Добавлено через 6 минут
И еще вопрос, что делают эти методы: char operator[] (int b) const и char & operator[] (int e)
faLek
99 / 100 / 7
Регистрация: 06.03.2012
Сообщений: 478
11.06.2013, 00:33     Классы строк, массивы преобразование и т.д #6
Цитата Сообщение от VLK Посмотреть сообщение
И еще вопрос, что делают эти методы: char operator[] (int b) const и char & operator[] (int e)
перегружают оператор [] для работы с символьным массивом...

Добавлено через 2 минуты
Цитата Сообщение от VLK Посмотреть сообщение
char & operator[] (int e)
{
if (e > dlinna_stroki)
{ return stroka[dlinna_stroki - 1]; *}
else
{ return stroka[e]; }
а вот этот кусочек добавлен ,чтобы ты мог использовать перегруженный оператор,как слева так и справа от оператора присваивания...
BumerangSP
 Аватар для BumerangSP
4283 / 1405 / 121
Регистрация: 16.12.2010
Сообщений: 2,941
Записей в блоге: 3
11.06.2013, 00:45     Классы строк, массивы преобразование и т.д #7
VLK, как все тяжко, можно ведь и проще. Вот код для функции operator +:
C++
1
2
3
4
5
6
7
LINE operator + (const LINE & rhs)
{
    char temp[100] = {0};
    strcat(temp, this->stroka);
    strcat(temp, rhs.stroka);
    return LINE(temp);
}
VLK
 Аватар для VLK
192 / 161 / 12
Регистрация: 05.05.2013
Сообщений: 1,221
11.06.2013, 11:54  [ТС]     Классы строк, массивы преобразование и т.д #8
BumerangSP, Спасибо, а можно решить данную проблему без использования функции strcat, т.к. я в изучение C++ еще до него не дошел, по этому хотелось бы решить сложно, но самыми простыми средствами.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.06.2013, 12:16     Классы строк, массивы преобразование и т.д
Еще ссылки по теме:

C++ Классы с++ vs глобальные массивы
Преобразование строк C++
C++ Массивы. Классы. Нахождение среднего значения дробей

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

Или воспользуйтесь поиском по форуму:
BumerangSP
 Аватар для BumerangSP
4283 / 1405 / 121
Регистрация: 16.12.2010
Сообщений: 2,941
Записей в блоге: 3
11.06.2013, 12:16     Классы строк, массивы преобразование и т.д #9
VLK, замена strcat. Лучше бы это оформить в виде функции, но пусть пока так будет.
C++
1
2
3
4
5
int i = 0;
while(*this->stroka)
    temp[i++] = *this->stroka++;
while(*rhs.stroka)
    temp[i++] = *rhs.stroka++;
Yandex
Объявления
11.06.2013, 12:16     Классы строк, массивы преобразование и т.д
Ответ Создать тему
Опции темы

Текущее время: 16:47. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru