Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

MS VS bug, or other compilers have bug?

62 views
Skip to first unread message

Bob Langelaan

unread,
Mar 9, 2018, 12:52:04 PM3/9/18
to
If you have code such as:

int var;
cin >> var;

and the user inputs:

12345i

afterward, with MS VS, var will contain 12345 and the character 'i' remains in the cin buffer. No error flags will be raised for the cin object.

With some other compilers, including Xcode and Clion , var will contain the value 0 after the operation and the 'i' will have been swallowed up in the operation as well. In other words, the 'i' will no longer be in the cin buffer. Not sure about the error state of the cin object after the operation.

Does the C++ language specify what the result should be? Could both results be "correct"?

Any input would be appreciated.

Mr Flibble

unread,
Mar 9, 2018, 1:36:39 PM3/9/18
to
The fact that only you and three others use Xcode and Clion and everyone
else uses g++, clang or VC++ should answer your question.

/Flibble

--
"Suppose it’s all true, and you walk up to the pearly gates, and are
confronted by God," Bryne asked on his show The Meaning of Life. "What
will Stephen Fry say to him, her, or it?"
"I’d say, bone cancer in children? What’s that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery
that is not our fault. It’s not right, it’s utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates
a world that is so full of injustice and pain. That’s what I would say."

Bob Langelaan

unread,
Mar 9, 2018, 2:24:40 PM3/9/18
to

Bob Langelaan

unread,
Mar 9, 2018, 2:32:56 PM3/9/18
to
I am having trouble with the interface I am using to this use group. So while I meant to reply to Mr. Flibble, I can't seem to be able to do so.

Mr. Flibble - if I understand you correctly, you are saying that the VC++ result is the correct result? I think you may have misunderstood me, since I actually use VC++. It is 2 of my students that are using Xcode and Clion. I did not want to tell they that their compiler is crap without some ammunition. It seems that you have just given me that ammunition :)

Jorgen Grahn

unread,
Mar 9, 2018, 3:05:27 PM3/9/18
to
On Fri, 2018-03-09, Bob Langelaan wrote:
> On Friday, March 9, 2018 at 10:36:39 AM UTC-8, Mr Flibble wrote:
>> On 09/03/2018 17:51, Bob Langelaan wrote:
>> > If you have code such as:
>> >
>> > int var;
>> > cin >> var;
>> >
>> > and the user inputs:
>> >
>> > 12345i
>> >
>> > afterward, with MS VS, var will contain 12345 and the character
>> > 'i' remains in the cin buffer. No error flags will be raised for
>> > the cin object.
>> >
>> > With some other compilers, including Xcode and Clion , var will
>> > contain the value 0 after the operation and the 'i' will have
>> > been swallowed up in the operation as well. In other words, the
>> > 'i' will no longer be in the cin buffer. Not sure about the
>> > error state of the cin object after the operation.
>> >
>> > Does the C++ language specify what the result should be? Could
>> > both results be "correct"?
>> >
>> > Any input would be appreciated.
>>
>> The fact that only you and three others use Xcode and Clion and everyone
>> else uses g++, clang or VC++ should answer your question.

Something is wrong here: Clion is not a compiler; it's an IDE. I've
seen it used on Linux with gcc and clang as backends. IIRC the same
goes for Xcode.

It's probably better to first establich which behavior is correct C++.
(I won't try, since I'm disinterested in parsing text using
std::istream.)

One piece of advice though, which I've mentioned here in the past: if
this is for a student exercise and std::istream reading is not the
main point, reformulate it so it's driven as a unit test instead of as
a main() which prompts for user input. Use Google Test, or something.
Much easier to handle for you and the students, and they can focus on
their main task.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

James Kuyper

unread,
Mar 9, 2018, 3:06:59 PM3/9/18
to
Yes, though figuring out what the specification means gets complicated.

The starting point is 27.7.2.2.2p3, which describes the Arithmetic
extractors for std::basic_istream<>::operator>>(int& val). It describes
their behavior in terms of use_facet< numget >(loc).get(*this, 0, *this,
err, lval), where lval has the type 'long'.

22.2 specifies that std::use_facet<Facet>() returns a Facet&

22.4.2.1.1 specifies that std::num_get::get(in, end, str, err, val)
calls do_get(in, end, str, err, val), which is a virtual function.

22.4.2.1.2 specifies that std::num_get::do_get(in, end, str, err, val)
reads in characters from the string, converting the locale-specific
decimal_point character to '.', discarding characters prior to the
decimal point which match the locale-specific thousands_sep(), and
converting any other characters that cannot be found in the string
"0123456789abcdefxABCDEFX+-" to null characters, and stopping as soon as
a character is found which is not allowed by the conversion specifier.
Note that 'i' is not allowed by any of the conversion specifiers, so it
is permitted only when using a locale which specifies 'i' as the
thousands separator :-).

do_get() then passes the character string to the C standard library
function strtoll(). At this point, you have to switch standards to get a
complete description of the process, but you don't need that much detail
for this question. For this input, strtoll() should set lval to 12345.

Coming back to the C++ standard, 27.7.2.2.2p3 specifies that operator>>
sets val to the value stored in lval.

Richard

unread,
Mar 9, 2018, 3:35:14 PM3/9/18
to
[Please do not mail me a copy of your followup]

Bob Langelaan <bobl...@gmail.com> spake the secret code
<208ad61c-3db6-442e...@googlegroups.com> thusly:

>[...] if I understand you correctly, you are saying that the
>VC++ result is the correct result?

Yes.

>I think you may have misunderstood
>me, since I actually use VC++. It is 2 of my students that are using
>Xcode and Clion. I did not want to tell they that their compiler is
>crap without some ammunition. It seems that you have just given me that
>ammunition :)

It's not their compiler that's at fault; it is their standard library
that is at fault.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Richard

unread,
Mar 9, 2018, 3:37:34 PM3/9/18
to
[Please do not mail me a copy of your followup]

Jorgen Grahn <grahn...@snipabacken.se> spake the secret code
<slrnpa5q7t.e...@frailea.sa.invalid> thusly:

>On Fri, 2018-03-09, Bob Langelaan wrote:

>Something is wrong here: Clion is not a compiler; it's an IDE. I've
>seen it used on Linux with gcc and clang as backends. IIRC the same
>goes for Xcode.

Correct.

Which compiler you're using under the hood depends on what's installed
on your system. Typically, installing Xcode also installs the
compiler and the IDE version is matched to a particular compiler
version that it installed. However, the IDE/project can be configured
to use a particular compiler.

>It's probably better to first establich which behavior is correct C++.
>(I won't try, since I'm disinterested in parsing text using
>std::istream.)

The MSVC implementation is reporting the correct behavior. Extracting
an integer from a stream stops at the first non-digit character in the
stream and returns the integer and leaves the non-digit character
alone for you to consume in a subsequent extraction operation.

Real Troll

unread,
Mar 9, 2018, 4:13:33 PM3/9/18
to
On 09/03/2018 17:51, Bob Langelaan wrote:
> With some other compilers, including Xcode and Clion , var will contain the value 0 after the operation and the 'i' will have been swallowed up in the operation as well. In other words, the 'i' will no longer be in the cin buffer. Not sure about the error state of the cin object after the operation.
>
How did you prove that " 'i' will have been swallowed up in the
operation as well. In other words, the 'i' will no longer be in the cin
buffer. "?

I tried this in Visual Studio 2017 and Embarcadero Tokyo and both give
me correct result, i.e they give me 12345. However, please tell me how
did you know that i is still in the buffer?

Thank you.


Bob Langelaan

unread,
Mar 9, 2018, 5:32:27 PM3/9/18
to
On Friday, March 9, 2018 at 9:52:04 AM UTC-8, Bob Langelaan wrote:
Question was how did I know 'i' was still in the buffer? Because the following code returned a boolean true result:

if (cin.peek() == 'i')
{
cin.get(); // swallow 'i'

...

In the code above we want to confirm that 'i' is the next character in the buffer before inputting it, but don't actually want the 'i' itself.

I hope that answers your question to your satisfaction.

Real Troll

unread,
Mar 9, 2018, 5:49:04 PM3/9/18
to
Thanks for posting back. I did a simple run like this:

#include <iostream>

using namespace std;
int main ()
{
int var;
cout << "Please enter an integer: ";
cin >> var;

cout << "You entered: " << var;

return 0;
}



It returns 12345 but I don't think it proves that i is still in the
buffer. But I take your word for it.

If you enter a number like: abc456
then you get 0

So clearly the cin parses the string and if it can't find an integer, it
returns nothing.

Mr Flibble

unread,
Mar 9, 2018, 6:17:57 PM3/9/18
to
For fuck's sake this isn't rocket science.

int var;
char ch;
cin >> var;
cin >> ch;
cout << var << "," << ch << endl;

Bob Langelaan

unread,
Mar 9, 2018, 6:21:19 PM3/9/18
to
For fuck's sake this isn't rocket science.

int var;
char ch;
cin >> var;
cin >> ch;
cout << var << "," << ch << endl;

LOL !!! I agree :)

