Monday, November 3, 2014

Digest for comp.lang.c++@googlegroups.com - 25 updates in 3 topics

comp.lang.c++@googlegroups.com Google Groups
Unsure why you received this message? You previously subscribed to digests from this group, but we haven't been sending them for a while. We fixed that, but if you don't want to get these messages, send an email to comp.lang.c+++unsubscribe@googlegroups.com.
Melzzzzz <mel@zzzzz.com>: Oct 31 10:54PM +0100

On Fri, 31 Oct 2014 22:43:23 +0100
> necessarily end after the number. I did not find format specifier
> that does the job.
 
> Marcel
 
#include <stdio.h>
 
int main()
{ long long i;
sscanf("0x80000000","%lli",&i);
printf("%llx\n", i);
return 0;
}
 
Problem is that 32 bit int is not long enough, just use long long
and all set...
 
--
Manjaro all the way!
http://manjaro.org/
Marcel Mueller <news.5.maazl@spamgourmet.org>: Oct 31 10:43PM +0100

I recently had a problem with a GPU assembler. The program is mainly
C++11, but the parsing of expression components is done with sscanf.
This causes problems because sscanf cannot read the integer constant
"0x80000000". %i returns 0x7fffffff and %u cannot read hex numbers. I
could bet that this has been working with %i for many years.
 
I just tested with gcc 4.8.2 for OS/2 - works with %i.
But with gcc 4.8.2 Linux (Mint 17) the result is the bitwise not.
 
#include <stdio.h>
int main()
{ int i;
sscanf("0x80000000", "%i", &i);
printf("%x", i);
return 0;
}
 
The goal is to read an unsigned number in all common formats (decimal,
binary, octal, hex) from a string. The string does not necessarily end
after the number. I did not find format specifier that does the job.
 
 
Marcel
Geoff <geoff@invalid.invalid>: Oct 31 03:48PM -0700

On Fri, 31 Oct 2014 17:34:14 -0500, Christopher Pisz
 
>or at least #include <cstdlib> which has been for quite a long time now...
 
To be equivalent to the C code it needs to be
 
std::cout << "0x" << std::hex << i << std::endl;
Christopher Pisz <nospam@notanaddress.com>: Oct 31 05:34PM -0500

On 10/31/2014 4:54 PM, Melzzzzz wrote:
> }
 
> Problem is that 32 bit int is not long enough, just use long long
> and all set...
 
or use C++ and drop the C style
 
#include <iostream>
 
int main()
{
long long i = 0x80000000;
std::cout << std::hex << i << std::endl;
 
return 0;
}
 
 
or if you will need the string later
 
 
#include <iostream>
#include <sstream>
 
int main()
{
long long i = 0x80000000;
std::ostringstream os;
 
os << std::hex << i;
std::cout << os.str() << std::endl;
 
return 0;
}
 
 
or at least #include <cstdlib> which has been for quite a long time now...
Geoff <geoff@invalid.invalid>: Oct 31 04:55PM -0700

On Fri, 31 Oct 2014 22:43:23 +0100, Marcel Mueller
>binary, octal, hex) from a string. The string does not necessarily end
>after the number. I did not find format specifier that does the job.
 
>Marcel
 
I like Christopher's solution, stay with C++ instead of C but this
would appear to be a bug in gcc 4.8.2. on that version of Linux. The
question is, is it a problem in sscanf or in printf? Breakpoint at the
printf line and examine the value of i in the debugger, is it
-2147483648 or 2147483647? If the former, you have a bug in printf
that is supposed to be taking an /unsigned/ i and outputting the hex
string. If the latter, then sscanf is interpreting 0x8000000 as -1.
Christopher Pisz <nospam@notanaddress.com>: Nov 03 01:17PM -0600

On 10/31/2014 11:38 PM, Ian Collins wrote:
 
> As it would be on a 64 bit system where the code was compiler for 64 bit.
 
>> strtoull() is your friend.
 
> It is.
 
It isn't my friend, because over and over I get to debug this problem
that a C-style programmer put into my code:
 
// Deprecated C headers
#include <stdio.h>
#include <stdlib.h>
 
// Standard Includes
#include <iostream>
 
 
int main()
{
std::string validzero("0");
std::string garbage("garbage");
 
std::cout << strtoul(validzero.c_str(), nullptr, 0) << std::endl;
std::cout << strtoul(garbage.c_str(), nullptr, 0) << std::endl;
 
// Done
return 0;
}
 
 
Such problems don't exist using sstream for conversion, because it has a
way to indicate failure that differs from a valid conversion.
scott@slp53.sl.home (Scott Lurndal): Nov 03 07:46PM

> std::string garbage("garbage");
 
> std::cout << strtoul(validzero.c_str(), nullptr, 0) << std::endl;
> std::cout << strtoul(garbage.c_str(), nullptr, 0) << std::endl;
 
The programmer is abusing strtoul in this case, of course. Probably
because some C++ ideologue has forced them to use the stupid output
stream crap.
 
A bad programmer can write bad code in any language.
Ian Collins <ian-news@hotmail.com>: Nov 04 09:17AM +1300

Christopher Pisz wrote:
 
> // Deprecated C headers
> #include <stdio.h>
> #include <stdlib.h>
 
Deprecated by whom?
 
> std::string validzero("0");
> std::string garbage("garbage");
 
> std::cout << strtoul(validzero.c_str(), nullptr, 0) << std::endl;
 
So you have been seeing bugs in C++ 11 code over and over?
 
> Such problems don't exist using sstream for conversion, because it has a
> way to indicate failure that differs from a valid conversion.
 
As does strtoull(), read the man page.
 
--
Ian Collins
Christopher Pisz <nospam@notanaddress.com>: Nov 03 02:19PM -0600

On 11/3/2014 1:46 PM, Scott Lurndal wrote:
> because some C++ ideologue has forced them to use the stupid output
> stream crap.
 
> A bad programmer can write bad code in any language.
 
Ok, show me an example in any form at all, C or otherwise, where we can
determine the difference between a valid value of zero and an error
please, for my own education is solving this bug that occurs countless
times.
 
I don't see how showing the result using cout has anything to do with
the problem.
 
use printf if you like, the result is the same.
Christopher Pisz <nospam@notanaddress.com>: Nov 03 02:24PM -0600

On 11/3/2014 2:17 PM, Ian Collins wrote:
> Christopher Pisz wrote:
>> On 10/31/2014 11:38 PM, Ian Collins wrote:
>>> Andrew Cooper wrote:
SNIP
>> #include <stdio.h>
>> #include <stdlib.h>
 
> Deprecated by whom?
 
by <cstdlib>
 
 
>> Such problems don't exist using sstream for conversion, because it has a
>> way to indicate failure that differs from a valid conversion.
 
> As does strtoull(), read the man page.
 
I don't have "man", because I am not on *nix.
I do have Google. Here is the same example using their reference, with
the same problem
 
// C headers
#include <stdio.h>
#include <stdlib.h>
 
// Standard Includes
#include <climits>
#include <iostream>
 
 
int main()
{
std::string zero("0");
std::string garbage("garbage");
 
unsigned long long validZeroConverted = strtoul(zero.c_str(),
nullptr, 0);
unsigned long long garbageConverted = strtoul(garbage.c_str(),
nullptr, 0);
 
if( validZeroConverted != ULONG_MAX )
{
std::cout << strtoul(zero.c_str(), nullptr, 0) << std::endl;
}
else
{
std::cout << "Could not convert zero" << std::endl;
}
 
if( garbageConverted != ULONG_MAX )
{
std::cout << strtoul(garbage.c_str(), nullptr, 0) << std::endl;
}
else
{
std::cout << "Could not convert garbage" << std::endl;
}
 
// Done
return 0;
}
 
 
Please show me Ian, how do we determine the difference between a valid
value of zero and an error Ian. Now for argument's sake, but because I
would simply like to know if it exists at all or if strtoxxx functions
simply cannot handle a value of zero.
 
The only way I can figure is to look at the string beforehand and
compare it to "0", which seems pretty darn silly.
Christopher Pisz <nospam@notanaddress.com>: Nov 03 02:27PM -0600

On 11/3/2014 2:24 PM, Christopher Pisz wrote:
> simply cannot handle a value of zero.
 
> The only way I can figure is to look at the string beforehand and
> compare it to "0", which seems pretty darn silly.
 
Peanut butter on my fingers.
 
Please show me Ian, how do we determine the difference between a valid
value of zero and an error. Not for argument's sake, but because I
would simply like to know if it exists at all. Can strtoxxx functions
simply cannot handle a value of zero?
 
The only way I can figure is to look at the string beforehand and
compare it to "0", which seems pretty darn silly.
Paavo Helde <myfirstname@osa.pri.ee>: Nov 03 02:37PM -0600

Christopher Pisz <nospam@notanaddress.com> wrote in
> simply cannot handle a value of zero.
 
> The only way I can figure is to look at the string beforehand and
> compare it to "0", which seems pretty darn silly.
 
Here you go:
 
#include <string>
#include <iostream>
#include <string.h>
 
unsigned long my_strtoul(const std::string& s) {
char* errPtr;
unsigned long result = strtoul(s.c_str(), &errPtr, 0);
if (*errPtr) {
throw std::runtime_error("not a numeric string: \"" + s + "\"");
} else {
return result;
}
}
 
int main()
{
std::string zero("0");
std::string garbage("garbage");
 
unsigned long long validZeroConverted = my_strtoul(zero);
 
try {
std::cout << my_strtoul(zero) << std::endl;;
} catch(const std::exception& e) {
std::cout << "Could not convert zero: " << e.what() <<
std::endl;
}
 
try {
std::cout << my_strtoul(garbage) << std::endl;;
} catch(const std::exception& e) {
std::cout << "Could not convert garbage: " << e.what() <<
std::endl;
}
 
// Done
return EXIT_SUCCESS;
}
 
 
 
Output:
 
0
Could not convert garbage: not a numeric string: "garbage"
Ben Bacarisse <ben.usenet@bsb.me.uk>: Nov 03 08:47PM

Christopher Pisz <nospam@notanaddress.com> writes:
<snip>
> value of zero and an error. Not for argument's sake, but because I
> would simply like to know if it exists at all. Can strtoxxx functions
> simply cannot handle a value of zero?
 
When no conversion can be done, the strto* functions set the pointer
pointed to by they second argument (it is is not null) to the value of
the first. Thus, after
 
char *end_ptr;
unsigned long u = strtoul(str, &endptr, 0);
 
if endptr == str you know that no conversion was done, and the return
(which will be zero), is meaningless. Testing for out-of-range errors
is a bit more fiddly since it uses errno, but it does not complicate
this situation since zero is never returned in these cases.
 
> The only way I can figure is to look at the string beforehand and
> compare it to "0", which seems pretty darn silly.
 
No need.
 
--
Ben.
Melzzzzz <mel@zzzzz.com>: Nov 03 09:57PM +0100

On Mon, 03 Nov 2014 14:24:33 -0600
 
> Please show me Ian, how do we determine the difference between a
> valid value of zero and an error Ian.
 
Check errno... and reset errno to 0 before call.
There is errno.h in your implementation? It's C standard
header?
 
 
 
--
Manjaro all the way!
http://manjaro.org/
Christopher Pisz <nospam@notanaddress.com>: Nov 03 03:03PM -0600

On 11/3/2014 2:47 PM, Ben Bacarisse wrote:
 
>> The only way I can figure is to look at the string beforehand and
>> compare it to "0", which seems pretty darn silly.
 
> No need.
 
So, this is confusion from bad documentation
 
Because, my crappy source says,
"
Parameters
str
C-string beginning with the representation of an integral number.
endptr
Reference to an object of type char*, whose value is set by the function
to the next character in str after the numerical value.
This parameter can also be a null pointer, in which case it is not used.
base
Numerical base (radix) that determines the valid characters and their
interpretation.
If this is 0, the base used is determined by the format in the sequence
(see strtol for details).
"
 
Which makes no mention of the second param being used to indicate an
error condition.
 
So, I went and got hold of a man page:
 
"If endptr is not NULL, strtol() stores the address of the first invalid
character in *endptr. If there were no digits at all, however,
strtol()
stores the original value of str in *endptr. (Thus, if *str is
not `\0'
but **endptr is `\0' on return, the entire string was valid.)"
 
 
I still fail to see why anyone wants to use this rather than a stream or
a lexical_cast. It's so C90.
 
Is the preference due to performance, plain hatred of streams, or
something else?
 
In my tests, the performance really wasn't that much different. Of
course, one could argue whether or not my performance test is written
properly for such an exercise. But I doubt its going to make more than a
microsecond of difference.
 
I am really not exaggerating when I speak of debugging the
aforementioned scenario over and over again. Bad programmers or not,
they don't seem to make such a mistake when told to use a stream or
lexical cast instead. We're gonna have to work with bad programmers in
most cases.
Paavo Helde <myfirstname@osa.pri.ee>: Nov 03 03:03PM -0600

Paavo Helde <myfirstname@osa.pri.ee> wrote in
> return result;
> }
> }
 
 
Sorry, a bit more reliable version is:
 
unsigned long my_strtoul(const std::string& s) {
errno = 0;
char* errPtr;
unsigned long result = strtoul(s.c_str(), &errPtr, 0);
if (*errPtr || errPtr==s.c_str() || errno!=0) {
throw std::runtime_error(
"not a numeric string: \"" + s +"\"");
} else {
return result;
}
}
scott@slp53.sl.home (Scott Lurndal): Nov 03 09:15PM

>determine the difference between a valid value of zero and an error
>please, for my own education is solving this bug that occurs countless
>times.
 
I posted such an example earlier in the thread. Here's a more
complicated use of strtoull.
 
a_memory_per_socket[msocket] = strtoull(arg, &cp, 0);
if ((*cp == 'G') || (*cp == 'g')) {
cp++;
a_memory_per_socket[msocket] <<= 30;
} else if ((*cp == 'M') || (*cp == 'm')) {
cp++;
a_memory_per_socket[msocket] <<= 20;
} else if ((*cp == 'K') || (*cp == 'k')) {
cp++;
a_memory_per_socket[msocket] <<= 10;
}
if (*cp == ',') {
arg = cp + 1;
msocket++;
if (msocket > a_socket_count) {
lp->log("There are only %u sockets available\n",
a_socket_count);
return false;
}
continue;
}
 
// Round down to modulo 64k
a_memory_per_socket[msocket] &= ~0xffffull;
 
if ((cp == arg)
|| (*cp != '\0')) {
lp->log("Invalid memory size '%s' on socket %zu\n", arg, msocket);
return false;
}
 
Authoritative documentation for strtoul (man page, if you like) is here:
 
http://pubs.opengroup.org/onlinepubs/009695399/functions/strtoul.html
Paavo Helde <myfirstname@osa.pri.ee>: Nov 03 03:18PM -0600

Christopher Pisz <nospam@notanaddress.com> wrote in news:m38qic$6ed$1
 
> So, this is confusion from bad documentation
 
I have found Linux man pages are often more easily readable than other
variants, and have grown a habit to google, e.g.: man strtoul linux
 
 
> I still fail to see why anyone wants to use this rather than a stream
or
> a lexical_cast. It's so C90.
 
> Is the preference due to performance, plain hatred of streams, or
> something else?
 
The former. Streams are invariably several times slower than other
options. For a simple string concatenation from pieces, appending to a
std::string with += operator is at least 2 times faster than using an
ostringstream.
 
Lexical_cast can be faster in principle (if not implemented via streams,
of course), and has the nice feature of throwing exceptions
automatically, which is not the case neither for C functions nor C++
streams. So in newer code and when the performance is not so important,
I'm using lexical_cast.
 
 
Cheers
Paavo
Ben Bacarisse <ben.usenet@bsb.me.uk>: Nov 03 09:19PM


> On 11/3/2014 1:46 PM, Scott Lurndal wrote:
<snip>
>> The programmer is abusing strtoul in this case, of course.
<snip>
> can determine the difference between a valid value of zero and an
> error please, for my own education is solving this bug that occurs
> countless times.
 
I posted an explanation, but here's a code fragment that tests very
various conditions:
 
char *endp;
errno = 0;
 
unsigned long u = strtoul(str, &endp, 0);
 
if (endp == str) {
// No conversion was done.
// This happens on inputs like "", " ", "garbage" and "+";
}
else if (errno == ERANGE) {
// The string represents and value that is out of range for
// unsigned long. u will be == ULONG_MAX. If using strtol, u
// would be either LONG_MAX or LONG_MIN so you can tell which
// side of zero the value was out of range.
}
else if (endp[strspn(endp, " \t")] != 0) {
// You can also test that what is left after the number is as
// expected though exactly what will vary from situation to
// situation. It may be OK for anything at all to follow the
// number, or it might be required that there be nothing at all
// (*endptr == 0). This example tests for anything other than
// trailing spaces and tabs.
}
else {
// All good. u really does represent a value that can be stored
// in an unsigned long. If u == ULONG_MAX or u == 0 that's
// because the input really did represent ULONG_MAX or zero.
}
 
There are still issues with these functions. For example, the unsigned
versions must accept signed numbers and convert them. That's not what
everyone wants, of course, but that's how they are specified.
 
<snip>
--
Ben.
Christopher Pisz <nospam@notanaddress.com>: Nov 03 03:22PM -0600

On 11/3/2014 3:18 PM, Paavo Helde wrote:
> I'm using lexical_cast.
 
> Cheers
> Paavo
 
Learn something new every day. Thanks guys.
Lynn McGuire <lmc@winsim.com>: Nov 03 02:33PM -0600

"Polymorphism and Overloading in C++"
http://www.codeproject.com/Articles/837146/Polymorphism-and-Overloading-in-Cplusplus
 
"A reader sent me an interesting question the other day. They asked if polymorphism and overloading were essentially the same thing."
 
"My initial reaction was Huh?"
 
Nice article.
 
Lynn
Christopher Pisz <nospam@notanaddress.com>: Nov 03 02:35PM -0600

On 11/3/2014 2:33 PM, Lynn McGuire wrote:
 
> "My initial reaction was Huh?"
 
> Nice article.
 
> Lynn
 
 
The way I see it, overloading is one facet of polymorphism, while
inheritance is the other. Depends which interviewer you talk to, some
have one in mind or the other or both. Best to go into both usually.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 03 05:32PM

On 03/11/2014 11:25, Rick C. Hodgin wrote:
>> much time.
 
> Am writing RDC specs draft presently. Lord
> willing, I will publish for review this week.
 
He was being sarcastic, couldn't you tell?
 
/Flibble
"Rick C. Hodgin" <rick.c.hodgin@gmail.com>: Nov 03 10:12AM -0800

On Monday, November 3, 2014 12:32:16 PM UTC-5, Mr Flibble wrote:
> > willing, I will publish for review this week.
 
> He was being sarcastic, couldn't you tell?
 
> /Flibble
 
Of course. His sarcasm didn't alter my answer though.
 
Best regards,
Rick C. Hodgin
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 03 06:57PM

On 03/11/2014 18:12, Rick C. Hodgin wrote:
 
>> He was being sarcastic, couldn't you tell?
 
>> /Flibble
 
> Of course. His sarcasm didn't alter my answer though.
 
That is because you are not taking your medication.
 
/Flibble
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: