Friday, November 10, 2017

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

Lynn McGuire <lynnmcguire5@gmail.com>: Nov 09 08:10PM -0600

On 11/9/2017 8:07 PM, Lynn McGuire wrote:
> number ?  atof and strtod do not work with the comma.
 
> Thanks,
> Lynn
 
A string such as 4,800.1 or 3,334.5e9.
 
Thanks,
Lynn
Lew Pitcher <lew.pitcher@digitalfreehold.ca>: Nov 09 10:17PM -0500

Stefan Ram wrote:
 
 
> #include <iostream>
> #include <ostream>
> #include <string>
 
Thanks for the C++ example. but, do you have anything in C?
--
Lew Pitcher
"In Skills, We Trust"
PGP public key available upon request
Alain Ketterlin <alain@universite-de-strasbourg.fr.invalid>: Nov 10 12:38PM +0100


>> Thanks,
>> Lynn
 
> A string such as 4,800.1 or 3,334.5e9.
 
Any of atof, strtod, sscanf will happily convert this, *provided* the
locale is setup correctly. Check setlocale (std::setlocale), especially
the LC_NUMERIC category.
 
See also
https://stackoverflow.com/questions/28470656/convert-string-with-thousands-and-decimal-separator-into-double
 
-- Alain.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 10 02:06PM

On 10/11/2017 02:52, Stefan Ram wrote:
> { ::std::string s { source };
> s.replace( 1, 1, ""s );
> return s; }
 
Your use of the namespace scoping operator is egregious; ::std is
totally unnecessary. Your solution is also non-optimal as it
unnecessarily passes by reference:
 
std::string replace(std::string source, const std::string& a, const
std::string& b)
{
source.replace(...);
return source;
}
 
/Flibble
scott@slp53.sl.home (Scott Lurndal): Nov 10 02:16PM


> IIRC, An implementation of C is not required to support
> other locales than the "C" locale, so any code based on
> any other locale would not be portable.
 
That would seem to be a total non-sequitor.
 
Every POSIX implementation supports it. If windows doesn't,
then switch to posix.
"James R. Kuyper" <jameskuyper@verizon.net>: Nov 10 09:31AM -0500

On 2017-11-10 06:38, Alain Ketterlin wrote:
 
> Any of atof, strtod, sscanf will happily convert this, *provided* the
> locale is setup correctly. Check setlocale (std::setlocale), especially
> the LC_NUMERIC category.
 
The C standard provides an official definition of the "decimal-point
character", explicitly identifying it as locale-specific, and frequently
uses that term when describing the behavior of the functions which
convert between floating point numbers and their representations as
strings. In particular, strtod() recognizes
 
"a nonempty sequence of decimal digits optionally containing a
decimal-point characters, then an optional exponent..." (7.22.1.3p3).
 
However, none of the other members of struct lconv are mentioned
anywhere in the standard other than the part describing <locale.h>. For
none of those members is there any function in the C standard library
whose defined behavior requires it to pay attention to the value of that
member in the current locale. The decimal-point character is the only
member of that struct for which there's a corresponding item listed in
section J.4, which summarizes locale-specific behavior. It is apparently
up to the user to write code whose behavior depends upon those values.
 
Note, in particular, that the description of strtod() above makes no
mention of the thousands_sep or grouping members of struct lconv. The
behavior of atof() and sscanf() are both defined in terms of calls to
strtod(), so the same is true of them.
 
> See also
> https://stackoverflow.com/questions/28470656/convert-string-with-thousands-and-decimal-separator-into-double
 
C++ differs from C in that there are C++ standard library routines that
do have behavior that depend upon values of thousands_sep and grouping
in the currently imbued locale, and that link shows how to take
advantage of that fact. Note, in particular, that even in C++,
std::strtod(), std::atof(), and std::sscanf() are NOT examples of this.
Their behavior is the same as the C standard library versions of those
routines in this regard.
legalize+jeeves@mail.xmission.com (Richard): Nov 10 05:54PM

[Please do not mail me a copy of your followup]
 
Lew Pitcher <lew.pitcher@digitalfreehold.ca> spake the secret code
>> #include <ostream>
>> #include <string>
 
>Thanks for the C++ example. but, do you have anything in C?
 
If you want a C example, why are you asking in a C++ newsgroup?
 
Followups redirected back to comp.lang.c++
--
"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>
"James R. Kuyper" <jameskuyper@verizon.net>: Nov 10 01:14PM -0500

On 2017-11-10 12:54, Richard wrote:
> [Please do not mail me a copy of your followup]
 
> Lew Pitcher <lew.pitcher@digitalfreehold.ca> spake the secret code
> <ou35oo$2tf$1@dont-email.me> thusly:
...
>> Thanks for the C++ example. but, do you have anything in C?
 
> If you want a C example, why are you asking in a C++ newsgroup?
 
Because the OP (Lynn McGuire) posted to both newsgroups, presumably
because Lynn was looking for both a C and a C++ solution (possibly
hoping that a single solution might exist that will work in both languages).
 
