is this unconventional or bad form?

Hey everyone,

I've been working on a text analysis program for personal practice and I came across a problem. I was able to solve the problem and it compiles and runs fine but it feels like it may be "bad form" or something so I wanna make sure.

The problem: program would crash if only one word with no spaces is inputed.

My solution: (segment of code from program [specifically line 13-16])

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main(){
	while(true){

	string s;
	vector<string> word;
	cout << "Enter a sentence: ";
	getline(cin, s);
	size_t found;
	size_t found1;
	found = s.find_first_not_of(" ");
	found1 = s.find_first_of(" ");
	size_t *pnt = &found1;
    unsigned long const L = 18446744073709551615;
	if ( *pnt == L)
		word.push_back(s);
	else{...


The rest of the program, for the most part, runs under the condition that word.size() > 1.

I have another topic where I'm trying to find out why my program terminates when the whole thing is looped, but this is a segment of that code. The program runs fine once, but it doesn't like to run continuously.

Thanks community!
RW
I assume you are separating a string into words.
1
2
3
4
5
6
7
8
9
10
11
12
13
string s = "this is a test string";
	vector<string> word;
	size_t spos = 0, epos = 0;//start and end of sub string
	while((epos = s.find(" ", spos)) != string::npos)//while a space is found
	{
		word.push_back(s.substr(spos, epos - spos));
		spos = epos + 1;
		epos = s.find(" ", spos);//find next space
	}
	word.push_back(s.substr(spos,s.length()-spos));// get the last word

	for(int i = 0; i < word.size(); ++i)
		cout<<word[i]<<"  ";


Edit:unsigned long const L = 18446744073709551615; That number is likely too large for an unsigned long, try unsigned long long.
Last edited on
Thanks for the reply. I'm able to explode the string without trouble, my only problem was that my program was crashing if a word was entered without spaces. As a result, I took the default value of my variable that was supposed to find the space and made it a constant. I set that constant value as a condition for the situation that no space was inputted.

Does it work on other machines or is it a local fix?

Is this fix considered bad form?

Here is the code in full: (while true is commented out because my program for some reason crashes if I try to run it continuously, still haven't found a good fix)

(The section of code above is roughly line 50-65)

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
#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<string> initVect(vector<string> v) {
	for(unsigned int i = 0; i < v.size(); ++i) {
		v.erase(v.begin(),v.end());
	}
	return v;
}

vector<size_t> reinitVect(vector<size_t> v) {
	for(unsigned int i = 0; i < v.size(); ++i) {
		v[i] = 0;
	}
	return v;
}

vector<string> ddVect(vector<string> v){
	for (unsigned int i = 0; i < v.size(); ++i){
		unsigned int d = 0;
		while (d < v.size() ){
			if (i != d) {
				while (v[i] == v[d] && d < v.size() ){
					v.erase (v.begin()+d);
				}
			} ++d;
		}
	}
	return v;
}

vector<string> delNonAlphaV(vector<string> v) {
	for (unsigned int i = 0; i < v.size(); ++i ){
		if (v[i].substr(v[i].length() - 1) == ".")
			v[i] = v[i].substr(0, v[i].length() - 1);
		if (v[i].substr(v[i].length() - 1) == ",")
			v[i] = v[i].substr(0, v[i].length() - 1);
		if(v[i].length() > 3){
			if (v[i].substr(v[i].length() - 2, 1) == "'")
				v[i] = v[i].substr(0, v[i].length() - 2);
		}
	}
	return v;
}


int main(){
	//while(true){

	string s;
	vector<string> word;
	cout << "Enter a sentence: ";
	getline(cin, s);
	size_t found;
	size_t found1;
	found = s.find_first_not_of(" ");
	found1 = s.find_first_of(" ");
	size_t *pnt = &found1;
    unsigned long long const L = 18446744073709551615;
	if ( *pnt == L)
		word.push_back(s);
	else{
		while(found1 != string::npos){
			word.push_back(s.substr(found,found1-found) );
			found = found1 + 1;
			found1 = s.find_first_of(" ", found1 + 1);
		}
		found1 = string::npos;
		word.push_back(s.substr(found, found1) );
	}
	word = delNonAlphaV(word);
	string sWord;
	cout << "What word would you like to search for?: ";
	cin >> sWord;
	int count = 0;
	for (unsigned int i = 0; i < word.size(); ++i){
		if(word[i] == sWord)
			++count;
	}
	unsigned int i = 0;
	unsigned int max = 0;
	unsigned int min = 0;
	vector<size_t> equals;
	if (word.size() > 1) {
		if (word[i].length() == word[i+1].length() ){
			equals.push_back(i);
			equals.push_back(i+1);
			max = i;
		}
		if (word[i].length() > word[i+1].length() ){
			max = i;
			min = i+1;
		}
		if (word[i].length() < word[i+1].length() ){
			max = i+1;
			min = i;
		}
		for (unsigned int i = 2; i < word.size() ; ++i) {
			if (word[max].length() == word[i].length() ){
				equals.push_back(max);
				equals.push_back(i);
			}
			if (word[min].length() == word[i].length() ){
				equals.push_back(min);
				equals.push_back(i);
			}
			if (word[max].length() < word[i].length() )
				max = i;
			if (word[min].length() > word[i].length() )
				min = i;
		}
	}
	vector<string> maxW;
	maxW.push_back(word[max]);
	if (word.size() > 1) {
		if (equals.size() != 0){
			if (word[max].length() == word[equals[equals.size() - 1]].length() ){
				if (equals.size() != 1) {
					for (i = 0; i < equals.size(); ++i){
						if (word[max].length() == word[equals[i]].length() ){
							maxW.push_back(word[equals[i]]); //vector of largest words, all of the same length.
						}
					}
				}
			}
		}
	}
	vector<string> minW;
		minW.push_back(word[min]);
		if (word.size() > 1) {
			if (equals.size() != 0){
				for(unsigned int i = 0; i < equals.size(); ++ i){
					if(word[min].length() > word[equals[i]].length() )
						minW.push_back(word[equals[i]]);
					if(word[min].length() == word[equals[i]].length() )
						minW.push_back(word[equals[i]]);
				}
			}
		}
	if (maxW.size() != 1)
		maxW = ddVect(maxW);
	if (minW.size() != 1)
		minW = ddVect(minW);
	if ( maxW.size() != 1){
		cout << "\nThe strings with the most characters are ";
		for (unsigned int i = 0; i < maxW.size(); ++i ){
			cout << maxW[i];
			if (i != maxW.size() - 1)
				cout << " & ";
			else {
				cout << ". ";
				break;
			}
		}
	}
	else {
		cout << "\nThe string with the most characters is " << maxW[maxW.size() - 1] << ".";
	}
	if ( minW.size() != 1){
		cout << "\nThe strings with the least characters are ";
		for (unsigned int i = 0; i < minW.size(); ++i ){
			cout << minW[i];
			if (i != minW.size() - 1)
				cout << " & ";
			else {
				cout << ". ";
				break;
			}
		}
	}
	else {
		cout << "\nThe string with the least characters is " << minW[minW.size() - 1] << ".";
	}
	if (count == 1)
		cout << "\nThere is " << count << " instance of the word " << sWord << "." << endl;
	else
		cout << "\nThere are " << count << " instances of the word " << sWord << "." << endl;

/*
	word = initVect(word);
	maxW = initVect(maxW);
	equals = reinitVect(equals);
	found = 0;
	found1 = 0;
	max = 0;
	i = 0;
	count = 0;
	cin.clear();
	cin.sync();

	}*/
	return 0;
}
Well the reference for find_first_of (http://www.cplusplus.com/reference/string/string/find_first_of/) says:
Return Value
The position of the first occurrence in the string of any of the characters searched for.
If the content is not found, the member value npos is returned.


Notice the underlined part.

So you should actually be able to do this instead - which is probably more standard complaint:
1
2
3
	found1 = s.find_first_of(" ");
	if ( found1 != string::npos)
		word.push_back(s);


I see you using the npos in your else, did this not work for you in a previous attempt?
Thanks bradw for your response. To be honest, I didn't know that the member value npos was returned. I got that number from printing the value of found1 to the screen before it was assigned a value.

Now that I know npos is returned, I will use that for sure in the future. Thanks for pointing that out!

In the meantime I've been working on a work-around because I assumed that const value as a condition was a bit absurd.

Here is what I came up with and it works!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
string s;
	vector<string> word;
	cout << "Enter a sentence: ";
	getline(cin, s);
	size_t found;
	size_t found1;
	int spacecheck = 0;
	found = s.find_first_not_of(" ");
	for(unsigned int i = 0; i < s.length(); ++i){
		if(s.substr(i,1) == " ")
			break;
		else
			spacecheck += 1;
			if (spacecheck == s.length() )
				word.push_back(s);
	}
	if (word.size() == 0) ... {


Now if I can just get the whole thing to loop >.< For some reason if I put the whole thing in while == true, and reset everything to 0 at the end, it steps out of bounds... still not sure why....
Last edited on
As far as the while(true) loop, its a bit big for me to try and debug in my head here tonight, right now.

But I will say that it is going to be good practice to move all of your variables to the begining of the function - before the loop - like its C. Wherever your are declaring these variables insert a statement that clears/resets the value.

I am not very sure on what "it steps out of bounds" means, I mean, I know what "out of bounds" could mean but I don't have much to go on. So, once your variables are in order you should be able to break on any out of bounds exceptions.

Oh and I think you might like to try exception handling. Here is a really basic skeleton form of what you would do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <exception>
// other includes here

using namespace std;

int main(void)
{
    try
    {
        // all of your code in the main() function gets put in here
        // ALL of it
    }
    catch (exception ex)
    {
        cout << "Error: " << ex.what() << endl;
        return -1;
    }
}

Then it will tell you what the problem is and exit gracefully.
Debugging is a critical skill. If you find where it is stepping out of bounds set a breakpoint on the line before and examining all of the variables being put in to the problem function should help you determine why it is failing.

Good luck!
Thank a lot for your detailed response bradw, I really appreciate you taking the time to help me!

I will try all of your suggestions and see what I come up with.

I haven't read much on the library <exception> with the try and catch functions, so I will definitely look into that tonight, although your explanation is very straight forward which I'm thankful for!

I'm writing this program for practice because I found this exercise:

"Write a program to count how many times each distinct word appears in its input.
Write a program to report the length of the longest and shortest string in its input."

Not much to go on but it's great practice for me, although I'm sure there are simpler ways to accomplish this lol.

Thanks again, really!

Latest update:
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
#include <iostream>
#include <string>
#include <vector>

using namespace std;

vector<string> initVect(vector<string> v) {
	for(unsigned int i = 0; i < v.size(); ++i) {
		v.erase(v.begin(),v.end());
	}
	return v;
}

vector<size_t> reinitVect(vector<size_t> v) {
	for(unsigned int i = 0; i < v.size(); ++i) {
		v[i] = 0;
	}
	return v;
}

vector<string> ddVect(vector<string> v){
	for (unsigned int i = 0; i < v.size(); ++i){
		unsigned int d = 0;
		while (d < v.size() ){
			if (i != d) {
				while (v[i] == v[d] && d < v.size() ){
					v.erase (v.begin()+d);
				}
			} ++d;
		}
	}
	return v;
}

vector<string> delNonAlphaV(vector<string> v) {
	for (unsigned int i = 0; i < v.size(); ++i ){
		if (v[i].substr(v[i].length() - 1) == ".")
			v[i] = v[i].substr(0, v[i].length() - 1);
		if (v[i].substr(v[i].length() - 1) == ",")
			v[i] = v[i].substr(0, v[i].length() - 1);
		if(v[i].length() > 3){
			if (v[i].substr(v[i].length() - 2, 1) == "'")
				v[i] = v[i].substr(0, v[i].length() - 2);
		}
	}
	return v;
}


int main(){
	//while(true){

	string s;
	vector<string> word;
	cout << "Enter a sentence: ";
	getline(cin, s);
	size_t found;
	size_t found1;
	unsigned int spacecheck = 0;
	found = s.find_first_not_of(" ");
	for(unsigned int i = 0; i < s.length(); ++i){
		if(s.substr(i,1) == " ")
			break;
		else
			spacecheck += 1;
			if (spacecheck == s.length() )
				word.push_back(s);
	}
	if (word.size() == 0) {
		found1 = s.find_first_of(" ");
		while(found1 != string::npos){
			word.push_back(s.substr(found,found1-found) );
			found = found1 + 1;
			found1 = s.find_first_of(" ", found1 + 1);
		}
		found1 = string::npos;
		word.push_back(s.substr(found, found1) );
	}
	word = delNonAlphaV(word);
	string sWord;
	cout << "What word would you like to search for?: ";
	cin >> sWord;
	int count = 0;
	for (unsigned int i = 0; i < word.size(); ++i){
		if(word[i] == sWord)
			++count;
	}
	unsigned int i = 0;
	unsigned int max = 0;
	unsigned int min = 0;
	vector<size_t> equals;
	if (word.size() > 1) {
		if (word[i].length() == word[i+1].length() ){
			equals.push_back(i);
			equals.push_back(i+1);
			max = i;
		}
		if (word[i].length() > word[i+1].length() ){
			max = i;
			min = i+1;
		}
		if (word[i].length() < word[i+1].length() ){
			max = i+1;
			min = i;
		}
		for (unsigned int i = 2; i < word.size() ; ++i) {
			if (word[max].length() == word[i].length() ){
				equals.push_back(max);
				equals.push_back(i);
			}
			if (word[min].length() == word[i].length() ){
				equals.push_back(min);
				equals.push_back(i);
			}
			if (word[max].length() < word[i].length() )
				max = i;
			if (word[min].length() > word[i].length() )
				min = i;
		}
	}
	vector<string> maxW;
	maxW.push_back(word[max]);
	if (word.size() > 1) {
		if (equals.size() != 0){
			for(unsigned int i = 0; i < equals.size(); ++ i){
				if(word[max].length() < word[equals[i]].length() )
					maxW.push_back(word[equals[i]]);
				if(word[max].length() == word[equals[i]].length() )
					maxW.push_back(word[equals[i]]); //vector of largest words, all of the same length.
			}
		}
	}
	vector<string> minW;
		minW.push_back(word[min]);
		if (word.size() > 1) {
			if (equals.size() != 0){
				for(unsigned int i = 0; i < equals.size(); ++ i){
					if(word[min].length() > word[equals[i]].length() )
						minW.push_back(word[equals[i]]);
					if(word[min].length() == word[equals[i]].length() )
						minW.push_back(word[equals[i]]);
				}
			}
		}
	if (maxW.size() != 1)
		maxW = ddVect(maxW);
	if (minW.size() != 1)
		minW = ddVect(minW);

	if (maxW[0].length() == minW[0].length() ) {
		cout << "\nThe strings with the most and the least characters are the same length!: ";
		for(unsigned int i = 0; i < maxW.size(); ++i ){
			cout << maxW[i];
			if (i != maxW.size() - 1)
				cout << " & ";
			else {
				break;
			}
		}
	}
	else {
		if (maxW.size() != 1){
			cout << "\nThe strings with the most characters are: ";
			for (unsigned int i = 0; i < maxW.size(); ++i ){
				cout << maxW[i];
				if (i != maxW.size() - 1)
					cout << " & ";
				else {
					break;
				}
			}
		}
		else {
			cout << "\nThe string with the most characters is: " << maxW[maxW.size() - 1];
		}
		if ( minW.size() != 1){
			cout << "\nThe strings with the least characters are: ";
			for (unsigned int i = 0; i < minW.size(); ++i ){
				cout << minW[i];
				if (i != minW.size() - 1)
					cout << " & ";
				else {
					cout << ". ";
					break;
				}
			}
		}
		else {
			cout << "\nThe string with the least characters is: " << minW[minW.size() - 1];
		}
	}
	if (count == 1)
		cout << "\nThere is " << count << " instance of the word: " << sWord << endl;
	else
		cout << "\nThere are " << count << " instances of the word: " << sWord << endl;

/*
	word = initVect(word);
	maxW = initVect(maxW);
	equals = reinitVect(equals);
	found = 0;
	found1 = 0;
	max = 0;
	i = 0;
	count = 0;
	cin.clear();
	cin.sync();

	}*/
	return 0;
}
/* */
Last edited on
Write a program to count how many times each distinct word appears in its input.
Write a program to report the length of the longest and shortest string in its input.


The first problem is not actually "easy". I will try to look at your implementation tomorrow.

The second problem is not "hard", and I like that you are keeping track of multiple words having the same greatest-length.

Thanks that would be great if you have time!
Last edited on
Since I said I might look, I started checking out how you are reading "words" and you would stand to gain by learning about streams. stringstreams, that is.

BTW, did you know that this:
1
2
3
4
5
6
7
8
	for(unsigned int i = 0; i < s.length(); ++i){
		if(s.substr(i,1) == " ")
			break;
		else
			spacecheck += 1;
			if (spacecheck == s.length() )
				word.push_back(s);
	}


Is actually this:
1
2
3
4
5
6
7
8
9
	for(unsigned int i = 0; i < s.length(); ++i){
		if(s.substr(i,1) == " ")
			break;
		else {
			spacecheck += 1;
		}
		if (spacecheck == s.length() )
			word.push_back(s);
	}


An "un-braced" condition like if, else if, else, and [all of the loops]. will only match the following 1 line.

The way the code was tabbed I didn't think so, but maybe.

This is a great place for stringstream!

You will have to add <sstream> to your includes.
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
int main(){
	//while(true){

	string s;
	stringstream ss;
	vector<string> word;

	cout << "Enter a sentence: ";
	getline(cin, s);

	size_t found;
	size_t found1;

	ss.str(s);				// fills the stringstream with contents of "s"
	while( !ss.eof() )			// stop if end of stream
	{
		ss >> s;			// read 1 word from ss in to s, automatically removing spaces
		if (ss.good())			// if read last string succeeded
			word.push_back(s);	// add it to our vector of words
		else
		{
			ss.clear();	// clear stream state flags - probably not needed 
					// if ss is not again used as an input-stream, but still it is
					// good practice because if you do this on cin - which I think you can - further stream reads will fail.
			break;	// stop reading on bad input (even though I don't 
					// think it will fail to read an integer into a string, 
					// but I don't recall well at this time without trying.)
					// the final read should be on an empty stream so you
					// would want to make the stream "good" again
		}
	}


With this change, I think you can get rid of this, which appears to be used for the case where you only had 1 word and your "look for a space-character" search failed.
1
2
3
4
5
6
7
8
9
10
	if (word.size() == 0) {		
		found1 = s.find_first_of(" ");	
		while(found1 != string::npos){	
			word.push_back(s.substr(found,found1-found) );	
			found = found1 + 1;
			found1 = s.find_first_of(" ", found1 + 1);
		}
		found1 = string::npos;
		word.push_back(s.substr(found, found1) );
	}


Your "initVect()" function can be replaced with vector's member function".clear()"
1
2
3
word = initVect(word);
// becomes:
word.clear();


I didn't get to look at everything, but you should be able to do about this if you include <algorithm>:
1
2
3
4
5
6
7
8
9
10
	cout << "What word would you like to search for?: ";
	cin >> sWord;

	vector<string>::iterator loc;
	loc = find(word.begin(), word.end(), sWord);

	if (loc != word.end())	// I _think_ this is the correct test
		cout << "I found it!" << endl;
	else
		cout << "I didnt find that" << endl;


Otherwise, if you dont like the <algorithm> for some reason you can iterate over it yourself:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
	bool weFoundIt = false;
	vector<string>::iterator b,e;	// Begin and End
	b = word.begin();
	e = word.end();
	while(b!=e)
	{
		if ( *b == sWord )	// a match? ( the "*b" is the value at that iterator)
		{
			weFoundIt = true;
			break;	// we can stop searching
		}
		b++;		// get the next word (if this one isnt it)
	}
	if (weFoundIt)
	{
		cout << "Yep! Found " << sWord << endl;
	}


See if you can figure out min/max with these iterators. :)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	string tempString;
	vector<string>::iterator b,e;
	b = word.begin();
	e = word.end();
	while( b != e )	// from begining to end of the vector of words
	{
		tempString = *b;	// tempString now holds this word
						// de-referencing an iterator is kind of strange but
						// it is really no different than a pointer here (kinda.)

		// tempString is now a standard "string" object
		// do your testing for length here and process result.

		+++b;	// next word, please
	}


Learning is fun. Fun!

But... "re-inventing the wheel" should be avoided, unless you really want to know how the "wheel" words (and when learning, I think you should look at it at lest some.) If you need to dig a hole in your yard, you dont invent a shovel do you? It is great for leaning, but after programming for many many years, I can tell you that it is far better to simply use the tools that have already been created for you.

There is a ton of code that is already written to do most trivial problems (and if you get to the non-trivial stuff, you will probably find that "boost" already has it - and a lot of people will recommend that you try it out.)

If you really want your mind-blown, then look up a "BST". I think that is the solution to the "first problem" that we used in Comp Sci.
Bradw, I don't know how to thank you enough!

More so than simply pointing me in the right direction, you really taught me how to improve my code and make it more efficient. I'm very much looking forward to spending the next couple of hours to practice everything you just taught me. I won't stop until I feel like I know it well enough to teach someone else!

Before I started this exercise, I read that the two ways to break-up a string of text was to "explode" the string the way I did, or to use stringstream. Admittedly, I saw that most recommendations were for stingstream, but since I hadn't used the more "primitive" method, I decided to start with that. I've learned so much thus far, and now I believe its time for me to learn the stringstream method which you so kindly explained to me.

I'm glad to know there is a member function for vectors to clear them, thanks for pointing that out among other things!

I'm sure to an experienced coder like yourself, this code must look like someone trying to invent many ways of doing something that already has a set standard approach. I thank you again for teaching me those standards! Programming is so cool though, with limited knowledge and a strong foundation of the basics, I feel like anything is possible! (at the risk of sounding cliche ) :D

I guess one of my problems is that I get faced with a problem that I need to solve while programming, and instead of researching what people have done in the past and checking to see if solutions or functions already exist to accommodate the problem, I think, "Hey, with what I know, I think I have a solution!" Often times, through the process of working to that solution I came up with, I run into more problems and then repeat the previous steps with the new problems. On the other hand, the knowledge gained from this approach seems valuable.

I take all of your suggestions to heart and I will try my best to avoid "re-inventing the wheel" in the future. Maybe one day I'll be so lucky to meet someone like you who will be my mentor. I just feel so addicted to programming, all I want to do is get better and better!

The information you have given me is invaluable. Upon clicking the submit button to this reply, I will be eagerly looking up "BST". I can't wait to read about it!

It's great to hear from someone who shares my same belief, Learning is fun. So Fun!
Last edited on
But... "re-inventing the wheel" should be avoided, unless you really want to know how the "wheel" words (and when learning, I think you should look at it at lest some.) If you need to dig a hole in your yard, you dont invent a shovel do you? It is great for leaning, but after programming for many many years, I can tell you that it is far better to simply use the tools that have already been created for you.


I agree with this very much, but also think that, as a beginner, re-inventing the wheel is quite valuable. I would even suggest re-creating the vector and string classes yourself. Before working on a Binary Search Tree, I would suggest making a Linked List.

A BST is how we solved this too. In my class we had to report the amount of times each word appeared in ascending order. The BST is good for making the data structure, but not very good trying to get to the count variable:
1
2
3
4
5
6
7
struct Node
{
  string word;
  int count;
  Node* left;
  Node* right;
};


While the words are easy to get alphabetical, the counts end up all over the place. After the tree was filled I was thinking of making some hash-table type structure for, but in the end handed it in as something that loops through the tree many times. Most people couldn't get their head around a pointer anyway, so I was in pretty good shape just having a working tree.


Btw, my in-class final exam included writing down (no computers) a working linked list (push-back, push_front, insert, delete, print). Needless to say, it was valuable that I banged my head against re-inventing that wheel a few months before.
Thanks for reply LowestOne. I'll look into re-creating the vector and string classes. I've heard that making a linked list is great practice for pointers so I will add that to my to-do list as well. If you have any good material on how to re-create these classes that you're willing to share, my email is in my profile.

I read a good bit on BST last night in order to begin to familiarize myself with the basic concepts. It was fascinating and I'll work making a working tree soon, after I finish a linked list and re-create at least one class.

Reporting all the words in ascending order seems like a good challenge I may work on as well. At the moment, I wanted to just report the amount of times each word appeared in the input stream. I thought it may not be bad to use a two dimensional array for this with the amount of columns being equal to the word that appears most frequently.

I wanted it to look like "the dog walked to the park to eat by the tree"

1
2
3
4
5
6
7
8
9
10
string array [8][3]

0 the the the
1 dog
2 walked
3 to to
4 park
5 eat
6 by
7 tree


I have successfully gotten this far but I'm not really sure about the most efficient way to loop through this array and get the counts. Maybe I'm going about this the wrong way, but it was good practice to be able to move everything from the vector and organize it this way in the array.

Sounds like a cool final exam by the way, good that you were prepared!

Thanks again LowestOne!
Hey bradw,

I just wanted to show you my updated code since I incorporated everything you taught me into it!

Furthermore, I was able to find a way to keep track of the number of each word in the input. My array idea fell through since I couldn't have mixed data types in the array so I just made a simple struct.

I figured out why the while loop was crashing and fixed that too! :D

Thanks again for the lesson, I learned 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
#include <iostream>
#include <string>
#include <vector>
#include <sstream>

using namespace std;

vector<string> ddVect(vector<string> v){
	for (unsigned int i = 0; i < v.size(); ++i){
		unsigned int d = 0;
		while (d < v.size() ){
			if (i != d) {
				while (v[i] == v[d] && d < v.size() ){
					v.erase (v.begin()+d);
				}
			} ++d;
		}
	}
	return v;
}

vector<string> delNonAlphaV(vector<string> v) {
	for (unsigned int i = 0; i < v.size(); ++i ){
		if (v[i].substr(v[i].length() - 1) == ".")
			v[i] = v[i].substr(0, v[i].length() - 1);
		if (v[i].substr(v[i].length() - 1) == ",")
			v[i] = v[i].substr(0, v[i].length() - 1);
		if(v[i].length() > 3){
			if (v[i].substr(v[i].length() - 2, 1) == "'")
				v[i] = v[i].substr(0, v[i].length() - 2);
		}
	}
	return v;
}

struct Words {
	string word;
	int counter;
};

int main(){
	while(true){

	string s;
	stringstream ss;
	vector<string> word;
	cout << "Enter a sentence: ";
	getline(cin, s);
	ss.str(s);
	while (!ss.eof() ){
		ss >> s;
		if (ss.good() )
			word.push_back(s);
		else {
			ss.clear();
			break;
		}
	}
	word.push_back(s);
	word = delNonAlphaV(word);
	string sWord;
	cout << "What word would you like to search for?\n"
			"(input 'ALL' for the frequency of each word): ";
	cin >> sWord;
	cin.ignore();
	cin.sync();
	int count = 0;
	vector<string>::iterator b,e;
	b = word.begin();
	e = word.end();
	while (b != e) {
		if ( *b == sWord) {
			count += 1;
		}
		b++;
	}
	unsigned int max = word[0].length();
	unsigned int min = word[0].length();
	vector<string> equalsH;
	vector<string> equalsL;
	vector<string> maxW;
	vector<string> minW;
	string tempString;
	b = word.begin();
	e = word.end();
	if (word.size() > 1) {
		while( b != e) {
			tempString = *b;
			if (tempString.length() > max )
				max = tempString.length();
			if (tempString.length() < min )
				min = tempString.length();
			++b;
		}
		b = word.begin();
		e = word.end();
		while (b != e) {
			tempString = *b;
			if (max == tempString.length() )
				equalsH.push_back(tempString);
			++b;
		}
		b = word.begin();
		e = word.end();
		while (b != e) {
			tempString = *b;
			if (min == tempString.length() )
				equalsL.push_back(tempString);
			++b;
		}
		if (equalsH.size() > 1)
			maxW = ddVect(equalsH);
		else
			maxW = equalsH;
		if (equalsL.size() > 1)
			minW = ddVect(equalsL);
		else minW = equalsL;
	}
	else {
		maxW = word;
		minW = word;
	}

	vector<string> word1 (word);
	vector<string> word2 (word);
	word1 = ddVect(word1);
	unsigned int const row = word1.size();
	Words freq[row];
	for(unsigned int r = 0; r < word1.size(); ++r){
		int count = 1;
		unsigned int d = 0;
		while(d < word2.size() ){
			if(r != d){
				if(word1[r] == word2[d]){
					count += 1;
					word2.erase(word2.begin()+d);
					d = 0;
				}
			}++d;
		}
	freq[r].word = word2[r];
	freq[r].counter = count;
	}

	if (maxW[0].length() == minW[0].length() ) {
		cout << "\nThe strings with the most and the least characters are the same length!: ";
		for(unsigned int i = 0; i < maxW.size(); ++i ){
			cout << maxW[i];
			if (i != maxW.size() - 1)
				cout << " & ";
			else {
				break;
			}
		}
	}
	else {
		if (maxW.size() != 1){
			cout << "\nThe strings with the most characters are: ";
			for (unsigned int i = 0; i < maxW.size(); ++i ){
				cout << maxW[i];
				if (i != maxW.size() - 1)
					cout << " & ";
				else {
					break;
				}
			}
		}
		else {
			cout << "\nThe string with the most characters is: " << maxW[maxW.size() - 1];
		}
		if ( minW.size() != 1){
			cout << "\nThe strings with the least characters are: ";
			for (unsigned int i = 0; i < minW.size(); ++i ){
				cout << minW[i];
				if (i != minW.size() - 1)
					cout << " & ";
				else {
					break;
				}
			}
		}
		else {
			cout << "\nThe string with the least characters is: " << minW[minW.size() - 1];
		}
	}
	if (count == 1)
		cout << "\nThere is " << count << " instance of the word: " << sWord << endl;
	else if (sWord == "ALL") {
		cout << endl << endl;
		for(unsigned int i = 0; i < word2.size(); ++i) {
			cout.width(max+4); cout << left << freq[i].word;
			cout << right << freq[i].counter << endl;
		}

	}
	else
		cout << "\nThere are " << count << " instances of the word: " << sWord << endl;

	cout << endl;
	}

	return 0;
}

Last edited on
I wanted it to look like "the dog walked to the park to eat by the tree"...

Very tough, maybe impossible to do effectively with an array (2d or otherwise). The main reason is that you don't really know that there will be 8 words and the most repeats three times. You don't know anything about what characters will appear. You would need an array that can change size, but, strictly speaking, this is not possible. However, in steps Vector, which is used in exactly that way:
vector<vector<string>>

It's a tricky little problem because of the unknowns. Once your vector<vector<string>> is made, the amount of times each string occurs is out of order. Such sorting a vector isn't designed to do efficiently. Sorting is "easiest" with a linked list. A Binary Tree will inherently be created in a sorted fashion (I would hope). As I said before, maybe the strings can be alphabetical, but the counts will be all over the place.

A good source for linked list? Maybe this:
http://www.codeproject.com/Articles/24684/How-to-create-Linked-list-using-C-C

You would want to at least be able to use class or struct before hand.

Because of the way a linked list is used, having [] or list.at(i) is not effective. You would want to create some sort of iterator. I found this site, which also is the best source I have found for making a linked list in general:

http://www.stanford.edu/class/cs107l/handouts/04-Custom-Iterators.pdf

Have fun :)
Wow thanks a lot LowestOne!

It's not impossible at all, in fact I did it. The problem I had was that I didn't know you couldn't have mixed data types in the array! I ended up being able to print out my strings or my counts. Since that was no good I built a simple struct that contained a string and an int and put it in a 1d array. That code is in my last reply just before this one.

Thanks a lot for the handout and article about linked lists. I'll definitely check that out tonight!

Here is the code that takes strings from a vector and sets them up in a 2D array like I was talking about.

Tell me what you think! Always having fun! :D

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

int mostFreq(vector<string> v) {
	int num1 = 1;
	int max = 1;
	for(unsigned int i = 0; i < v.size(); ++i) {
		unsigned int d = 0;
		if (num1 > max)
			max = num1;
		num1 = 1;
		while(d < v.size() ) {
			if(i != d) {
				if(v[i] == v[d]) {
					num1 += 1;
					v.erase(v.begin()+d);
					d = 0;
				}
			} ++d;
			if (v.size() == 1)
				if (num1 > max)
					max = num1;
		}
	}
	if (num1 > max)
		max = num1;
	return max;
}

vector<string> ddVect(vector<string> v){
	for (unsigned int i = 0; i < v.size(); ++i){
		unsigned int d = 0;
		while (d < v.size() ){
			if (i != d) {
				while (v[i] == v[d] && d < v.size() ){
					v.erase (v.begin()+d);
				}
			} ++d;
		}
	}
	return v;
}


int main() {
	string s;
	vector<string> word;
	cout << "Enter a sentence: ";
	getline(cin, s);
	size_t found;
		size_t found1;
		unsigned int spacecheck = 0;
		found = s.find_first_not_of(" ");
		for(unsigned int i = 0; i < s.length(); ++i){
			if(s.substr(i,1) == " ")
				break;
			else
				spacecheck += 1;
				if (spacecheck == s.length() )
					word.push_back(s);
		}
		if (word.size() == 0) {
			found1 = s.find_first_of(" ");
			while(found1 != string::npos){
				word.push_back(s.substr(found,found1-found) );
				found = found1 + 1;
				found1 = s.find_first_of(" ", found1 + 1);
			}
			found1 = string::npos;
			word.push_back(s.substr(found, found1) );
		}

	vector<string> word1 (word);
	vector<string> word2 (word);
	int MAX = mostFreq(word1);
	word1 = ddVect(word1);
	unsigned int const col = MAX;
	unsigned int const row = word1.size();
	string snt[row][col];
	for(unsigned int r = 0; r < row; ++r){
		int count = 1;
		unsigned int d = 0;
			while(d < word2.size() ){
				if(r != d){
					if(word2[r] == word2[d]){
						count += count;
						word2.erase(word2.begin()+d);
						d = 0;
					}
				}++d;
			}
	int i = 0;
	while (i < count){
		snt[r][i] = word2[r] + " ";
		++i;
		}
	}

	for(unsigned int r = 0; r < row; ++r) {
		for (unsigned int c = 0; c < col; ++c) {
			cout << snt[r][c];
		}
		cout << endl;
	}


	return 0;
}
Last edited on
Topic archived. No new replies allowed.