Topic: Simple C++ Typing-on-Input Question


Author: cflatter@nrao.edu (Chris Flatters)
Date: 16 Sep 1994 21:27:14 GMT
Raw View
In article 22941@nameserver.pwfl.com,  bakrdoug@nameserver.pwfl.com (Douglas Baker 407-796-8990) writes:
>I am new to C++ and have a simple question to ask.  I was playing with some
>simple examples trying to learn C++ and ran across an unusual behavior.
>The program accepts an INT representing miles and converts this to kilmeters.
>This is in a DO loop that terminates with a 0 or negative input. I have tried
>removing the simple inline function with no difference in operation.
>
>Everything works great when I enter integer values but not if I enter a
>floating point number.  The program looks like this:
>
> [...]
>
>When I compile and execute this, the following results:
>
>$ run mi_km
>Input distance in miles : 1
>Distance is 1 km.
>Input distance in miles : 10
>Distance is 16 km.
>Input distance in miles : 1.4
>Distance is 1 km.
>Input distance in miles :
>Distance is 1 km.
>Input distance in miles :
>Distance is 1 km.
>
>Interrupt
>
>[...]
>
>Anyone explain this?

What happens is that the << operator reads the stream up to the first
character that is not part of an integer.  When you enter "1.4" the "1"
is read from the stream and stored in the integer variable (miles)
leaving ".4" in the input stream.  The next time around the loop the <<
operator examines the first character in the input stream ('.'),
realizes that this can not be the first character of an integer, sets
the stream status to ios::failbit and leaves the variable unchanged.
The loop therefore repeats.  The next time through the extraction
operator will do nothing since the stream status has not been cleared
(see the man page for ios(3C++)) and from then on it's deja vu all over
again.

If an input stream can possibly hold invalid input then you should test
the stream status after an extraction.  For example

#include <iostream.h>

const double m_to_k = 1.609;
inline int convert(int mi) { return (mi*m_to_k);}

main()
{
  int miles;

  do {
       if (!cin.good())
       {
           cerr << "End of file or bad input: quitting" << endl;
           break;
       }
       cout << "Input distance in miles : ";
       cin >> miles;
       cout << endl << "Distance is " << convert(miles) << " km. " << endl;
     } while (miles > 0);

  return (0);
}



---
------------------------------------------------------------------------------
Chris Flatters      cflatter@nrao.edu
------------------------------------------------------------------------------
Well, our problem stems from the fact that we, basically, allow every planet
and moon-base this side of Alpha Centauri to make their own version of Spam.
       "Mystery Meat"
       Man... or Astroman?






Author: davidc@bruce.cs.monash.edu.au (David Chatterton)
Date: 17 Sep 1994 02:03:50 GMT
Raw View
Douglas Baker 407-796-8990 (bakrdoug@nameserver.pwfl.com) wrote:
: I am new to C++ and have a simple question to ask.

Such questions are better directed to comp.lang.c++

: I was playing with some
: simple examples trying to learn C++ and ran across an unusual behavior.
: The program accepts an INT representing miles and converts this to kilmeters.
: This is in a DO loop that terminates with a 0 or negative input. I have tried
: removing the simple inline function with no difference in operation.

: Everything works great when I enter integer values but not if I enter a
: floating point number.

There are two problems with your code.

: The program looks like this:
:
: //
: #include <iostream.h>

: const double m_to_k = 1.609;
: inline int convert(int mi) { return (mi*m_to_k);}

This function should take and return a double so that the miles is not
rounded to an int before being multiplied by your constant. Likewise if you
want a better answer you should return a double. This problem is minor
compared to the next one.

: main()
: {
:   int miles;

:   do {
:        cout << "Input distance in miles : ";
:        cin >> miles;

Here you are reading an int. The question you have to ask yourself is when
does this know the end of the number has been reached? Simple, whenever a
non-digit character is encountered.

:        cout << endl << "Distance is " << convert(miles) << " km. " << endl;
:      } while (miles > 0);

:   return (0);
: }


: When I compile and execute this, the following results:

: $ run mi_km
: Input distance in miles : 1
: Distance is 1 km.
: Input distance in miles : 10
: Distance is 16 km.
: Input distance in miles : 1.4

So what you have actually entered here is the digit 1, a character and then
another digit. So miles is set to 1, that is only a slight problem. As the
next character is a '.' it thinks that it has reached the end of its input
again. Suprisingly, the value of miles does not get changed and so equals
1, and the '.' does not get removed. Hence you get the same results again
and again until you break from the program. It never reads in the '4'.

: Distance is 1 km.
: Input distance in miles :
: Distance is 1 km.
: Input distance in miles :
: Distance is 1 km.
:
: Interrupt


: (locked in a loop).


: That was on a DEC Alpha running OpenVMS. I also tried it on a SUN running
: SUNOS with the same result.

Totally platform independant and should be compiler independant too.

: Anyone explain this?

Change your program so that you are completely using doubles, but if you
want an integer result just change you output to:

    cout << endl << "Distance is " << (int)convert(miles) << " km. " << endl;

Hope this helps.

David


David Chatterton     | "A new character has come on the scene (I am sure I did
Comp Sci Department, | not invent him, I did not even want him, though I like
Monash Uni, Clayton, | him, but there he came, walking out of the woods of
Australia, 3168.     | Ithilien): Faramir, the brother of Boromir."
Phone: 03 905 5375   | - in a letter from JRR Tolkien to his son, 4 May 1944.
email: davidc@bruce.cs.monash.edu.au




Author: bakrdoug@nameserver.pwfl.com (Douglas Baker 407-796-8990)
Date: Fri, 16 Sep 1994 17:21:48 GMT
Raw View
I am new to C++ and have a simple question to ask.  I was playing with some
simple examples trying to learn C++ and ran across an unusual behavior.
The program accepts an INT representing miles and converts this to kilmeters.
This is in a DO loop that terminates with a 0 or negative input. I have tried
removing the simple inline function with no difference in operation.

Everything works great when I enter integer values but not if I enter a
floating point number.  The program looks like this:

//
#include <iostream.h>

const double m_to_k = 1.609;
inline int convert(int mi) { return (mi*m_to_k);}

main()
{
  int miles;

  do {
       cout << "Input distance in miles : ";
       cin >> miles;
       cout << endl << "Distance is " << convert(miles) << " km. " << endl;
     } while (miles > 0);

  return (0);
}


When I compile and execute this, the following results:

$ run mi_km
Input distance in miles : 1
Distance is 1 km.
Input distance in miles : 10
Distance is 16 km.
Input distance in miles : 1.4
Distance is 1 km.
Input distance in miles :
Distance is 1 km.
Input distance in miles :
Distance is 1 km.

Interrupt


(locked in a loop).


That was on a DEC Alpha running OpenVMS. I also tried it on a SUN running
SUNOS with the same result.

Anyone explain this?

Thanks!


+===========================================+===============================+
| Douglas L. Baker                          |                               |
| Senior Computing Engineer                 |  Phone    : 1-407-796-8990    |
| Government Engines & Space Propulsion     |  Fax      : 1-407-796-4669    |
| Pratt & Whitney - West Palm Beach, Florida|  Internet : bakrdoug@pwfl.com |
+===========================================+===============================+