Where is the Segmentation Fault?

SO I've been writing a custom string class for school, and I've been getting a couple of segmentation faults, and I'm having trouble finding where they are.

If you guys could help me with that and help me fix them, it would help a lot.
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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
  #include "mystring.h"
#include <iostream>
#include <cstring>

/*
    char * str; // pointer to a dynamic array of chars
    unsigned int size;   // holds the size of the  dynamic array
*/

// Standard Constructors
MyString::MyString()
// Empty String
{
    size = 0;
    str = new char[size+1];    // null pointer, no data yet
    str[0] = '\0';
}
MyString::MyString(const char * s)
// conversion from c-string
{
    size = strlen(s);       // set size to length of c-cstring s
    str = new char[size+1];   // allocate enough space to store s
    strcpy(str, s);
}
MyString::MyString(int n)
// conversion from int
{
    int n2 = n;

    int digits = 0;
    while (n != 0)
    {
        n = n / 10;
        ++digits;
    }
    size = digits;

    str = new char[size+1];

    for (int i = size-1; i >= 0; i--)
    {
        str[i] = (n2 % 10) + '0';
        n2 = n2 / 10;
    }

    str[size] = '\0';
}
MyString::~MyString()
// destructor for final clean up
{
    delete [] str;
}
MyString::MyString(const MyString& s)
// copy constructor (for deep copy)
{
    size = s.size;
    str = s.str;

    str = new char[size+1];

    for (int i = 0; i <= size; i++)
    {
        str[i] = s.str[i];
    }
}
MyString& MyString::operator=(const MyString& s)
// Assignment operator (for deep copy)
{
    if (this != &s)
    {
        delete [] str;

        size = s.size;
        str = s.str;

        str = new char[size+1];

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

    return * this;
}

// I/O Functions
ostream& operator<< (ostream& os, const MyString& s)
// << operator overload
{
    os << s.str;

    return os;
}
istream& operator>> (istream& is, MyString& s)
// << operator overload
{
    int max = 1;
    int index = 0;
    char * buffer =  new char[max];

    while (isspace(is.peek()))
    {
        is.ignore();
    }

    while (!isspace(is.peek()))
    {
        char * tempstr = new char[max + 1];
        buffer[index] = is.get();

        for(int i = 0; i < max; i++)
        {
            tempstr[i] = buffer[i];
        }

        index++;
        max++;
        delete [] buffer;
        buffer = tempstr;
    }

    buffer[index] = NULL;
    delete [] s.str;
    s.str = buffer;
    return is;
}
istream& getline (istream& is, MyString& s)
// getline operator overload
{
    int max = 1;
    int index = 0;
    char * buffer =  new char[max];


    while (is.peek() != '\n')
    {
        char * tempstr = new char[max + 1];
        buffer[index] = is.get();

        for(int i = 0; i < max; i++)
        {
            tempstr[i] = buffer[i];
        }

        index++;
        max++;
        delete [] buffer;
        buffer = tempstr;
    }

    is.ignore();

    buffer[index] = '\0';
    delete [] s.str;
    s.str = buffer;
    return is;
}
istream& getline (istream& is, MyString& s, char delim)
// getline (with delimiter) operator overload
{
    int max = 1;
    int index = 0;
    char * buffer =  new char[max];


    while (is.peek() != delim)
    {
        char * tempstr = new char[max + 1];
        buffer[index] = is.get();

        for(int i = 0; i < max; i++)
        {
            tempstr[i] = buffer[i];
        }

        index++;
        max++;
        delete [] buffer;
        buffer = tempstr;
    }

    is.ignore();

    buffer[index] = '\0';
    delete [] s.str;
    s.str = buffer;
    return is;
}

// Comparison Operators
bool operator< (const MyString& x, const MyString& y)
// < operator overload
{
    return strcmp(x.str, y.str) < 0;
}
bool operator> (const MyString& x, const MyString& y)
// > operator overload
{
    return strcmp(x.str, y.str) > 0;
}
bool operator<=(const MyString& x, const MyString& y)
// <= operator overload
{
    return strcmp(x.str, y.str) <= 0;
}
bool operator>=(const MyString& x, const MyString& y)
// >= operator overload
{
    return strcmp(x.str, y.str) >= 0;
}
bool operator==(const MyString& x, const MyString& y)
// == comparison operator overload
{
    return strcmp(x.str, y.str) == 0;
}
bool operator!=(const MyString& x, const MyString& y)
// != comparison operator overload
{
    return strcmp(x.str, y.str) != 0;
}

// Concatenation Operators
MyString operator+ (const MyString& x, const MyString& y)
// Concatenation
{
    MyString combined = x;
    combined += y;
    return combined;
}
MyString& MyString::operator+=(const MyString& s)
// Concatenation/Assignment operator
{
    size = size + s.size;
    str = new char[size+1];
    strcat(str, s.str);

    return * this;
}

// Bracket Operators
char& MyString::operator[] (unsigned int index)
{
    // resize to fit index
    if (index >= size)
    {
        int resize = index - size;

        char * tempstr = new char[size+1];
        strcpy(tempstr, str);

        str[size + resize];

        for (int i = 0; i < size + resize; i ++)
        {
            str[i] = ' ';
        }
        str[size + resize] = '\0';

        return str[index];
    }
    else
    {
        return str[index];
    }
}
const char& MyString::operator[] (unsigned int index) const
{
    //if index is too big return null

    if (index >= size)
    {
        return str[size];
    }
    else
    {
        return str[index];
    }
}

// Standard Accessors
int MyString::getLength() const
// return string length
{
    return size;
}
const char* MyString::getCString() const
// return c-string equivalent
{
    return str;
}

// Substring Functions
MyString MyString::substring(unsigned int index, unsigned int length) const
{
    MyString substr = substring(index);

    if (substr.size - 1 <= length)
    {
        return substr;
    }
    else
    {
        char * tempstr = new char[length + 1];

        for (int i = 0; i < length; i++)
        {
            tempstr[i] = substr.str[i];
        }

        tempstr[length] = '\0';
        delete [] substr.str;
        substr.str = tempstr;
        substr.size = length + 1;
    }
    return substr;
}
MyString MyString::substring(unsigned int index) const
{
    MyString substr;
    int subsize = size - index;

    if (subsize <= 1)
    {
        substr.str = NULL;
        substr.size = 1;
    }
    else
    {
        char * tempstr = new char[subsize];

        for (int i = 0; i < subsize - 1; i++)
        {
            tempstr[i] = str[i + index];
        }

        tempstr[subsize - 1] = '\0';
        delete [] substr.str;
        substr.str = tempstr;
        substr.size = subsize;
    }
    return substr;
}

// insert() Function
MyString& MyString::insert(unsigned int index, const MyString& s)
// insert s into the string at position "index"
{
    MyString * half1 = reinterpret_cast<MyString *>(new char[size + s.size + 1]);
    MyString * half2 = reinterpret_cast<MyString *>(new char[size + 1]);
    MyString * tempstr = reinterpret_cast<MyString *>(new char[size + 1]);

    half1[size+s.size+1] = '\0';
    half2[size+1] = '\0';
    tempstr[size+1] = '\0';

    strcpy(reinterpret_cast<char *>(tempstr), str);

    for(int i = 0; i <= index + s.size - 1; i++)
    {
        half1[i] = tempstr[i];
    }
    strcat(reinterpret_cast<char *>(half1), s.str);
    for(int j = index + s.size; j <= size; j++)
    {
        half2[j] = tempstr[j];
    }
    strcat(reinterpret_cast<char *>(half1), reinterpret_cast<const char *>(half2));

    delete [] half1;
    delete [] half2;
    delete [] tempstr;

    return reinterpret_cast<MyString &>(half1);
}

// indexof() Function
int MyString::indexOf(const MyString& s) const
// find index of the first occurrence of s inside the string
//  return the index, or -1 if not found
{
    int index;
    bool found = false;

    if (size < s.size)
    {
        return -1;
    }
    else
    {
        for (int i = 0; i < size; i++)
        {
            if (s.str[i] == s && found == false)
            {
                i = index;
                found = true;
            }
        }

        if (found == true)
        {
            return index;
        }
        else if (found == false)
        {
            return -1;
        }
    }
}
And my .h file too:

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
#include <iostream>
using namespace std;

class MyString
{
    friend ostream& operator<< (ostream& os, const MyString& s);
    friend istream& operator>> (istream& is, MyString& s);
    friend istream& getline (istream& is, MyString& s);
    friend istream& getline (istream& is, MyString& s, char delim);

    friend MyString operator+ (const MyString& x, const MyString& y);

    friend bool operator< (const MyString& x, const MyString& y);
    friend bool operator> (const MyString& x, const MyString& y);
    friend bool operator<=(const MyString& x, const MyString& y);
    friend bool operator>=(const MyString& x, const MyString& y);
    friend bool operator==(const MyString& x, const MyString& y);
    friend bool operator!=(const MyString& x, const MyString& y);

public:
    MyString();				                    // empty string
    MyString(const char * s);		            // conversion from c-string
    MyString(int);			                    // conversion from int
    ~MyString();				                // destructor for final clean up

    MyString(const MyString& s);		        // copy constructor
    MyString& operator=(const MyString& s);     // assignment operator
    MyString& operator+=(const MyString& s);    // concatenation/assignment

    // bracket operators to access char positions
    char& operator[] (unsigned int index);
    const char& operator[] (unsigned int index) const;

    // insert s into the string at position "index"
    MyString& insert(unsigned int index, const MyString& s);

    // find index of the first occurrence of s inside the string
    //  return the index, or -1 if not found
    int indexOf(const MyString& s) const;

    int getLength() const;		                // return string length
    const char* getCString() const;	            // return c-string equivalent

    MyString substring(unsigned int, unsigned int) const;
    MyString substring(unsigned int) const;

private:
    char * str; // pointer to a dynamic array of chars
    unsigned int size;   // holds the size of the  dynamic array
};
Where is your main() and a test case that provokes a segfault?

1
2
3
4
5
6
7
8
9
MyString& MyString::operator+=(const MyString& s)
// Concatenation/Assignment operator
{
    size = size + s.size;
    str = new char[size+1];
    strcat(str, s.str);

    return * this;
}


You have an error here. You are trying to concatenate to the existing string, but you overwrite str with the value of the new memory address. The contents of this memory are unknown. You then try to concatenate to this. You need something like (not tried)

1
2
3
4
5
6
7
8
9
10
11
12
13
MyString& MyString::operator+=(const MyString& s)
// Concatenation/Assignment operator
{
    size += s.size;
    auto newstr = new char[size + 1];
    strcpy(newstr, str);
    strcat(newstr, s.str);

    delete [] str;
    str = newstr;

    return * this;
}

Last edited on
I have another segmentation fault.

Here is the main() that I've been using to test this, sorry I haven't been active on the thread.

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
#include <iostream>
using namespace std;

#include "mystring.h"

int main()
{
    MyString s1;
    MyString s2("Hello, World");
    MyString s3 = "Welcome to Florida, have a nice day";
    MyString s4 = 12345;

    cout << "s1 = " << s1 << '\n';
    cout << "s2 = " << s2 << '\n';
    cout << "s3 = " << s3 << '\n';
    cout << "s4 = " << s4 << '\n';
    cout << '\n';

    cout << "Making the calls:\n"
         << "\tcin >> s1\n"
         << "\tgetline(cin, s2, ',')\n"
         << "\tgetline(cin, s3)\n";
    cout << "Enter some sentences: ";

    cin >> s1;
    getline(cin,s2,',');
    getline(cin,s3);

    cout << "\nNew string values:\n";

    cout << "s1 = " << s1 << '\n';
    cout << "s2 = " << s2 << '\n';
    cout << "s3 = " << s3 << '\n';
    cout << "---------------------------\n";

// ----------------------------------

    s1 = "Dog";
    s2 = "Food";
    MyString result = s1 + s2;
    cout << "result = " << result << '\n';

    s1 += s2;
    cout << "s1 = " << s1 << endl;

    const MyString s5 = "The concatenation of the catapult is a catamaran";
    cout << "s5 = " << s5 << endl;
    cout << "s5.indexOf(\"cat\") returns " << s5.indexOf("cat") << '\n';
    cout << "s5.indexOf(\"dog\") returns " << s5.indexOf("dog") << '\n';

    cout << "s5.getLength() = " << s5.getLength() << '\n';

    cout << "s5[4] = " << s5[4] << '\n';
    cout << "s5[10] = " << s5[10] << '\n';
    cout << "s5[15] = " << s5[15] << '\n';
    cout << "s5[52] = ascii " << static_cast<int>(s5[52]) << '\n';

    cout << "s5.substring(10,16) = " << s5.substring(10,16) << '\n';
    cout << "s5.substring(23) = " << s5.substring(23) << '\n';

    cout << "-----------------------------\n";

    MyString words = "Greetings, Earthling";

    cout << "words = " << words << '\n';
    cout << "words.getLength() = " << words.getLength() << '\n';
    words[0] = 'K';
    words[4] = 'p';
    words[16] = 'z';


I've been using the phrase, "john was here, but not there" as a test.

By the way, seeplus , that helped a bit.
This should be the proper ouput for the function, all of it should show up in the terminal:

s1 =
s2 = Hello, World
s3 = Welcome to Florida, have a nice day
s4 = 12345

Making the calls:
cin >> s1
getline(cin, s2, ',')
getline(cin, s3)
Enter some sentences: John was here, but not there

New string values:
s1 = John
s2 = was here
s3 = but not there
---------------------------
result = DogFood
s1 = DogFood
s5 = The concatenation of the catapult is a catamaran
s5.indexOf("cat") returns 7
s5.indexOf("dog") returns -1
s5.getLength() = 48
s5[4] = c
s5[10] = e
s5[15] = o
s5[52] = ascii 0
s5.substring(10,16) = enation of the c
s5.substring(23) = e catapult is a catamaran
-----------------------------
words = Greetings, Earthling
words.getLength() = 20
words = Kreepings, Earthzing
words = Kreepings, Earthzing Q
words = Kreepings, Insane Earthzing Q
-----------------------------
x = apple
y = apply
x < y is true
x <= y is true
x != y is true
Last edited on
Your insert function looks wrong. Your reinterpert_casts just so happen to work because the first data member in your class is a char* -- it's still non-standard for non-POD types.
You really shouldn't need to be casting anything here. Furthermore, your return line makes no sense since you're trying to reinterpret a pointer as a reference to a MyString.

Also, I'm pretty sure your operator+= leaks, because you are overwriting the str variable.
Last edited on
and I'm having trouble finding where they are.


You really need to learn how to use the debugger so that you can trace through the code and find at which point the error occurs. Just looking at code is really not the way to do this. The debugger will allow you to step through the code showing contents of variables, set break points etc etc. It's a skill that all programmers need to acquire - but is often not taught or taught badly.
I think I had a segmentation fault in my insert() function. I'm trying to fix it. This is what I have so far:

Any help?

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
 MyString& MyString::insert(unsigned int index, const MyString& s)
// insert s into the string at position "index"
{
    char * half1 = new char[size + s.size + 1];
    char * half2 = new char[size + 1];
    char * tempstr = new char[size + 1];
    MyString concat[size + s.size+1];

    concat[size + s.size+1] = '\0';

    half1[size+s.size+1] = '\0';
    half2[size+1] = '\0';
    tempstr[size+1] = '\0';

    strcpy(tempstr, str);

    for(int i = 0; i <= index + s.size - 1; i++)
    {
        half1[i] = tempstr[i];
    }
    strcat(half1, s.str);
    for(int j = index + s.size; j <= size; j++)
    {
        half2[j] = tempstr[j];
    }

    strcpy(concat, half1);

    delete [] half1;
    delete [] half2;
    delete [] tempstr;

    return concat;
}
First problem I see is that concat is a local variable, but you're trying to return it by reference (MyString&). I assume you want a reference to the current MyString object returned, in which case you should be returning *this.

Second issue -- which may be more of a logic issue and not necessarily the cause of a crash -- is that you never use your str member variable. Shouldn't the str variable be used at some point (delete the old array, to assign a new array, for instance)?

Where does the segfault happen? Like seeplus said, if you use a debugger, you'd be able to tell pretty much exactly where it happens. Examine the data at the point of the crash.

Develop a test. For example, given that your string current says "apple", and you are trying to insert "orange" at index 2, the end result should be "aporangeple". Write a minimum test program that simply does this, and checks the result.

1
2
3
4
5
6
7
8
9

// ...

int main()
{
    MyString my_str("apple");
    my_str.insert(2, "orange");
    cout << my_str << '\n';
}

Does it print the expected result? Does it crash?
Last edited on
Ok, so I've been tinkering around for a bit, and here's my new class.

I've got a segfault at line 372. Again, somewhere in my insert() function, I think I might be doing something wrong with the pointers.

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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
#include "mystring.h"
#include <iostream>
#include <cstring>

/*
    char * str; // pointer to a dynamic array of chars
    unsigned int size;   // holds the size of the  dynamic array
*/

// Standard Constructors
MyString::MyString()
// Empty String
{
    size = 0;
    str = new char[size+1];    // null pointer, no data yet
    str[0] = '\0';
}
MyString::MyString(const char * s)
// conversion from c-string
{
    size = strlen(s);       // set size to length of c-cstring s
    str = new char[size+1];   // allocate enough space to store s
    strcpy(str, s);
}
MyString::MyString(int n)
// conversion from int
{
    int n2 = n;

    int digits = 0;
    while (n != 0)
    {
        n = n / 10;
        ++digits;
    }
    size = digits;

    str = new char[size+1];

    for (int i = size-1; i >= 0; i--)
    {
        str[i] = (n2 % 10) + '0';
        n2 = n2 / 10;
    }

    str[size] = '\0';
}
MyString::~MyString()
// destructor for final clean up
{
    delete [] str;
}
MyString::MyString(const MyString& s)
// copy constructor (for deep copy)
{
    size = s.size;
    str = s.str;

    str = new char[size+1];

    for (int i = 0; i <= size; i++)
    {
        str[i] = s.str[i];
    }
}
MyString& MyString::operator=(const MyString& s)
// Assignment operator (for deep copy)
{
    if (this != &s)
    {
        delete [] str;

        size = s.size;
        str = s.str;

        str = new char[size+1];

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

    return * this;
}

// I/O Functions
ostream& operator<< (ostream& os, const MyString& s)
// << operator overload
{
    os << s.str;

    return os;
}
istream& operator>> (istream& is, MyString& s)
// << operator overload
{
    int max = 1;
    int index = 0;
    char * buffer =  new char[max];

    while (isspace(is.peek()))
    {
        is.ignore();
    }

    while (!isspace(is.peek()))
    {
        char * tempstr = new char[max + 1];
        buffer[index] = is.get();

        for(int i = 0; i < max; i++)
        {
            tempstr[i] = buffer[i];
        }

        index++;
        max++;
        delete [] buffer;
        buffer = tempstr;
    }

    buffer[index] = NULL;
    delete [] s.str;
    s.str = buffer;
    return is;
}
istream& getline (istream& is, MyString& s)
// getline operator overload
{
    int max = 1;
    int index = 0;
    char * buffer =  new char[max];


    while (is.peek() != '\n')
    {
        char * tempstr = new char[max + 1];
        buffer[index] = is.get();

        for(int i = 0; i < max; i++)
        {
            tempstr[i] = buffer[i];
        }

        index++;
        max++;
        delete [] buffer;
        buffer = tempstr;
    }

    is.ignore();

    buffer[index] = '\0';
    delete [] s.str;
    s.str = buffer;
    return is;
}
istream& getline (istream& is, MyString& s, char delim)
// getline (with delimiter) operator overload
{
    int max = 1;
    int index = 0;
    char * buffer =  new char[max];


    while (is.peek() != delim)
    {
        char * tempstr = new char[max + 1];
        buffer[index] = is.get();

        for(int i = 0; i < max; i++)
        {
            tempstr[i] = buffer[i];
        }

        index++;
        max++;
        delete [] buffer;
        buffer = tempstr;
    }

    is.ignore();

    buffer[index] = '\0';
    delete [] s.str;
    s.str = buffer;
    return is;
}

// Comparison Operators
bool operator< (const MyString& x, const MyString& y)
// < operator overload
{
    return strcmp(x.str, y.str) < 0;
}
bool operator> (const MyString& x, const MyString& y)
// > operator overload
{
    return strcmp(x.str, y.str) > 0;
}
bool operator<=(const MyString& x, const MyString& y)
// <= operator overload
{
    return strcmp(x.str, y.str) <= 0;
}
bool operator>=(const MyString& x, const MyString& y)
// >= operator overload
{
    return strcmp(x.str, y.str) >= 0;
}
bool operator==(const MyString& x, const MyString& y)
// == comparison operator overload
{
    return strcmp(x.str, y.str) == 0;
}
bool operator!=(const MyString& x, const MyString& y)
// != comparison operator overload
{
    return strcmp(x.str, y.str) != 0;
}

// Concatenation Operators
MyString operator+ (const MyString& x, const MyString& y)
// Concatenation
{
    MyString combined = x;
    combined += y;
    return combined;
}
MyString& MyString::operator+=(const MyString& s)
// Concatenation/Assignment operator
{
    size += s.size;
    char * newstr = new char[size + 1];
    strcpy(newstr, str);
    strcat(newstr, s.str);

    delete [] str;
    str = newstr;

    return * this;
}

// Bracket Operators
char& MyString::operator[] (unsigned int index)
{
    // resize to fit index
    if (index >= size)
    {
        int resize = index - size;

        char * tempstr = new char[size+1];
        strcpy(tempstr, str);

        str[size + resize];

        for (int i = 0; i < size + resize; i ++)
        {
            str[i] = ' ';
        }
        str[size + resize] = '\0';

        return str[index];
    }
    else
    {
        return str[index];
    }
}
const char& MyString::operator[] (unsigned int index) const
{
    //if index is too big return null

    if (index >= size)
    {
        return str[size];
    }
    else
    {
        return str[index];
    }
}

// Standard Accessors
int MyString::getLength() const
// return string length
{
    return size;
}
const char* MyString::getCString() const
// return c-string equivalent
{
    return str;
}

// Substring Functions
MyString MyString::substring(unsigned int index, unsigned int length) const
{
    MyString substr = substring(index);

    if (substr.size - 1 <= length)
    {
        return substr;
    }
    else
    {
        char * tempstr = new char[length + 1];

        for (int i = 0; i < length; i++)
        {
            tempstr[i] = substr.str[i];
        }

        tempstr[length] = '\0';
        delete [] substr.str;
        substr.str = tempstr;
        substr.size = length + 1;
    }
    return substr;
}
MyString MyString::substring(unsigned int index) const
{
    MyString substr;
    int subsize = size - index;

    if (subsize <= 1)
    {
        substr.str = NULL;
        substr.size = 1;
    }
    else
    {
        char * tempstr = new char[subsize];

        for (int i = 0; i < subsize - 1; i++)
        {
            tempstr[i] = str[i + index];
        }

        tempstr[subsize - 1] = '\0';
        delete [] substr.str;
        substr.str = tempstr;
        substr.size = subsize;
    }
    return substr;
}

// insert() Function
MyString& MyString::insert(unsigned int index, const MyString& s)
// insert s into the string at position "index"
{
    size += s.size;

    char * chunk1 = new char[size + 1];
    char * chunk2 = new char[size + 1];
    char * middle = new char[size + 1];

    strcpy(middle, s.str);
    strncpy(chunk1, str, index);
    for(int i = index; i < size; i++)
    {
        chunk2[i] = str[i];
    }

    strcat(chunk1, middle);
    strcat(chunk2, chunk2);

    delete [] chunk1;
    delete [] chunk2;
    delete [] str;
    str = chunk1;

    return * this;
}

// indexof() Function
int MyString::indexOf(const MyString& s) const
// find index of the first occurrence of s inside the string
//  return the index, or -1 if not found
{
    int index;
    bool found = false;

    if (size < s.size)
    {
        return -1;
    }
    else
    {
        for (int i = 0; i < size; i++)
        {
            if (s.str[i] == s && found == false)
            {
                i = index;
                found = true;
            }
        }

        if (found == true)
        {
            return index;
        }
        else if (found == false)
        {
            return -1;
        }
    }
}
Here's a close-up of the insert() function.

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
// insert() Function
MyString& MyString::insert(unsigned int index, const MyString& s)
// insert s into the string at position "index"
{
    size += s.size;

    char * chunk1 = new char[size + 1];
    char * chunk2 = new char[size + 1];
    char * middle = new char[size + 1];

    strcpy(middle, s.str);
    strncpy(chunk1, str, index);
    for(int i = index; i < size; i++)
    {
        chunk2[i] = str[i];
    }

    strcat(chunk1, middle);
    strcat(chunk2, chunk2);

    delete [] chunk1;
    delete [] chunk2;
    delete [] str;
    str = chunk1;

    return * this;
}
I've made another change to my insert() function:

It has no more segmentation faults, but the output is still wrong. Any ideas?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// insert() Function
MyString& MyString::insert(unsigned int index, const MyString& s)
// insert s into the string at position "index"
{
    size += s.size;
    char * middle = new char[size + 1];
    strcpy(middle, str);

    for (int i = size; i >= index; i--)
    {
        str[i] = str[i-1];
    }

    for(int i = index; i < s.size - 1; i++)
    {
        str[i] = s.str[i];
    }

    delete [] middle;

    return * this;
}
I've got a segfault at line 372


That's expected - as you're using chunck1 which has just been deleted!

You need to write the code in small 'parts' with each part tested and got working before going on to write more code.

Also, as per previous, you can't debug code like this just by looking at it and hoping for some inspiration. You need to learn to use the debugger and debug your code - trace through it to find problems and also to ensure that's working as expected. Just because a program 'seems to work', that doesn't mean it does properly. With C/C++, you can get an 'expected' result with faulty code. This is 'fragile' code that gives the impression of being right, but isn't.
Last edited on
Topic archived. No new replies allowed.