Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1668
  • Last Modified:

Need help with a while loop using cin.peek()

I need help finding some logic errors. My program is getting stuck in the two while loops. This program takes two numbers and then formats the output to scientific notation. Here is the first part of my code. Any help would be greatly appreciated!

int main()
{
      double x, y;

      x = readNum();
      y = readNum();
      //printFormatted( x, y );

      return 0;
}

double readNum()
{
      
      double num = 0;
      double place = 10;
      char numb[20];
      cout << "Enter a number: ";
      cin.get(numb, 20);

      while (cin.peek() != '.' || cin.peek() != '\n')
            num *= static_cast<double>(cin.get() ) + 10;
            
      while (cin.peek() != '\n') {
            num += static_cast< double >( cin.get() ) / place;
            place *= 10;
      }
      
      cin.ignore();
      return num;
}
0
AndyCV6
Asked:
AndyCV6
4 Solutions
 
lakshman_ceCommented:
I couldn't understand why you are using cin.peek() here. cin.peek() prompts for entry by user

Just try this..code for reading two numbers

double readNum()
{
   
     double num = 0;
     double place = 10;
     cout << "Enter a number: ";
     num *= static_cast<double>(cin.get() ) + 10;
     num += static_cast< double >( cin.get() ) / place;
     place *= 10;      
     cin.ignore();
     return num;

}
Please refer to for using cin.peek()
http://www.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20789094.html

-Lakshman
0
 
AndyCV6Author Commented:
I am trying to learn about cin.peek(). Is there any reason why that it would not work like I have it? Doesn't cin.peek() look at each character? In the first loop, I want it to look at each character and stop when it comes to a '.' or a newline. My end result from this program should be two numbers formated like so:
x is +2.346000000
y is      8.95e-001

I will check out that link you gave me and see if that helps.

Thanks
0
 
efnCommented:
I was going to advise you not to use peek until I saw your last comment.

The call to get leaves the terminating newline character in the input stream, so if the next loop is terminated by a newline character, it will end before it reads anything.

It's not advisable to call peek twice in the same expression, because you could get different results each time if input appeared between the two calls.  This is just a fine point, not likely to be a problem in your testing.

The first while loop will run as long as peek returns something that is either not a period or not a newline.  What could peek return that would cause the loop to end?  If it's a period, it's not a newline, so the loop still runs.  If it's a newline, it's not a period, so the loop still runs.

The call to get consumes the first line input, not including the newline character.  You as the user must know that after you enter a number and press Enter, you still have to enter another number and press Enter again.  Perhaps you were doing that.

The American Standard Code for Information Interchange, commonly known as "ASCII" specifies a correspondence between the numeric values of characters and the character representation used in input and output with humans.  For example, the character '1' has a numeric value of 49.  When you cast a character to double, you get the numeric value.  For example, a '1' character will give you a double value of 49.0.  This is probably not what you want.  A simple way to convert a digit character to the corresponding numeric value is to subtract '0' from it.  This doesn't work so well with characters that are not digits, so industrial-strength software would check for that possibility.

num is initialized to zero.  The first loop attempts to multiply it by input numbers.  Since zero times anything is zero, this is unlikely to change the value of num.

--efn
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
AndyCV6Author Commented:
ok, i read the info from the link, and what  efn posted. I made some changes to my code. It will now break out of the loops but, my output is still not right. I am not sure what to do about initializing num. Let me post all of my code for this program.

#include <iostream>

using std::cout;
using std::endl;
using std::cin;
using std::ios;

#include <iomanip>

using std::setw;
using std::setprecision;
using std::resetiosflags;
using std::setfill;
using std::setiosflags;

double readNum();
void printFormatted( double, double );

int main()
{
      double x, y;

      x = readNum();
      y = readNum();
      printFormatted( x, y );

      return 0;
}

double readNum()
{
      double num = 0;
      double place = 10;
      cout << "Enter a number: ";

      while (cin.peek() != '.' && cin.peek() != '\n')
            num *= static_cast< double >( cin.get() ) + 10;
      //cin.ignore();
      
      while (cin.peek() != '.') {
            num += static_cast< double >( cin.get() ) / place;
            place *= 10;
      }
       cin.ignore();
       return num;
}

void printFormatted( double x, double y )
{
      char buffer[] = "The value of x is: ";
       for( int i = 0; buffer[ i ] != '\0'; i++ )
             cout.put( buffer[ i ] );

       cout << setprecision( 3 ) << setfill( '0' )
             << setiosflags( ios::fixed | ios::showpos )
             << setiosflags( ios::left ) << setw( 12 ) << x << endl;

       cout.write( "The value of y is: ", 21 );
       cout << resetiosflags( ios::showpos )
             << setprecision( 3 )
             << setiosflags( ios::scientific | ios::right )
             << y << endl;
}

0
 
efnCommented:
The last two bugs I described are still there.

If you are trying to build up a number by reading its digits from left to right, each time you get a new digit, you should multiply what you had so far by 10 and then add the digit.  So you want something like this:

number = (number * 10) + digit;

What you have (if you fix the casting-to-double bug) is:

number *= digit + 10;

This is equivalent to

number = number * (digit + 10);

The problem is not initializing num to zero.  The problem is the calculation.

--efn
0
 
itsmeandnobodyelseCommented:
As efn has told you the calculation (and loop conditions) were wrong. Try this.

double readNum()
{
     double num = 0;
     double place = 10;
     char   digit;

     cout << "Enter a number: ";

     while ((digit = cin.peek()) != '.' && digit != '\n')
     {
         if (digit < '0' || digit > '9')
         {
             cout << "Invalid digit " << digit << endl;
             exit(1);
         }
         // eat digit
         cin.get();
         num = num * 10. + (digit - '0');
     }

     if (digit == '.')
     {
         // eat period
         cin.get();

         while ((digit = cin.peek()) != '\n')
         {
             if (digit < '0' || digit > '9')
             {
                 cout << "Invalid digit " << digit << endl;
                 exit(2);
             }
             // eat digit
             cin.get();
             num += (digit - '0') / place;
             place *= 10;
         }
     }
     cout << "Valid number is " << num << endl;
     cin.ignore();
     return num;
}

Regards, Alex

0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now