Solved

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

Posted on 2004-03-29
6
1,411 Views
Last Modified: 2007-12-19
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
Comment
Question by:AndyCV6
6 Comments
 
LVL 15

Assisted Solution

by:lakshman_ce
lakshman_ce earned 20 total points
ID: 10709951
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
 

Author Comment

by:AndyCV6
ID: 10710245
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
 
LVL 15

Assisted Solution

by:efn
efn earned 50 total points
ID: 10710405
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
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 

Author Comment

by:AndyCV6
ID: 10711081
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
 
LVL 15

Assisted Solution

by:efn
efn earned 50 total points
ID: 10711367
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
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 55 total points
ID: 10712645
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 Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

747 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now