user3678093
user3678093

Reputation: 47

C++ reading input from cin until the whole line has been read

I have a while loop reading in a char 'c', I have a check to see if the the char is an operator; '+', '-', '/', or '*'. The while loop reads through character by character but it doesn't stop...if the last char inputed is '+' for example. It will stay in the loop with the char 'c' set to '+' forever.

stack<int> num;
char c;
int n,count=0,a,b;
while (cin>>c)
{
    if (c != '+' && c != '-' && c != '/' && c != '*')
     {
         cout << c << endl;
         n = (c - 48);
         num.push(n);
         cin >> c;
         count++;
     }
     else if (c == '+' || c == '-' || c == '/' || c == '*')
     {
         cout << "count is " << count << endl;
         if (count>1)
         {
            b =  num.top();
            a = num.top();
            num.pop();
            num.pop();

            if (c == '+')
            {
                num.push(a+b);
                count--;
            }
            else if (c == '-')
            {
                num.push(a+b);
                count--;
            }
            else if (c == '/')
            {
                if (b != 0)
                {
                    num.push(a/b);
                    count--;
                }
                else
                {
                    cout << "division by zero" << endl;
                    return(0);
                }
            }
            else if (c == '*')
            {
                num.push(a*b);
                count--;
            }
            else
            {
                cout << "invalid input" << endl;
                return(0);          
            }
         }
         else
         {
             cout << "stack underflow" << c << endl;
             return(0);
         }
     }
     cout << c << endl;
 }
}

Upvotes: 2

Views: 2087

Answers (4)

Teo Zec
Teo Zec

Reputation: 381

This should work:

#include <cstdio>
...

int c; // As pointed out by James Kanze in his comment, c should be an int to detect EOF
do {
    c = getchar();
    // Do stuff
} while ((c != '\n') && c != EOF))

You don't need to check just for EOF, but also for the line terminator.

Upvotes: 1

James Kanze
James Kanze

Reputation: 153909

There are several problems with your code. For starters, I don't understand the purpose of the cin >> c in the if branch; you input a character, but you never seem to use it; it's just lost. And of course, there's no need for the if part in the else if, since it is the complement of the condition of the if. And of course, a switch is far more natural that you if/else if chain when comparing a single character against a number of different constants. And of course, '0' isn't always 48 (and even if it were, '0' is a lot more readable than 48).

As for staying in the loop with the char c set to +, I don't see it. The only loop I see is while( std::cin >> c ), and this will either read a new character, or terminate.

If your goal is to just read a single line, it's probably better to use std::getline, then iterate over the string you input:

std::string line;
while ( std::getline( std::cin, line ) ) {
    //  Set up your stack here...
    for ( std::string::const_iterator it = line.begin(); it != line.end(); ++ it ) {
        if ( isdigit( static_cast<unsigned char>( *it ) ) ) {
            //  process digit...
        } else if ( ispunct( static_cast<unsigned char>( *it ) ) ) {
            //  process punctuation, with eventually
            switch ( *it ) {
            case '+':
                //  addition...
                break;
            case '-':
                //  substraction...
                break;
            //  ...
            default:
                //  illegal operator...
                break;
            }
        } else {
            //  process anything else...
        }

    }
}

Alternatively, you can define an isOperator function, along the lines of:

bool
isOperator( char ch )
{
    static std::string const legalOps( "+-*/" );
    return std::find( legalOps.begin(), legalOps.end(), ch) != legalOps.end();
}

Upvotes: 1

AliciaBytes
AliciaBytes

Reputation: 7429

Now that you clarified your question it's way clearer. And @TeoZec answer should be right. I just wanna note two things that seem buggy in your above code:

else if (c == '-')
{
    num.push(a+b);
    count--;
}

here you probably wanted a-b instead.

if (count>1)
{
    b =  num.top();
    a = num.top();
    num.pop();
    num.pop();

b and a will be the same number here, you should call pop() before getting the second number, like:

if (count>1)
{
    b =  num.top();
    num.pop();
    a = num.top();
    num.pop();

Upvotes: 3

Daniel
Daniel

Reputation: 588

Its because you have no condition to terminate your while loop, you will need to add either more conditions to your while like so:

while(cin>>c && c != '+' && c != '-' && c != '*' && c != '/')
{
    //do stuff here
}

Or add a break to the inside of your while loop, after performing your checks to see what character was entered.

Upvotes: 1

Related Questions