> Followups redirected back to comp.lang.c++
 
Followups restored as originally specified.
jacobnavia <jacob@jacob.remcomp.fr>: Nov 10 09:22PM +0100

Le 10/11/2017 à 03:10, Lynn McGuire a écrit :
 
> A string such as 4,800.1 or 3,334.5e9.
 
> Thanks,
> Lynn
 
void EliminateComma(char *src)
{
char *dst = src;
while (*src) {
if (*src != ',')
*dst++ = *src;
src++;
}
*dst=0;
}
Ben Bacarisse <ben.usenet@bsb.me.uk>: Nov 10 08:44PM

I'm just picking a pace to comment really...
 
> }
> *dst=0;
> }
 
Removing commas, either in place or in a copy, is probably how I'd do
this too, but it's also possible that it is not at all what is needed.
For example, the input might include other commas that have to be
preserved, or the removal of all commas allows input to be parsed which
should be treated as an error. Without knowing more about the overall
requirement it's hard to give good advice.
 
--
Ben.
Keith Thompson <kst-u@mib.org>: Nov 10 01:14PM -0800

> }
> *dst=0;
> }
 
This might be a good first step *if* you don't mind modifying the
original string in place.
 
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
jacobnavia <jacob@jacob.remcomp.fr>: Nov 10 10:22PM +0100

Le 10/11/2017 à 22:14, Keith Thompson a écrit :
> This might be a good first step*if* you don't mind modifying the
> original string in place.
 
If you do mind, make a copy before... not rocket sicence isn't it?
Paavo Helde <myfirstname@osa.pri.ee>: Nov 10 01:27AM +0200

On 9.11.2017 22:23, JiiPee wrote:
> Thanks, but just thinking another thing: is is a good idea at all using
> enums as (option) flags? I read some say online that should use
> constants instead.
 
In my experience, enums are much better than static constant integer
data members in a class. The latter sometimes require a separate
definition outside of the class, which is a hassle. And "sometimes"
means depending on the usage of the constant, the compiler, the compiler
version and the compiler optimization flags, making this approach pretty
fragile.
 
Actually it is very easy to define an enum with bit flag values:
 
enum flags: std::uint8 {
A = (1<<0),
B = (1<<1),
C = (1<<2),
// ...
};
 
Also, the bitflags are typically combined, and with the enum approach
the result is still legally representable in the same enum type, making
this more encapsulated (especially with 'enum class'). With separate
integer constants there is no separate type and the compiler does not
even warn you if you try to combine incompatible constants.
 
A drawback of bitflag enums is that one also needs to define several
one-liners like operator|, operator& for each such enum type for using
them smoothly. I believe the new meta-language features will make this a
bit easier in the future.
 
hth
Paavo
Xiao Liang <shaw.leon@gmail.com>: Nov 09 06:25PM -0800

在 2017年11月10日星期五 UTC+8上午3:41:47,JiiPee写道:
> with a function or something (reducing human error).
 
> Or the only way to do it is to hardcode like that?
 
> I need this in my flags system where I need values 1,2,4,8,16,...
 
Use macro:
 
enum class MyOpt {
#define OPT(n) opt ## n = 1 << n
OPT(0),
OPT(1),
OPT(2),
OPT(3)
#undef OPT
};
 
Or if you have complex initializer:
 
#define OPT(n) opt ## n = opt_value(n)
constexpr int opt_value(int n) {
if (n == 0) {
return 1;
}
return 2 * opt_value(n - 1);
}
Xiao Liang <shaw.leon@gmail.com>: Nov 09 06:28PM -0800

On Friday, November 10, 2017 at 3:41:47 AM UTC+8, JiiPee wrote:
> with a function or something (reducing human error).
 
> Or the only way to do it is to hardcode like that?
 
> I need this in my flags system where I need values 1,2,4,8,16,...
 
Use macro:
 
enum class MyOpt {
#define OPT(n) opt ## n = 1 << n
OPT(0),
OPT(1),
OPT(2),
OPT(3)
#undef OPT
};
 
Or if you have complex initializer:
 
#define OPT(n) opt ## n = opt_value(n)
constexpr int opt_value(int n) {
if (n == 0) {
return 1;
}
return 2 * opt_value(n - 1);
}
"Öö Tiib" <ootiib@hot.ee>: Nov 09 08:18PM -0800

On Thursday, 9 November 2017 21:41:47 UTC+2, JiiPee wrote:
> with a function or something (reducing human error).
 
> Or the only way to do it is to hardcode like that?
 
> I need this in my flags system where I need values 1,2,4,8,16,...
 
If you there are lot of flags (more than 16 and growing) then
life has shown that using enum may complicate your future. Use
std::bitset as such flag system and keep the enum as index of
a flag in it (IOW defaults 0,1,2,3 ...).
 
When there are less flags that unlikely will grow over time then
do not overthink it. Either use explicit decimals (1, 2, 4, 8,
16, 32, ...) or hexadecimal (0x01, 0x02, 0x04, 0x08, 0x10,
0x20, ...) or bit shifts (1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4,
1 << 5, ...). It is purely aesthetic preference since every of
those will work fine.
scott@slp53.sl.home (Scott Lurndal): Nov 10 01:44PM

>means depending on the usage of the constant, the compiler, the compiler
>version and the compiler optimization flags, making this approach pretty
>fragile.
 
It's only fragile if one doesn't _always_ add the separate definition
as a rule.
 
Prior to typed enums, static const members were the only way to specify
unsigned 64-bit constants due to the default int type for enums.
 
Unfortunatly, some of us are unable to take advantage of C++11 and
beyond due to circumstances outside of our control and must live with
static const members.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Nov 10 02:07PM

On 09/11/2017 20:07, James R. Kuyper wrote:
>> Yes I can do it manually, but I would like to do it automatically maybe
 
> This is about as close as you can get to doing it automatically:
 
> enum class MyOpt {opt1=1, opt2, opt3=opt2*2, opt4=opt3*2};
 
Egregious.
 
opt2=opt1*2
 
/Flibble
"Öö Tiib" <ootiib@hot.ee>: Nov 10 06:12AM -0800

On Friday, 10 November 2017 15:45:15 UTC+2, Scott Lurndal wrote:
 
> Unfortunatly, some of us are unable to take advantage of C++11 and
> beyond due to circumstances outside of our control and must live with
> static const members.
 
Unfortunately there always will be new platform vendors who make
some sort of Crap++ compiler instead of standard one and then
call it C++ and even ask money for it. For example from Arduino or
Texas Instruments one will get such trash.
"James R. Kuyper" <jameskuyper@verizon.net>: Nov 10 10:03AM -0500

On 2017-11-10 09:07, Mr Flibble wrote:
 
>> enum class MyOpt {opt1=1, opt2, opt3=opt2*2, opt4=opt3*2};
 
> Egregious.
 
> opt2=opt1*2
 
I'm simply taking advantage of the default, which is that opt2=opt1+1,
which in this case is exactly the same as opt2=opt1*2. I expect any
reader of my code to be familiar with that default. Perhaps I'm setting
my expectations too high?
scott@slp53.sl.home (Scott Lurndal): Nov 10 03:09PM

>some sort of Crap++ compiler instead of standard one and then
>call it C++ and even ask money for it. For example from Arduino or
>Texas Instruments one will get such trash.
 
In our case, it is dependence upon third-party object libraries that
require certain versions of gcc that don't fully support C++11 and
beyond.
 
That's ok with me; the only features from C++11+ that I'd be
interested in are typed enums and static_assert.
Gareth Owen <gwowen@gmail.com>: Nov 10 05:00PM


> I'm simply taking advantage of the default, which is that opt2=opt1+1,
> which in this case is exactly the same as opt2=opt1*2. I expect any
> reader of my code to be familiar with that default.
 
So you've a potential cost (someone not understanding the default -
slightly less comprehensible code), and literally no benefit at besides
far less typing than it took to explain it.
 
If you're using a pattern, breaking the pattern for *no* *good* *reason*
is a poor idea. People like patterns, and people understand patterns.
ram@zedat.fu-berlin.de (Stefan Ram): Nov 10 12:43AM

>Thanks, but just thinking another thing: is is a good idea at all using
>enums as (option) flags? I read some say online that should use
>constants instead.
 
Or what about
 
main.cpp
 
#include <iostream>
#include <ostream>
 
template< int i >
constexpr int verify()
{ static_assert( i >= 1, "i < 1" );
static_assert( i <= 4, "i > 4" );
return i; }
 
template< int i >constexpr int opt = 1<<( verify< i >()- 1 );
 
int main()
{ ::std::cout << opt< 1 ><< '\n';
::std::cout << opt< 2 ><< '\n';
::std::cout << opt< 3 ><< '\n';
::std::cout << opt< 4 ><< '\n'; }
 
transcript
 
1
2
4
8
 
?
ram@zedat.fu-berlin.de (Stefan Ram): Nov 10 02:52AM

>A string such as 4,800.1 or 3,334.5e9.
 
#include <iostream>
#include <ostream>
#include <string>
 
using namespace ::std::literals;
 
/* This definition of "replace" is a stub!
The implementation is left as an exercise. */
 
static ::std::string replace
( ::std::string const & source,
::std::string const &, ::std::string const & )
{ ::std::string s { source };
s.replace( 1, 1, ""s );
return s; }
 
int main()
{ ::std::cout << stod( replace( "4,800.1"s, ","s, ""s ))<< '\n';
::std::cout << stod( replace( "3,334.5e9"s, ","s, ""s ))<< '\n'; }
 
transcript
 
4800.1
3.3345e+012
ram@zedat.fu-berlin.de (Stefan Ram): Nov 10 12:16PM

>Any of atof, strtod, sscanf will happily convert this, *provided* the
>locale is setup correctly.
 
IIRC, An implementation of C is not required to support
other locales than the "C" locale, so any code based on
any other locale would not be portable.
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: