Need help for basic code

Hello, there is my program :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 #include <iostream>
int main() 
{
    int currVal = 0, val = 0;
    if (std::cin >> currVal) {
        int cnt = 1;
        while (std::cin >> val) {
            if (val == currVal) 
                ++cnt;
            else {
                std::cout << currVal << "occurs" << cnt << "times" << std::endl;
                currVal = val;
                cnt = 1;
            }
        }
        std::cout << currVal << "occurs" << cnt << "times" << std::endl;
    }
    return 0;
}


I am a beginner of C++.
Why when you have 2 cin, you don't have to enter the values twice?
In my head, we have to type a series of numbers for line 5, then another series of numbers for line 7, and we only type the series of numbers once in practice, how is that possible?
Line 5 is an if, so you only get one chance to enter one number.

Line 7 is a while, so you can enter as many numbers as you want.
Except that in practice, for example after writing the numbers 1 2 3 3 4 5 then entering: https://www.noelshack.com/2019-28-1-1562578196-screenshot-from-2019-07-08-11-29-00.png

Then Ctrl+D : https://www.noelshack.com/2019-28-1-1562578250-screenshot-from-2019-07-08-11-29-22.png

It seems I enter numbers for the if, but no one for the while because I need to enter a series of number
Last edited on
1 2 3 3 4 5

In the screenshot you did type:
1 2 3 4 5


If the while indeed does nothing, then what do you get from:
1
2
3
4
5
6
7
8
9
10
#include <iostream>
int main() 
{
    int currVal = 0, val = 0;
    if (std::cin >> currVal) {
        int cnt = 1;
        std::cout << currVal << "occurs" << cnt << "times" << std::endl;
    }
    return 0;
}

That should show that the "if" reads exactly one integer (if possible).


Almost same as your program:
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
#include <iostream>

int main()
{
    bool first = true;
    int currVal = 0;
    int val = 0;
    int cnt = 0;
    while ( std::cin >> val ) {
        if ( first ) {
            currVal = val;
            cnt = 1;
            first = false
        }
        else if ( val == currVal) {
            ++cnt;
        }
        else {
            std::cout << currVal << " occurs " << cnt << " times\n";
            currVal = val;
            cnt = 1;
        }
    }
    if ( !first ) std::cout << currVal << " occurs " << cnt << " times\n";
}

1 2 3 3 3 4 5 3 6 x
1 occurs 1 times
2 occurs 1 times
3 occurs 3 times
4 occurs 1 times
5 occurs 1 times
3 occurs 1 times
6 occurs 1 times
Hello Mur54,

Good use of code tags for just starting here.

Lets pick apart the program and hopefully you will come to understand what is happening.

The program:
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
#include <iostream>

int main()
{
	int currVal = 0, val = 0;  // <--- C++11 int currVal{}, val{};

	if (std::cin >> currVal)
	{
		int cnt = 1;

		while (std::cin >> val)
		{
			if (val == currVal)
				++cnt;
			else
			{
				std::cout << currVal << "occurs" << cnt << "times" << std::endl;
				currVal = val;
				cnt = 1;
			}
		} 

		std::cout << currVal << "occurs" << cnt << "times" << std::endl;
	}

	return 0;
}

First notice the blank lines. The compiler does not care about blank lines or white space, but the reader does. Since you write the code for some, including your-self, to read make it as easy as possible to read.

There are several different styles of writing code https://en.wikipedia.org/wiki/Indentation_style. I prefer the "Allman" style my-self, which is what the above code is done in. The point is that you should not mix different styles in the program code. It makes it confusing and hard to follow and slows down the rhythm of reading.

Some well placed blank lines separate the lines of code into different sections. Which tends to help keep the different parts in perspective. This part is something you will have to learn over time. For an example line 5 and line 7 are two different things. Separating these two lines with a blank line just makes sense.

Starting with the if statement on line 7. What is between the parentheses evaluates to either false (zero[0]) or true (1). So even if you are comparing two different variables the result will be either false or true. In this as long as "std::cin" is in a good state and usable it is considered true.


In my head, we have to type a series of numbers for line 5


The way this is set up you can only use one number. I will explain that shortly.

As long as you enter a number in the if condition and "std::cin" remains in a good state( I will cover that shortly too) "currVal" will only have one number stored in it. Say you enter "1 2 3 4 5" and press enter only the (1) will be stored in "currVal" and you will enter the if block. Because the "cin" will evaluate to true when it is finished.

The way "std::cin >>currVal" works. First this is known as formatted input. So when "cin" checks the variable and see that is id defined as an "int" "cin" expects a number to be entered. As long as you enter a number everything is alright. Should you enter a letter or punctuation character it will cause "cin" to fail and "cin" will no longer be usable.

There are times where you can use this to your advantage.

Now whether it is "std::cin", "std::cout" or a file stream they all have state bits associated with the stream. You can check out a nice truth table at http://www.cplusplus.com/reference/ios/ios/good/ and the rest of the page is worth reading.

The while loop on line 11 is similar to line 7 in that as long as you enter a number it keeps looping.

At this time you need to understand that if you enter (1 Enter) it will work one number at a time or you can enter (1 2 3 4 5Enter) it still works. This is because "std::cin >>val" is put into the input buffer and not directly into the variable. Only after you press "Enter" does it try to extract from the input buffer. Since "val" is defined as an "int" and it is expecting to extract a number as long as it is a number it will extract up to a white space or new line whichever comes first leaving whatever is left in the input buffer.

So when you enter (1 2 3 4 5Enter) the while loop will extract the (1) and stops at the space putting (1) into "val" for processing. When you get back to the top of the while loop the "std::cin >> val" will not wait for any input from the keyboard it will extract the (2) from the input buffer and stop at the space entering the loop for processing. When it finally reaches the new line it stops leaving "std::cin" ready for more input.

Here is where the formatted input can be used to end the while loop. You are entering "Ctrl D" to exit the while loop. This is just signaling "eof" and setting the "eof" bit to (1) and the "good" bit to (0) zero causing the while condition to be evaluated as false. This is where the formatted input can work to your advantage. Since it is expecting a number if you enter something that is not a number, like a letter or punctuation character this will cause "cin" to fail and the condition to evaluate to false thus exiting the while loop.

Another alternative is to check for a number like (-99) to signal the end and put an if statement as the first bit of code in the while and if the number is equal to (-99) then break out of the while loop.

Since you do not use "std::cin" after the while loop just entering a letter to cause the while condition to fail is all that is needed.

The test I did try produced:

2
1 2 3 2 4 5 2 6 2 7
2 occurs 1 times 
1 occurs 1 times 
2 occurs 1 times 
3 occurs 1 times 
2 occurs 1 times 
4 occurs 1 times 
5 occurs 1 times 
2 occurs 1 times 
6 occurs 1 times 
2 occurs 1 times 


I did change the "std::cout" statement to
std::cout << currVal << " occurs " << cnt << " times " << std::endl;. By putting a space at the beginning and end of the quotes strings it keeps the output from running together.

I believe you would want an output that looks more like:


2
1 2 3 2 4 5 2 6 2 7

1 occurs 1 times 
2 occurs 4 times 
3 occurs 1 times 
4 occurs 1 times 
5 occurs 1 times 
6 occurs 1 times 
7 occurs 1 times 


This will take some changes to the code and you may need to add an array or vector to do this. I will help you through that if it is something that you want to do.

For lines 7 and 11 you give no idea of what to enter. Line 7 needs a prompt as to what to enter. And line 11 needs a prompt before the while with an example of how the information (numbers) are to be entered. For the while loop something like:
1
2
3
4
std::cout<<"\n Enter a number to compare to: ";  // <--- For line 7.

std::cout<<"\n Enter a series of numbers (1 2 3 4 5 a) and press enter"
"\n The last entry is something that is not a number: ";  // <--- For line 11. 


BTW to go with what salem c is saying if you enter something like (1 2 3Enter) for line 7 it will only put the (1) into "currVal" and leave the rest in the input buffer for the while loop to extract. Based on the way your code is written line 7 is designed to only need one number. Anything more is a potential problem.

If you find anything that you do not understand let me know.

Hope that helps,

Andy
Topic archived. No new replies allowed.