I don't get the "Detect repeated words" program in Practise and Principles using C++

I've been over this chapter about an hour and I just can't figure out how this program works. I think I should just stop learning to program if this is how hard it is. This is how my mind works. We define string and previous means " ". Then we make a loop and input the data. I for example enter "hey hey how are you doing?". So if previous (" ") is equal to current (hey hey how are you doing?), print on the screen "Repeated Word: current (hey hey how are you doing?)"

I just don't get why the if statement works. " " isn't equal to "hey hey how are you doing?" I'm just really sad that I don't get this example. I've been so excited to get this book and start learning to program but I guess this isn't for me.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include<iostream>
#include<fstream>
#include<sstream>
#include<cmath>
#include<cstdlib>
#include<string>
#include<list>
#include<vector>
#include<algorithm>
#include<stdexcept>

using namespace std;

int main()
{
   string current;
   string previous = " ";

   while (cin>>current){
        if(previous == current)
            cout << "Repeated Word: " << current << "\n";
        previous = current;
   }
}
Last edited on
You are certainly correct that " " != "{text}". But look what comes after the if statement: previous=current
That assigns the value of current to previous.

So, on the first round, let's say we input "foo" when it asks. The code in the if statement will not execute because "foo" is not equal to " ". Then it assigns "foo" as the value of previous.
So previous now is "foo" instead of " ".
So, on the next round, if we input "foo", the if statement will execute, and the console will read "Repeated Word: foo"

Oh, and btw, the only #includes you need are <string> and <iostream>, if that's the only code you have.

Programming can get difficult, sometimes I come across errors that take days to solve. Don't let that discourage you. I find programming to be fun and interesting, even though sometimes I'm like this: https://i.imgflip.com/ghg4t.jpg
Thanks for the reply man. Yeah it is fun until you come across an error but really thanks for the reply. It clears things up and I won't give up. This is me most of the time http://d.justpo.st/media/images/2013/05/110a7fec924b161ca30c61c86676757f.jpg
Last edited on
Also, I thought programs work in chronological order. Like it starts reading and executing from line 1>100 etc. Am I wrong?
Last edited on
I think what you're not getting is that cin ignores whitespaces, so if you enter "HEY HEY" it will read the first HEY, then execute the rest of the code (if statement, which will yield false, then it continues to assign current (which is HEY) to previous. It will then read the other HEY and do it all over again, but this time the if statement is true and you will see "repeated words"

I think that's what happens (I used to be stuck on this too), what I said is probably in boring detail, during program execution it all happens in less than a second.

Please, if any experienced programmer can confirm what I said.. that would be great. Because I'm less than a beginner, but I thought I could help.
Sorry if I sound like a complete noob @Josephreak but what do you mean it ignores whitespace? So if input in the program "What's up", it will actually be "What'sUp? Am I right or am I wrong? And also, I thought programs execute in order, am I right about this? What I mean by this if I type

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <string>

using namespace std;

int main()
{
      cout << hText << endl;
      string hText = "Hello";
}


This won't work because it hasn't been "assigned" yet. So then how does previous = current; work?
Last edited on
Welcome to the forum, Ned757.

"Whitespace" refers to any characters that are used for formatting purposes, such as spaces, tabs and newline characters.

std::cin will read input until it comes across a whitespace character, turning "What's up" into "What's". The remaining data is effectively discarded and lost.

To read an entire line of characters without skipping spaces, you can use std::getline(). Here's an example of how you might use it:

1
2
3
std::string fullName;
std::cout << "Enter your full name: ";
std::getline(std::cin, fullName);


Notice the first argument for std::getline() is std::cin. This is simply an std::istream object.


This won't work because it hasn't been "assigned" yet.

Essentially, yes. A smart compiler won't let you do this.

So then how does previous = current; work?

Let's take another look at your initial code:

1
2
3
4
5
while (cin>>current){
        if(previous = current)
            cout << "Repeated Word: " << current << "\n";
        previous = current;
   }


This is your code before you edited your original post, note the change from == to =.

== is the equality comparison operator.
= is the assignment operator.

On line 1 of the snippet, you're reading data into current.
On line 2 of the snippet, you're assigning current to previous, this is not a comparison. C++ let's you put assignments in if() control structures like that because technically, an assignment operation can be interpreted as a true-or-false statement - previous returns it's value after the assignment to the calling code, which, in the conditional if control structure, will be true as long as that value is non-zero.

That's a mouthful, here's a simpler example.

1
2
3
4
int a = 0;
if (a = 5) {
	/*...*/
}


The operation a = 5 on line 2 returns 5.
It effectively becomes this:

if(5) {//...

Since 5 is a non-zero value, the expression is evaluated as true, therefore, the condition is satisfied and the if branch executes.

The same is true for strings:

if("abc") {

This will evaluate to true. I forget which criteria have to be met in order for strings to be evaluated as false. Online sources say the string must be empty, but even the following yields true:

if("") {

So, don't ask me why this that's the case - maybe someone else can enlighten me.
Last edited on
Ahh I finally get what you mean by cin and >>. So it just reads the first word inputted and discards the rest? And thanks alot for the reply, you sum it up really good!
Last edited on
I don't think I changed from "=" to "==". Did you make an error in your post?
I know this is a different topic but I don't get the difference between void and main. People say void returns nothing while int returns an integer. They can be used the same way. I don't get what they mean they return an integer because it technically doesn't display an integer, can someone explain that? (I bet you experienced programmers are face-palming but I won't give up on my mistakes)
Last edited on
Sorry for the late response.

I don't think I changed from "=" to "==". Did you make an error in your post?

I assumed you went back and edited your original post to change it from '=' to '==' after Homberto pointed it out.

I don't get the difference between void and main

I think you meant, void and int, yes?

Every function must have a return type, such as void or int or any other type you can think of.
It's up to the programmer to decide what to do with the things returned from functions. Just because a function returns something doesn't necessarily mean that it will be printed. If the programmer wants to print the returned value of a function, then it's up to them to make it happen.

What makes a void function unique (as you already pointed out) is that it returns nothing. You'd use void as a function return type when you don't want a function to return something:
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>

void sayHello() {
	std::cout << "Hello" << std::endl;
}

int main() {

	sayHello();

	std::cin.get();
	return 0;
}


'sayHello' is a void function because it doesn't return anything. It simply prints "Hello".

If, on the other hand, I did something like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>

std::string returnHello() {
	std::string helloString = "Hello";
	return helloString;
}

int main() {

	std::cout << returnHello() << std::endl;

	std::cin.get();
	return 0;
}


The end effect is the same. The program prints "Hello". The differences being:

1.) There is no longer a void 'sayHello' function, instead we have a 'returnHello' function which returns a std::string object.
2.) The actual printing occurs in the main function, which makes a call to 'returnHello'.

As you can see, it is up to the programmer to make use of the values returned by functions. If functions are written in such a way that they return something (in other words, they are not void), one can assume that the result is important, otherwise, why should the function return anything?
However, it is entirely possible to simply ignore the values returned by functions. You don't need to do anything with returned values, but it's a strange thing to do since you, as the programmer, wrote the function in such a way that it returns something.
The following is entirely valid, but pointless.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <string>

std::string returnHello() {
	std::string helloString = "Hello";
	return helloString;
}

int main() {

	returnHello();
	//returned string object isn't being used for anything. Is effectively discarded and lost forever.

	//nothing happens
	std::cin.get();
	//the program ends
	return 0;
}


That was some preliminary stuff. Now, on to the main function.

The C++ standard dictates that the main function must have a return type of int. The reason for this is that it allows a programmer to indicate whether or not a program executed successfully:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>

bool there_was_an_error() {/*check for errors*/}

int main() {

	if (there_was_an_error()) {
		//Oh no! Let's return 1 to indicate a failure.
		return 1;
	}
	else {
		//Yay! Everything went smoothly.
		return 0;
	}
}


Note that this program is incomplete, because the function 'there_was_an_error' doesn't return anything yet. I left it empty and put a comment there because this is simply pseudo-code. We can assume that the 'there_was_an_error' function returns true when there was an error, and false when there was none. What errors it's checking for is entirely arbitrary and irrelevant.

In the program above, the programmer decided to indicate a failure with "1" and success with "0". These numbers are also arbitrary, and only mean something to someone or something that knows what these numbers represent - in this case, whether or not the program executed successfully. When used like this, these numbers go by a variety of names such as "return codes", "error codes" or "exit codes" - these names all basically mean the same thing.

One example where you might experience error codes in action is with an installation wizard. If you're installing a program, but something goes wrong, the setup will return a "failure" error code to the operating system. I don't know which operating system you're using, but when that happens to me on my windows machine, the operating system responds to that kind of failure error code with a "Did this install correctly?" dialog box.

In reality, there is no real reason for the main function to return integers specifically, it's pretty arbitrary. I suppose it's just that integers lend themselves to representing error codes, since they are numbers - it's also just what the standard decided on.
Last edited on
Topic archived. No new replies allowed.