Bob Langelaan

unread,
Mar 9, 2018, 6:28:32 PM3/9/18
to
I had already created before Mr. F's post the following program for my students to build and execute to see if their compiler/libraries meet the necessary requirement:

#include <iostream>
using namespace std;

int main()
{
int i;
char c;
cout << "Enter the string: \"12345i x\" without quotes and the only space being between the 'i' and the 'x': ";
cin >> i >> c;
cout << '\n' << i << '\n' << c << '\n' << endl;
cout << "\nThe output above should be 12345 and i on 2 separate lines of output.\n" << endl;
}

Real Troll

unread,
Mar 9, 2018, 8:33:38 PM3/9/18
to
For fuck's sake your original post was just this:

> int var;
> cin >> var;

This doesn't put "i" in the buffer unless you also include:

char ch;
cin << ch.

It's rocket science here.

In future make a point of including all the relevant information.




Öö Tiib

unread,
Mar 10, 2018, 5:38:30 AM3/10/18
to

James R. Kuyper

unread,
Mar 14, 2018, 10:03:12 AM3/14/18
to
I was a bit tired when I wrote that post, and made a number of mistakes
which I'm now correcting:

On 03/09/2018 03:06 PM, James Kuyper wrote:
> On 03/09/2018 12:51 PM, Bob Langelaan wrote:
>> If you have code such as:
>>
>> int var;
>> cin >> var;
>>
>> and the user inputs:
>>
>> 12345i
>>
>> afterward, with MS VS, var will contain 12345 and the character 'i' remains in the cin buffer. No error flags will be raised for the cin object.
>>
>> With some other compilers, including Xcode and Clion , var will contain the value 0 after the operation and the 'i' will have been swallowed up in the operation as well. In other words, the 'i' will no longer be in the cin buffer. Not sure about the error state of the cin object after the operation.
>>
>> Does the C++ language specify what the result should be? Could both results be "correct"?
>
> Yes, though figuring out what the specification means gets complicated.

I just realized that you asked two questions, and my "Yes" applied only
to the first one. The answer to the second question is implied by the
rest of my response - it's "No".

...
The following citations from section 22 are actually from section 25:

> 22.2 specifies that std::use_facet<Facet>() returns a Facet&
>
> 22.4.2.1.1 specifies that std::num_get::get(in, end, str, err, val)
> calls do_get(in, end, str, err, val), which is a virtual function.
>
> 22.4.2.1.2 specifies that std::num_get::do_get(in, end, str, err, val)
> reads in characters from the string, converting the locale-specific
> decimal_point character to '.', discarding characters prior to the
> decimal point which match the locale-specific thousands_sep(), and
> converting any other characters that cannot be found in the string
> "0123456789abcdefxABCDEFX+-" to null characters, and stopping as soon as
> a character is found which is not allowed by the conversion specifier.
> Note that 'i' is not allowed by any of the conversion specifiers, so it
> is permitted only when using a locale which specifies 'i' as the
> thousands separator :-).

At this point, you might be asking "what conversion specifier?", since I
dropped the paragraph explaining that point. 22.4.2.1.2p3 describes the
behavior in terms of the following example code:

fmtflags flags = str.flags();
fmtflags basefield = (flags & ios_base::basefield);
fmtflags uppercase = (flags & ios_base::uppercase);

Tables 73 specifies the corresponding <cstdio> scanf() conversion
specifier: if basefield is oct, hex, or 0, then the specifier is "%o",
"%X", or "%i" respectively. The only other valid value for basefield is
dec, in which case the fact that var is signed means that the specifier
is "%d". do_get() is not actually defined as calling scanf(). Instead:

> do_get() then passes the character string to the C standard library
> function strtoll(). At this point, you have to switch standards to get a
> complete description of the process, but you don't need that much detail
> for this question. For this input, strtoll() should set lval to 12345.

scanf() and num_get::do_get() are both described as calling strtoll() -
the conversion specifiers determine which base scanf() passes to
strtoll(): 8, 16, 0, and 10 for the specifiers mentioned above, in that
order. The implication of table 73 is that do_get() must do the same.
0 new messages