Cracknut
Cracknut

Reputation: 3

How is if (cin) { while(cin)... Works?

int main () {
int num1, num2;
int cnt = 1;
    if (cin >> num1){       
        while (cin >> num2){
              if (num1==num2){
                  ++cnt;
              } else {
                  cout << num1 << " is " << cnt << " times" << endl;
                  cnt = 1;
                  num1 = num2;
              }
        }
    }
    cout << num1 << " is " << cnt << "-times" << endl;
}

This code accepts a line of numbers and outputs how many times each number was entered. What I dont understand is why there is num1=num2. With removing it program outputs the first number which was entered, which lead me to believe that I don't know how cin works in loops.

What I think now is that first digit goes into if (cin >> num1), and it keeps sitting here and next same digits don't overwriting num1 integer. Second and the rest digits going into while (cin >> num2) overwriting it every time until there is a different number, which makes else to execute and it outputs number which was stored in num1 the whole time.

With num1=num2 it changes num1 in if(cin>> num1) and the whole thing starts again. Am I right?

Which also strange that the very last cout may sure inside of first if body, and it may not, it works anyway...

Edit1: with num1=num2; I input 1 1 2 2 3 3 3, as one line, it outputs

1 is 2 times

2 is 2 times

3 is 3 times. 

Without num1=num1;

1 is 2 times

1 is 1 times

1 is 1 times

1 is 1 times

1 is 1 times

Upvotes: 0

Views: 734

Answers (4)

Swordfish
Swordfish

Reputation: 13134

#include <iostream>

int main () {
    int num1, num2;
    int cnt = 1;
    if (std::cin >> num1) { // if a valid integer can be extracted from cin
        while (std::cin >> num2) { // do as long as valid integers are extracted from cin
            if (num1 == num2) { // if the first extracted int matches the next one
                ++cnt; // increase the count
            }
            else { // if it is a different int then do some output and
                std::cout << num1 << " is " << cnt << " times\n";
                cnt = 1; // reset the counter and
                num1 = num2; // remember the new extracted number for
                             // the next iteration of the while-loop
                             // since only num2 will be read again from cin
            }
        }
    }
    std::cout << num1 << " is " << cnt << "-times\n";
}

Since the last line in main() is meaningless if there is no valid input i'd advocate for early exit:

#include <cstdlib>
#include <iostream>

int main () {
    // ...
    if (!( std::cin >> num1 ))
        return EXIT_FAILURE;

    while (std::cin >> num2) {
        if (num1 == num2) {
    //  ...

it also reduces indentation levels and thus enhances readability.

Upvotes: 4

DaMachk
DaMachk

Reputation: 643

The first if if (cin >> num1) checks if there was an input (waits for the input, of course) into num1, only then will it continue to the loop.

Then it waits for the second input into num2 and enters the loop, if the input is empty.

Then it compares the two inputs. If they're the same... it increments the counter. Otherwise, it will output how many times that same input was detected in a row and then change the comparing input to the last entered value and repeat the loop, waiting for an input.

So it compares how many times after another you're providing the same input...

Basically if the input is:

5
5
5
1

The output will be "5 is 3 times"

and if the input is

1
5
5
5

The output will be "1 is 1 times"

Upvotes: 0

sepp2k
sepp2k

Reputation: 370092

cin >> num1 tries to read a number from the standard input into the num1 variable. If that succeeds, the body of the if will be executed. Otherwise (e.g. if the user entered something other than a number or pressed Ctrl-d/Ctrl-z right away), we jump directly to the code after the if. This happens exactly once.

cin >> num2 does the same thing with the num2 variable, except this time it's inside a while instead of an if. So if the input operations succeeds, the body of the while loop executes and cin >> num2 is then executed again until it eventually fails.

What I dont understand is why there is num1=num2.

As I said, cin >> num1 only executes once (it's not inside any loop). So if you never re-assign num1, it will always keep the first value that was entered. But you don't want that, you want it to contain the value you're currently counting. That's why that assignment is there.

With num1=num2 it changes num1 in if(cin>> num1) and the whole thing starts again. Am I right?

No, cin >> num1 never executes again. It's not inside a loop. Only cin >> num2 is executed multiple time because that one's part of the while loop.

Which also strange that the very last cout may sure inside of first if body, and it may not, it works anyway...

If the first input operation fails, it will jump to the outside of the body right away. If the cout statement is there, that will mean that it will be executed even if the first input failed. In that case num1 will be uninitialized, so using it will invoke undefined behaviour. Therefore that statement should not be outside of the if.

Upvotes: 1

vijoc
vijoc

Reputation: 693

What I understand the code does is calculate and display the number of consecutive appearances of a number, so it wouldn't work for an unordered list.

That said, how it works is essentially as follows:

  1. See if there is a number available in the stream, and if so, store it in num1.
  2. For each following number, read the number to num2.
  3. If num1 and num2 are the same, increment the counter.
  4. If, however, the numbers are not the same: output the repeat count, set the counter to 1, and change the first number of comparison (num1) to the newly read number (num2).

Upvotes: 0

Related Questions