Solved

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

Posted on 2004-03-29
6
1,460 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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 

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 Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

829 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