简体   繁体   中英

C++ int or double input

I'm looking to clean up some already-functioning code I have. First of all, this is for an assignment and the assignment specifies ints must be taken as ints, doubles as doubles, etc, otherwise I might just take the input as a double and cast as an int if(number%1==0) .

I've trimmed the code down to just handling the input (with an output statement to verify it's working properly).

int wholePart=0;
double decimalPart=0;
cout << "Input a number: ";
cin >> wholePart;
if(cin.peek() != '\n')
    cin >> decimalPart;

cout << "wholePart = " << wholePart << endl << "decimalPart = " << decimalPart << endl;

Now... this works as is, and after I add the code to handle combining the integer and decimal if the decimalPart isn't 0, then I've already done more than the assignment calls for, but I'm looking to learn, and I want to clean this code up as much as possible.

I can wrap the whole input section with other input validation to be sure the user is actually entering numbers and not characters. But my primary concern here is that if(cin.peek() != '\\n') isn't good enough. Perhaps if(cin.peek() == '.') is a better option, but I'm curious what would be the best way of going about accomplishing what I'm trying to accomplish here. Any ideas?

And please don't just turn this down as "oh it's homework." I want to emphasize that my program already goes above and beyond what even the extra credit part of the homework asks for. I'm just trying to learn more about the language and what the best way for handling this sort of input might be.

I presume that something like "1.0" should be taken as a double as well; that pretty much eliminates things like reading a double, then checking if it is actually an integer.

The only way is to parse the data, to see whether you encounter something that can be interpreted as an int or not. If you're going to use the conversion functions of the stream, this pretty much means scanning the input twice. The obvious solution would be to put the input into a string; these are much easier to scan multiple times. If you're not allowed to do that, you can use istream::tellg to memorize the position, scan ahead, and once you've decided, istream::seekg to go back to where you started from. But I don't know what rules your instructor has imposed.

If you can't seek, you can try hacking it by hand. First read an int , then peek at the next character. If it's a '.' , you can then read a double, which will give you the fractional part, which you can add to the integer you've already read. If it's an 'E' or and 'e' , it becomes a bit more difficult; you probably have to advance, read an int, and use pow manually. But this is far from perfect: if the double has the form "1.2E6" , you'll end up with 200000 as the "fractional" part; you'll need some means of detecting this, and scaling the integer you've alread read. And if the number is ".3" , you'll get an error when reading the integer: you can either check for this beforehand (but don't forget "-.3" ), or reset the error before doing anything else. And of course, it's possible that the integral part of a double won't fit into an int (or even a long long ).

All in all, it seems a bit artificial to me. In practice, you'd read into a string, and match regular expressions against it in order to determine how you wanted to interpret it.

It's probably easier to read in the whole line as a string first, check for a decimal point and then feed the line to a stringstream which can then either convert it to an int or double (depending on if the decimal point is available):

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>

using namespace std;

int main() {
  string line;
  int anInteger;
  double aDouble;

  getline( cin, line );
  stringstream ss( line );
  if ( line.find( '.' ) == string::npos ) {
    ss >> anInteger;
  } else {
    ss >> aDouble;
  }

  return 0;
}

Given your specification, I would read a std::string , see if that could be something else than an integer and depending on the outcome parse as int or as double . For example

int         integer;
double      number;
std::string value;
if (std::cin >> value) {
    if (value.find_first_of(".Ee")) {
        if (std::istringstream(value) >> number) {
            std::cout << "read double=" << number << '\n';
        }
        else {
            std::cout << "failed to read double from '" << value << "'\n";
        }
    }
    else {
        if (std::istringstream(value) >> integer) {
            std::cout << "read integer=" << integer << '\n';
        }
        else {
            std::cout << "failed to read integer from '" << value << "'\n";
        }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM