3

Is it possible to disable implicit casting in C/C++.

Suppose I want to write a validity function that makes me enter only integers in range [1,10]

I have written:

#include <iostream>


using namespace std;

int main( )
{
    int var=0;
    cout << "Enter a number (Integer between 1 to 10) : ";

    while( (!(cin >> var )) || (var > 10 ) || (var < 1) )
    {
        cout << "U nuts .. It can only be [1,10]\n";
        cin.clear();
        cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
        cout << "Enter a number (Integer between 1 to 10) : ";
        }

    cout << "\nYou entered : " << var;

   return 0;
}

But if the user enters 9.5 it accepts it by converting the float 9.5 as 9 and storing it in var. I want any float entry to be treated as invalid entry. How do I achieve this most compactly.

I do not want to do something of this sort:

#include <iostream>
#include <cmath>


using namespace std;

int main( )
{
    float var=0;
    cout << "Enter a number (Integer between 1 to 10) : ";

    while( (!(cin >> var )) ||(var < 1)|| (var > 10 ) || !(ceilf(var) == var) )
    {
        cout << "U nuts .. It can only be [1,10]\n";
        cin.clear();
        cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
        cout << "Enter a number (Integer between 1 to 10) : ";
        }

    cout << "\nYou entered : " << var;

   return 0;
}

This serves my purpose . But what I want to know, that is there any way where a conversion from float to int - I can suppress or it can show it as false input.

Similar to the way cin >> var where var type is int - if we enter char it returns false condition. Can we achieve the same for float entry ?

Thanks

Gaurav K
  • 2,864
  • 9
  • 39
  • 68
  • `while( (!(cin >> var )` what do you think this is doing? checking if var is 0 or not or if cin is null or not?. this will always evaluate to false. – Koushik Shetty Apr 29 '13 at 11:00
  • @Koushik - if u enter 'char' then 'cin >> var' returns false as var is of type - int. – Gaurav K Apr 29 '13 at 11:02
  • 2
    Read a string and do your own conversion. – Joop Eggen Apr 29 '13 at 11:03
  • Gaurav See [this](http://stackoverflow.com/questions/7903083/how-do-i-prevent-an-implicit-cast-double-int), it talks about preventing `double` to `int` implicit conversion – Suvarna Pattayil Apr 29 '13 at 11:03
  • For checking floating point number entries.. this may get handy.. http://cboard.cprogramming.com/c-programming/71064-checking-floating-point-number.html – Hiren Pandya Apr 29 '13 at 11:05
  • cin >> var' returns false? how is that? `>>` is overloaded for istream and it return `istream&`. if you enter char its converted to int(implicitly and stored in var). – Koushik Shetty Apr 29 '13 at 11:05
  • 1
    @Koushik dude .. check this out .. u got confusion with I/O Stream Class ... http://www.parashift.com/c++-faq-lite/istream-and-ignore.html – Gaurav K Apr 29 '13 at 11:07
  • @Koushik He means if you enter the string "char", not a `char` value. Then yes, the fail bit will be set and the stream, when converted to `bool`, will be `false`. – Joseph Mansfield Apr 29 '13 at 11:11
  • @sftrabbit, He is confused as to how the implicit conversion of `istream&` to `boolean` takes place. In his estimation, the ASCII value of `char` will be stored – Suvarna Pattayil Apr 29 '13 at 11:16
  • 1
    @sftrabbit if you enter any character - suppose I enter `'j'` or `'hello'` - then for expression `'cin >> var'` fail bit will be set for returned `istream&` - and it evalutes to `false` as `var` type is `int` – Gaurav K Apr 29 '13 at 11:16
  • 1
    @Koushik Check [this](http://stackoverflow.com/questions/6791520/if-cin-x-as-a-condition) too – Suvarna Pattayil Apr 29 '13 at 11:19
  • @SuvP is there a conversion operator (operator bool()?)defined for istream? – Koushik Shetty Apr 29 '13 at 11:21
  • @SuvP the conversion is not implicit but through conversion operator. and yes i was really confused about accepting char. i thought since char is integral type it will be promoted to int and stored. but wow learnt. Gaurav thanks and sorry. – Koushik Shetty Apr 29 '13 at 11:27
  • @Koushik in C++11 yes there is an `operator bool()`, in C++98 there is an `operator void*` that is compared to `null` in a boolean expression. – zakinster Apr 29 '13 at 11:29
  • @zakinster how is the call resolved to void * coversion operator in pre c++11 era? – Koushik Shetty Apr 29 '13 at 11:31
  • @Koushik Because it's the only implicit conversion that would make the object type valid in this context. See this : http://stackoverflow.com/questions/6277678/stream-output-and-implicit-void-cast-operator-function-invocation – zakinster Apr 29 '13 at 11:34
  • @zakinster ah now its not required:-) – Koushik Shetty Apr 29 '13 at 11:34
  • @Koushik. Yeps. I was searchin for a nice link . But I guess its all cleared now :) – Suvarna Pattayil Apr 29 '13 at 11:39
  • @SuvP i never realised istream having conversion operator thats why the whole mess. better late than never. thanks a lot:-) . – Koushik Shetty Apr 29 '13 at 11:43
  • 2
    Note that there is no such thing as "implicit casting". A **cast** is something you write in your code to tell the compiler to do a **conversion**. An **implicit conversion** is a conversion that the compiler does without a cast; an **explicit conversion** is one that the compiler does because of a cast. – Pete Becker Apr 29 '13 at 12:22

