string implementation with tokenize function

I made an string class based on page 602 from C++: How to Program 6th edition (Mine is not finished yet). I'm trying to implement 2 functions, in special. One is int* find(char) and another is char** split(char). Split does not return a runtime error, but it does nothing and the program seems freezed. Find just gave me a run time error. What am I doing wrong?
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
#ifndef STRING_INCLUDED
#define STRING_INCLUDED
#include <iostream>

namespace c_string
{
    size_t strlen(const char* variable)
    {
        int length;
        for(length = 0; variable[length] != '\0'; length++);
        return length;
    }
    char * strcpy(char *s1, const char *s2)
    {
        char *s = s1;
        while ((*s++ = *s2++) != 0)
        ;
        return (s1);
    }

    int strcmp (const char *s1, const char *s2)
     {
        const unsigned char *p1 = (const unsigned char *)s1;
        const unsigned char *p2 = (const unsigned char *)s2;
        while (*p1 != '\0')
        {
            if (*p2 == '\0') return  1;
            if (*p2 > *p1)   return -1;
            if (*p1 > *p2)   return  1;

            p1++;
            p2++;
        }
        if (*p2 != '\0') return -1;
        return 0;
    }

    extern const size_t STR1_GREATER = 1;
    extern const signed short int STR2_GREATER = -1;
    extern const size_t EQUAL_STRINGS = 0;
}


class string
{
    private:

        char* str_value;
        void set_string(const char* value, string& str)
        {
            str.str_value = const_cast<char*>(value);
        }

    public:

        friend std::ostream& operator<<(std::ostream& os, string& str)
        {
            os << str.str_value;
            return os;
        }
        friend std::istream& operator>>(std::istream& is, string& str)
        {
            is >> str.str_value;
            return is;
        }
        size_t length() const
        {
            return c_string::strlen(this->str_value);
        }

        char* str()
        {
            return this->str_value;
        }

        const char* c_str()
        {
            const char* ret_ = this->str();
            return ret_;
        }
        string(string& copy_str)
        {
            set_string(copy_str.c_str(), *this);
            this->str_value = new char[copy_str.length() + 1];
        }

        string(const char* str = "")
        {
            set_string(str, *this);
            this->str_value = new char[0];
        }
        ~string()
        {
            delete[] this->str_value;
        }
        bool operator!()
        {
            return !(this->length());
        }
        bool operator==(string& str)
        {
            return c_string::strcmp(this->c_str(), str.c_str()) == c_string::EQUAL_STRINGS;
        }
        bool operator<(string& str)
        {
            return c_string::strcmp(this->c_str(), str.c_str()) == c_string::STR2_GREATER;
        }
        bool operator>(string& str)
        {
            return str < *this;
        }

        bool operator <=(string& str)
        {
            return !(*this > str);
        }
        bool operator >=(string& str)
        {
            return !(str < *this);
        }
        unsigned int* find(char char_)
        {
            int* ret_;
            char* str_stack = this->str();
            unsigned short int ocur = 0;
            for(int i = 0; i <= c_string::strlen(str_stack) + 1; i++)
            {
                if(str_stack[i] == char_)
                {
                    ret_[ocur] = i;
                }
            }
        }

        char** split(char character)
        {
            char** ret_;
            char* str_stack = this->str();
            unsigned int ch = 0;
            unsigned int i = 0;
            int _i = 0;
            while(str_stack[i] != character || ch <= c_string::strlen(this->str()))
            {
                ret_[_i][i] = str_stack[i];
                ch++;
            }
            return ret_;
        }
};
#endif // STRING_INCLUDED 


Thanks!
Last edited on
for the find function I spotted an error: (Which should be a compile-time error)
-There is no return
1
2
3
4
5
6
7
8
9
10
         friend std::ostream& operator<<(std::ostream& os, string& str)
        {
            os << str.str_value;
            return os;
        }
        friend std::istream& operator>>(std::istream& is, string& str)
        {
            is >> str.str_value;
            return is;
        }

based on my knowledge:friend functions are declared inside the class:
friend std::ostream& operator<<(std::ostream& os, string& str);
and implemented outside the class:
1
2
3
4
5
        std::ostream& operator<<(std::ostream& os, string& str)
        {
            os << str.str_value;
            return os;
        }
You can define it there.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
        void set_string(const char* value, string& str)
        {
            str.str_value = const_cast<char*>(value); //possible bad cast.
        }

        string(const char* str = "")
        {
            set_string(str, *this); //¿what for?
            this->str_value = new char[0]; //you overwrite it. By the way str_value[0] has garbage
        }

        string(string& copy_str) //¿ever heard of const-correctness?
        {
            set_string(copy_str.c_str(), *this);
            this->str_value = new char[copy_str.length() + 1]; //same problem as above
        }


You are dereferencing an uninitialized pointer `ret_' in `split()'

You are missing an assignment operator.


Also, you should provide the client code.
@ne555
 (Mine is not finished yet).


Else: Yes... Too much errors, but I can't solve it :(. Please, help!
Last edited on
In your split function, the variable ret is uninitialised before being used. Also the code does not fully split the string. What happens when more than one occurrence of the delimiting character is found in the string?

Your find function does not work because you are not returning anything in the function. Frankly I'm surprised this function compiled

This find function should work:
1
2
3
4
5
6
7
8
9
10
11
size_t find(char char_)
{
	char* str_stack = this->str();
	size_t size = c_string::strlen(str_stack);
	
	for(size_t pos = 0; pos < size; pos++)
		if(str_stack[pos] == char_)
			return pos;
	
	return size_t(-1);
}
Last edited on
Ok. Found it: EVEN << OPERATOR DOESN'T WORK. :)
God, what should I do? I've thinked in everything...
Since now:

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
#ifndef STRING_INCLUDED
#define STRING_INCLUDED
#include <ostream>
#include <istream>

namespace c_string
{
    size_t strlen(const char* variable)
    {
        int length;
        for(length = 0; variable[length] != '\0'; length++);
        return length;
    }
    char * strcpy(char *s1, const char *s2)
    {
        char *s = s1;

        while ((*s++ = *s2++) != 0);
        return (s1);
    }

    int strcmp (const char *s1, const char *s2)
     {
        const unsigned char *p1 = (const unsigned char *)s1;
        const unsigned char *p2 = (const unsigned char *)s2;
        while (*p1 != '\0')
        {
            if (*p2 == '\0') return  1;
            if (*p2 > *p1)   return -1;
            if (*p1 > *p2)   return  1;

            p1++;
            p2++;
        }
        if (*p2 != '\0') return -1;
        return 0;
    }

    extern const size_t STR1_GREATER = 1;
    extern const signed short int STR2_GREATER = -1;
    extern const size_t EQUAL_STRINGS = 0;
}

class string
{
    private:

        char* str_value;
        void set_string(const char* value)
        {
            if(value != 0)
            c_string::strcpy(str_value, value);
            else str_value[0] = '\0';
        }

    public:

        friend std::ostream& operator<<(std::ostream& os, string& str)
        {
            os << str.str_value;
            return os;
        }
        friend std::istream& operator>>(std::istream& is, string& str)
        {
            is >> str.str_value;
            return is;
        }
        size_t length() const
        {
            return c_string::strlen(this->str_value);
        }

        char* str()
        {
            return this->str_value;
        }

        const char* c_str()
        {
            const char* ret_ = this->str();
            return ret_;
        }
        string(string& copy_str)
        {
            set_string(copy_str.c_str());
            this->str_value = new char[copy_str.length() + 1];
        }

        string(const char* str = "")
        {
            set_string(str);
        }
        ~string()
        {
            delete[] this->str_value;
        }
        bool operator!()
        {
            return !(this->length());
        }
        bool operator==(string& str)
        {
            return c_string::strcmp(this->c_str(), str.c_str()) == c_string::EQUAL_STRINGS;
        }
        bool operator<(string& str)
        {
            return c_string::strcmp(this->c_str(), str.c_str()) == c_string::STR2_GREATER;
        }
        bool operator>(string& str)
        {
            return str < *this;
        }

        bool operator <=(string& str)
        {
            return !(*this > str);
        }
        bool operator >=(string& str)
        {
            return !(str < *this);
        }

        char** split(char character)
        {
            char** ret_ = NULL;
            char* str_stack = this->str();
            unsigned int ch = 0;
            unsigned int i = 0;
            int _i = 0;
            while(str_stack[i] != character || ch <= c_string::strlen(this->str()))
            {
                ret_[_i][i] = str_stack[i];
                ch++;
            }
            return ret_;
        }
};
#endif // STRING_INCLUDED 
I'll tell you again, your string creation is incorrect.

1
2
3
4
5
        string(string& copy_str)
        {
            set_string(copy_str.c_str());
            this->str_value = new char[copy_str.length() + 1];
        }
Fist you are assigning the string, then you are reserving the space. That makes no sense.
1
2
this->str_value = new char[copy_str.length()+1];
this->set_string(cpy_str.c_str());


1
2
3
4
        string(const char* str = "")
        {
            set_string(str);
        }
`str_value' is not initialized, so `set_string()' would fail.
1
2
            this->str_value = new char[strlen(str) + 1];
            set_string(str);
Last edited on
Thanks ne555 :) Ill test it.
I found some errors. Now, I'm trying to implement string::substr member function. I only have errors with this and split function. My code is:
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
#ifndef STRING_INCLUDED
#define STRING_INCLUDED
#include <ostream>
#include <istream>

namespace c_string
{
    size_t strlen(const char* variable)
    {
        int length;
        for(length = 0; variable[length] != '\0'; length++);
        return length;
    }
    char * strcpy(char *s1, const char *s2)
    {
        char *s = s1;

        while ((*s++ = *s2++) != 0);
        return (s1);
    }

    int strcmp (const char *s1, const char *s2)
     {
        const unsigned char *p1 = (const unsigned char *)s1;
        const unsigned char *p2 = (const unsigned char *)s2;
        while (*p1 != '\0')
        {
            if (*p2 == '\0') return  1;
            if (*p2 > *p1)   return -1;
            if (*p1 > *p2)   return  1;

            p1++;
            p2++;
        }
        if (*p2 != '\0') return -1;
        return 0;
    }

    extern const size_t STR1_GREATER = 1;
    extern const signed short int STR2_GREATER = -1;
    extern const size_t EQUAL_STRINGS = 0;
}

class string
{
    private:

        char* str_value;
        void set_string(const char* value)
        {
            if(value != 0)
            c_string::strcpy(str_value, value);
            else str_value[0] = '\0';
        }

    public:
        friend std::ostream& operator<<(std::ostream& os, string& str)
        {
            os << str.str_value;
            return os;
        }
        friend std::istream& operator>>(std::istream& is, string& str)
        {
            is >> str.str_value;
            return is;
        }
        size_t length() const
        {
            return c_string::strlen(this->str_value);
        }

        char* str()
        {
            return this->str_value;
        }

        const char* c_str()
        {
            const char* ret_ = this->str();
            return ret_;
        }
        string(string& copy_str)
        {
            this->str_value = new char[copy_str.length() + 1];
            set_string(copy_str.c_str());
        }

        string(const char* str = "")
        {
            this->str_value = new char[c_string::strlen(str) + 1];
            set_string(str);
        }
        ~string()
        {
            delete[] this->str_value;
        }
        bool operator!()
        {
            return !(this->length());
        }
        bool operator==(string& str)
        {
            return c_string::strcmp(this->c_str(), str.c_str()) == c_string::EQUAL_STRINGS;
        }
        bool operator<(string& str)
        {
            return c_string::strcmp(this->c_str(), str.c_str()) == c_string::STR2_GREATER;
        }
        bool operator>(string& str)
        {
            return str < *this;
        }

        bool operator <=(string& str)
        {
            return !(*this > str);
        }
        bool operator >=(string& str)
        {
            return !(str < *this);
        }
        void operator=(string new_value)
        {
            this->str_value = new char[new_value.length() + 1];
            set_string(new_value.str());
        }
        void operator=(const char* new_value)
        {
            this->str_value = new char[c_string::strlen(new_value) + 1];
            set_string(new_value);
        }
        char operator[](unsigned int subscript)
        {
            if(subscript > c_string::strlen(this->str_value) + 1) return 0;
            else return this->str_value[subscript];
        }
        void operator+=(const char* str)
        {

        }
        void operator+=(string& str)
        {
            *this += str.str_value;
        }
        char* substr(unsigned int index, unsigned int end)
        {
                    if(index == end)
                    {
                        return (char*)-1;
                    }
                    else if(end < index || end > c_string::strlen(this->c_str()))
                    {
                        return (char*)-1;
                    }

                        char* str_stack = new char[end - index];
                        str_stack = 0;
                        for(unsigned int i = index; i <= end; i++)
                        {
                            str_stack[index - i] = this->operator[](i);
                        }
                        return str_stack;

        }
        char** split(char character)
        {
            char** ret_ = NULL;
            char* str_stack = this->str();
            unsigned int ch = 0;
            unsigned int i = 0;
            int _i = 0;
            while(str_stack[i] != character || ch <= c_string::strlen(this->str()))
            {
                ret_[_i][i] = str_stack[i];
                ch++;
            }
            return ret_;
        }

};
#endif // STRING_INCLUDED
Your substr function should return a string type.

Remember that c-strings are terminated with a NUL character. You must allocate space for that character, and you must terminate the string.

You realize that (char*)-1 may be a perfectly valid pointer value? We have null pointers for a reason.

On line 174 your dereference a null pointer.
Last edited on
@cire
On line 174 your dereference a null pointer

What should I do?
What should you do?

Don't do: pointer = NULL ; pointer[i] = some_value ;

It isn't entirely clear from the name and definition of the function what semantics you intend split to have. But, I suspect that 'split' should return a container (such as a vector) of strings, and probably shouldn't be a member of the class. I would expect a string to supply the all of the basic functions that 'split' would need to use, and so 'split' would not need to be a member (or friend) of the class.
Ok. I agree, if it is a member, should return the type. But split need to return 2d something, thats the idea. How would I return a string? I'll keep split as char* and substr as char*, because it is like the operator[] access many times (until end).
Topic archived. No new replies allowed.