C ++: help with the difference between Linux and Windows

I have a Win32 console program that I wrote, and it works fine. The program receives data from the user and performs some calculations and displays the output - standard material. For fun, I'm trying to get the program to work in my Fedora block, but I have a problem clearing cin when the user enters something that doesn't 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 on Windows. For example, if the user tries to enter the char data type (as opposed to double), then the program informs the user about the error, resets cin and allows the user to enter the actual value again.

When I port this code to Fedora, it compiles fine. When I run the program and enter an invalid data type, the while loop is never interrupted so that the user can change the input.

My questions; How to clear cin when invalid data is entered into Fedora environment? Also, how do I write this code so that it works in both environments (Windows and Linux)?

Thanks in advance for your help!

+4
source share
4 answers

I think it's a bad idea to use formatted input to read user responses. I would use getline - something like this:

 #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 - at the moment I have not included my Linux block.

+1
source

I think cin.ignore sets a flag with an error on cin , which makes it stay in the top if statement forever. INT_MAX is a very large number - are you sure cin.ignore is allowed on all platforms?

+2
source

I would switch to using getline to read the input and then stringstream with 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; } } 
+1
source

I agree with Anders Abel and Johannes Schaub; I also think that it cannot be guaranteed that in case of an error the main one will remain untouched, so you can consider adding principal=0.0; at the beginning of the cycle.

By the way, to do this 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 preferable if you want to avoid copying, the second may be more convenient for built-in types. Examples of using:

 //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 can change your code as follows:

 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; } 
0
source

Source: https://habr.com/ru/post/1308599/


All Articles