C++: Help with cin difference between Linux and Windows


C++: Help with cin difference between Linux and Windows



I have a Win32 console program that I wrote and it works fine. The program takes input from the user and performs some calculations and displays the output - standard stuff. For fun, I am trying to get the program to work on my Fedora box but I am running into an issue with clearing cin when the user inputs something that does not match my variable type. Here is the code in question:

void CParameter::setPrincipal() { double principal = 0.0;  cout << endl << "Please enter the loan principal: "; cin >> principal;  while(principal <= 0) {     if (cin.fail())     {           cin.clear();           cin.ignore(INT_MAX, '\n');     }     else     {         cout << endl << "Plese enter a number greater than zero. Please try again." << endl;         cin >> principal;     } }  m_Parameter = principal; 

}

This code works in Windows. For example, if the user tries to enter a char data type (versus double) then the program informs the user of the error, resets cin, and allows the user another opportunity to enter a valid value.

When I move this code to Fedora, it compiles fine. When I run the program and enter an invalid data type, the while loop never breaks to allow the user to change the input.

My questions are; how do I clear cin when invalid data is inputted in the Fedora environment? Also, how should I write this code so it will work in both environments (Windows & Linux)?

Thanks in advance for your help!




What can I do with Seed?

1:



How to force inclusion of an object file in a static library when linking into executable?
I think it's a bad idea to use formatted input to read user responses.


Fast method call scheduling in Python
I'd use getline - something like this:.
Spawning and waiting for child processes in Python
#include <iostream> #include <string> #include <sstream> using namespace std;  template <typename T> bool Read( T & t, istream & is ) {     string s;     if ( ! getline( is, s ) ) {         return false;     }     else {         istringstream ss( s );         return ss >> t;     } }      int main() {     while(1) {         double d;         if ( ! Read( d, cin ) ) {             cout << "invalid\n";         }         else {             cout << "You entered " << d << "\n";         }     } } 
which works on Windows - I don't have my Linux box switched on at the moment..
linux pthread_suspend


How many files in a directory is too many (on Windows and Linux)? [duplicate]


How to check if a process is running or got segfaulted or terminated in linux from its pid in my main() in c++

2:



how to assign value to EIP with C language in ubuntu
I think that cin.ignore sets the failed flag on cin, which makes it stay in the upmost if statement for ever.

INT_MAX is a very large number - are you sure it is allowed to cin.ignore on all platforms?.


3:


I'd switch to using a getline to read the input and then parse with a stringstream:.
double principal = 0; string temp; while (principal <= 0) {     getline(cin, temp);     istringstream converter(temp);     if (!(converter>>principal) ||         !(converter>>std::ws).eof() ||         principal <= 0)     {         cout << "Try again" << endl;         principal = 0;     } } 


4:


I agree with Anders Abel and Johannes Schaub; I think also that it may not be guaranteed that, in case of error, principal is left untouched, so you may consider adding principal=0.0; at the beginning of the cycle.. By the way, to perform that kind of work I usually use this template function:.
template<typename InType> void AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString, InType & Result) {     do     {         Os<<Prompt.c_str();         if(Is.fail())         {             Is.clear();             Is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');         }         Is>>Result;         if(Is.fail())             Os<<FailString.c_str();     } while(Is.fail()); }  template<typename InType> InType AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString) {     InType temp;     AcquireInput(Os,Is,Prompt,FailString,temp);     return temp; } 
The first overload may be preferred if you want to avoid copying, the second may be more convenient for builtin types.

Usage examples:.
//1st overload double aDouble; AcquireInput(cout,cin,"Please insert an integer: ","Invalid value.\n",aDouble);  //2nd overload (more convenient, in this case and in general with POD) double aDouble=AcquireInput(cout,cin, "Please insert an integer: ","Invalid value.\n"); 
In your case you may change your code in this way:.
double principal=0.0; const char * errMsg="Plese enter a number greater than zero. 

Please try again.\n"; while(principal<=0.0) { principal=0.0; principal=AcquireInput(cout,cin,"Please enter the loan principal: ",errMsg); if(principal<=0.0) cout<<errMsg; }



98 out of 100 based on 68 user ratings 518 reviews