Exercise from C++ Primer

Hi, I done this exercise for the book I am reading. Here is the exercise:

Write a program to read strings from standard input
looking for duplicated words. The program should find places in the input
where one word is followed immediately by itself. Keep track of the largest
number of times a single repetition occurs and which word is repeated. Print
the maximum number of duplicates, or else print a message saying that no
word was repeated. For example, if the input is

how now now now brown cow cow

the output should indicate that the word now occurred three times.

Here is the code I wrote:

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
int main()
{
	vector<string> v;
	string s;
	while (cin >> s)
		v.push_back(s);
	auto it = v.begin();
	unsigned maxrepeats = 1, repeats = 1;
	string prev, word;
	while (it != v.end()) {
		if (*it == prev) {
			++repeats;
			if (repeats > maxrepeats) {
				maxrepeats = repeats;
				word = *it;
			}
		}
		else
			repeats = 1;
		prev = *it;
		++it;
	}
	if (!word.empty())
		cout << word << " occured " << maxrepeats << " times in a row." << endl;
	else
		cout << "There are no repeating words" << endl;

	return 0;
}


The program seems to work okay but I can't help thinking that there is a better way to do it.

Anyone have any ideas? I'm just trying to improve my coding, it's not like this program needs to run extremely efficiently or anything.

Thanks!
Check std::map
Hmm, looks interesting. Haven't got into much of the STL yet except the basics of vectors, strings and such.

Thanks for the reply.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <string>

/*
Write a program to read strings from standard input
looking for duplicated words. The program should find places in the input
where one word is followed immediately by itself. Keep track of the largest
number of times a single repetition occurs and which word is repeated. Print
the maximum number of duplicates, or else print a message saying that no
word was repeated. For example, if the input is

how now now now brown cow cow

the output should indicate that the word now occurred three times.
*/

int main()
{
    int max_dup_count = 1 ; // maimum repetion count
    std::string max_duplicated_word ; // word that was repeated maximum times

    int running_dup_count = 1 ; // repetition count for the word just read
    std::string previous_word ; // the word that was just previous to the current one

    std::string word ;
    while( std::cin >> word ) // for each word that is read
    {
        if( word == previous_word ) // if it is the same as the previous word
        {
            ++running_dup_count ; // increment repetition count for the word just read
        }
        else // it is different from the previous word
        {
            if( running_dup_count > max_dup_count ) // if the dup count is the largest so far
            {
                // update max_dup_count, max_duplicated_word
                max_dup_count = running_dup_count ;
                max_duplicated_word = previous_word ;
            }

            running_dup_count = 1 ; // new word, reset count
            previous_word = word ; // and this becomes the previous word now
        }
    }

    if( max_dup_count > 1 )
    {
        std::cout << "word '" << max_duplicated_word << "' was repeated "
                   << max_dup_count << " times.\n" ;
    }
    else std::cout << "no word was repeated.\n" ;
}
Yep, that makes a hell of a lot more sense than mine did. It will only execute the if statement if word != previous_word.

Whereas in mine it was testing whether the running count was greater than the max every time it was repeated.

I guess it's good to know that I wasn't too far off the mark though.

Also, do you ever use the using declaration? e.g. using std::string;
If not, why not? I heard it can cause conflicts sometimes but is there any other downsides?

Thanks.
> It will only execute the if statement if word != previous_word. Whereas in mine it was testing
> whether the running count was greater than the max every time it was repeated.

That made me look at my code a second time; and it is broken.

What happens if we enter "how now now now brown cow cow cow cow cow" ?
(The last word is the one that repeats the most number of times).
I'll leave fixing that bug as as an exercise for you.



> do you ever use the using declaration? e.g. using std::string;

Never for something like std::string.
But if the name is a long one, or for composing a namespace with selection, I do use the using declaration.

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
namespace A
{
     struct foo { /* ... */ } ;
     struct bar { /* ... */ } ;
     void function() ;

     // ...

}

namespace B
{
     struct foo { /* ... */ } ;
     struct bar { /* ... */ } ;
     void another_function() ;

     // ... 
}

namespace my
{
    using std::place_holders::_1 ;
    using std::place_holders::_2 ;
    using A::foo ;
    using B::bar ;
    using A::function ;
    using B::another_function() ;
    
    // ...
}


For many long names from the same namespace, I tend to prefer namespace aliases over using declarations.

1
2
3
4
5
6
int main()
{
    namespace qi = boost::spirit::qi ;
    ...
    qi::parse( ...., qi::int_ .... ) ;  
}

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

/*
Write a program to read strings from standard input
looking for duplicated words. The program should find places in the input
where one word is followed immediately by itself. Keep track of the largest
number of times a single repetition occurs and which word is repeated. Print
the maximum number of duplicates, or else print a message saying that no
word was repeated. For example, if the input is

how now now now brown cow cow

the output should indicate that the word now occurred three times.
*/

int main()
{
	int max_dup_count = 1; // maimum repetion count
	std::string max_duplicated_word; // word that was repeated maximum times

	int running_dup_count = 1; // repetition count for the word just read
	std::string previous_word; // the word that was just previous to the current one

	std::string word;
	while (std::cin >> word) // for each word that is read
	{
		if (word == previous_word) // if it is the same as the previous word
		{
			++running_dup_count; // increment repetition count for the word just read
		}
		else // it is different from the previous word
		{
			if (running_dup_count > max_dup_count) // if the dup count is the largest so far
			{
				// update max_dup_count, max_duplicated_word
				max_dup_count = running_dup_count;
				max_duplicated_word = previous_word;
			}

			running_dup_count = 1; // new word, reset count
			previous_word = word; // and this becomes the previous word now
		}
	}

	if (running_dup_count > max_dup_count) 
	/* one last check outside the loop that 
	will catch the last set of repeated words, if any */
	{
		// update max_dup_count, max_duplicated_word
		max_dup_count = running_dup_count;
		max_duplicated_word = previous_word;
	}

	if (max_dup_count > 1) {
		std::cout << "word '" << max_duplicated_word << "' was repeated "
			<< max_dup_count << " times.\n";
	}
	else std::cout << "no word was repeated.\n";
}


Okay, so all I done was added the same if outside the loop in order to catch the last set of words that will not be tested by the if inside the loop because it will not execute the else statement. This is because the last "cow" entered will be true so the code to set the max count and word won't run.

I'm thinking that there is another way of doing it without duplicating the code outside the loop but can't figure it out.

I haven't gotten into namespaces yet but I can see why it is important in some situations.
Last edited on
> Okay, so all I done was added the same if outside the loop in order to catch the last set of words
> that will not be tested by the if inside the loop because it will not execute the else statement.
> This is because the last "cow" entered will be true so the code to set the max count and word won't run.

Yes. That is all that is required.



> I'm thinking that there is another way of doing it without duplicating the code
> outside the loop but can't figure it out.

What you have done is good enough. Keep it as simple as possible.

When in doubt, use brute force - Ken Thompson
(prefer simple, robust, and portable code over brittle ‘smart’ code)
.

Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. - Brian Kernighan
Okay, thanks for your help. I can read on in my book now. Amazing book by the way, C++ Primer 5th Edition.

Haha, great quotes. Did you ever notice that all the best programmers have beards? Must be some special powers about them.
Topic archived. No new replies allowed.