2 Answers2

6

But if the user enters 9.5 it accepts it by converting the float 9.5 as 9 and storing it in var.

No it doesn't. If the the user enters 9.5, then cin >> var stops reading when it hits the . (and leaves it on the stream). There's no float-to-int conversion because you haven't read a float, just an int.

The fix is to read the rest of the input (after cin >> var), and make sure there's nothing bad left over after the end of the int.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • What is the best way to check the residual characters in cin stream ? Is there any function available to check residual? Also `cin` always confuses me - suppose it is taking an string entry.. when we hit `enter` does it remain in the stream or extracted and saved in string var `str` for expressions such as `cin >> str` – Gaurav K Apr 29 '13 at 11:52
  • @GauravK could try [cin.ignore](http://en.cppreference.com/w/cpp/io/basic_istream/ignore) after you read to var. – Koushik Shetty Apr 29 '13 at 11:58
  • added to previous comment : What I mean to ask - `string str; cin >> str` now I enter `hello` followed by hitting `enter` - does this `enter` remain in the stream or it is also saved to `str` along with `hello` – Gaurav K Apr 29 '13 at 11:59
  • @Koushik ignore will discard residuals , I wana check if any residual is there or not ? as explained in the answer - when we enter `9.5` , `.5` will remain in the cin stream - is there any method to check residual in istream class object? – Gaurav K Apr 29 '13 at 12:02
  • @GauravK: the best way is `string str; readline(cin, str);`. In the case where the user enters `9` that will read an empty string, whereas `cin >> str` would read the next line. – Steve Jessop Apr 29 '13 at 12:57
  • @SteveJessop can you please give an example ? – Gaurav K Apr 29 '13 at 13:04
  • @Gaurav `9.5` would be left in the buffer. – Suvarna Pattayil Apr 29 '13 at 13:55
1

If you want to validate all of the input, you will have to get the whole line first.

Try:

string line;
getline(cin, line); // gets whole line
char *endptr;
long int var = strtol(line.c_str(), &endptr, 10); // converts string to int

// now check that endptr points to end of the string
if (endptr<line.c_str()+line.length()) {
  // extra characters found after the integer
}
ronalchn
  • 12,225
  • 10
  • 51
  • 61
  • This depends on the desired behaviour, and I am not in a position to determine that. The OP will be most qualified in determining the tweaks necessary, and it is not difficult to achieve this, so I will not add this behaviour to the answer. – ronalchn Apr 29 '13 at 11:18