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

Working with Large Values (double)

378 views
Skip to first unread message

Mike Copeland

unread,
Feb 20, 2014, 7:25:50 PM2/20/14
to
How can I express a large value as a double? (e.g. 1000000.3)
Whereas this compiles and executes, when I try to convert it to a
string value it converts as a scientific string (e.g. "1e+006", not
"1000000.3"). I want to process all the characters of the value of the
data as a std::string.
Or is there a way to convert the double to assure it's not expressed
in scientific notation? TIA

---
This email is free from viruses and malware because avast! Antivirus protection is active.
http://www.avast.com

Paavo Helde

unread,
Feb 21, 2014, 12:33:32 AM2/21/14
to
mrc...@cox.net (Mike Copeland) wrote in
news:MPG.2d704afdc...@news.eternal-september.org:

> How can I express a large value as a double? (e.g. 1000000.3)
> Whereas this compiles and executes, when I try to convert it to a
> string value it converts as a scientific string (e.g. "1e+006", not
> "1000000.3"). I want to process all the characters of the value of
> the data as a std::string.
> Or is there a way to convert the double to assure it's not
> expressed
> in scientific notation? TIA

Yes, there are several ways to achieve that. Example:

#include <iostream>
#include <sstream>
#include <iomanip>

int main() {
double x = 10000.3e+34;

std::ostringstream oss;
oss << std::fixed << std::setprecision(100) << x;
std::string s = oss.str();

std::cout << s << "\n";
}

This prints:
"100003000000000000000000000000000000000.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"

hth
Paavo

Robert Wessel

unread,
Feb 21, 2014, 1:00:10 AM2/21/14
to
On Thu, 20 Feb 2014 17:25:50 -0700, mrc...@cox.net (Mike Copeland)
wrote:

> How can I express a large value as a double? (e.g. 1000000.3)
> Whereas this compiles and executes, when I try to convert it to a
>string value it converts as a scientific string (e.g. "1e+006", not
>"1000000.3"). I want to process all the characters of the value of the
>data as a std::string.
> Or is there a way to convert the double to assure it's not expressed
>in scientific notation? TIA


Doubles are floating point and are inherently "in" scientific
notation.

But if you've converted a double to a character format, you can
usually specify a precision, if the default (commonly 6) is not what
you want. With streams, for example, you can use std::setprecision().

Scott Lurndal

unread,
Feb 21, 2014, 9:51:27 AM2/21/14
to
mrc...@cox.net (Mike Copeland) writes:
> How can I express a large value as a double? (e.g. 1000000.3)
> Whereas this compiles and executes, when I try to convert it to a
>string value it converts as a scientific string (e.g. "1e+006", not
>"1000000.3"). I want to process all the characters of the value of the
>data as a std::string.
> Or is there a way to convert the double to assure it's not expressed
>in scientific notation? TIA

man 3 snprintf

(Yes, it works fine in C++)

Mike Copeland

unread,
Feb 21, 2014, 1:33:52 PM2/21/14
to
In article <miqdg9p89gkk0v3ca...@4ax.com>, robertwessel2
@yahoo.com says...
Yes, a combination of fixed, setw and setprecision do what I want:

double inVal = 10000000.3;
ostringstream ossw;
ossw.str(""), ossw << fixed << setw(10) << setprecision(2) << inVal
<< ends;
str = ossw.str();

Thanks!

jacob navia

unread,
Feb 21, 2014, 2:41:28 PM2/21/14
to
Sorry but compiling with gcc gives
100002999999999994323893219714356215808.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Which compiler did you use?

Victor Bazarov

unread,
Feb 21, 2014, 2:54:18 PM2/21/14
to
*I* get the crisp "3000" with VC++ 2013 Express, for instance. Not sure
about Paavo, of course.

V
--
I do not respond to top-posted replies, please don't ask

Paavo Helde

unread,
Feb 21, 2014, 3:20:42 PM2/21/14
to
jacob navia <ja...@spamsink.net> wrote in
news:le8a54$8rn$1...@speranza.aioe.org:
>>
>> #include <iostream>
>> #include <sstream>
>> #include <iomanip>
>>
>> int main() {
>> double x = 10000.3e+34;
>>
>> std::ostringstream oss;
>> oss << std::fixed << std::setprecision(100) << x;
>> std::string s = oss.str();
>>
>> std::cout << s << "\n";
>> }
>>
>> This prints:
>> "100003000000000000000000000000000000000.00000000000000000000000000000
>> 0000000000000000000000000000000000000000000000000000000000000000000000
>> "
>>
>> hth
>> Paavo
>>
>
> Sorry but compiling with gcc gives
> 100002999999999994323893219714356215808.0000000000000000000000000000000
> 000000000000000000000000000000000000000000000000000000000000000000000
>
> Which compiler did you use?

Microsoft VS2012 Professional, 64-bit mode.

I guess both compilers produce correct output. I like gcc behavior more,
it shows better what one can get when blindly following a whim like "I
don't like scientific notation".

Cheers
Paavo

Paavo Helde

unread,
Feb 21, 2014, 3:28:57 PM2/21/14
to
sc...@slp53.sl.home (Scott Lurndal) wrote in news:PJJNu.5151$7V3.3521
@fx18.iad:

>
> man 3 snprintf
>
> (Yes, it works fine in C++)

Except that it is part of C99 and not present in MSVC++, which is what Mike
is using (to add confusion, there is nonstandard _snprintf with slightly
different interface).

Cheers
Paavo

Geoff

unread,
Feb 21, 2014, 4:14:58 PM2/21/14
to
Copeland is writing a check writing program, I think scientific
notation might not work in that case. :)

Robert Wessel

unread,
Feb 21, 2014, 8:28:32 PM2/21/14
to
On Fri, 21 Feb 2014 13:14:58 -0800, Geoff <ge...@invalid.invalid>
wrote:
Attempting to use FP to represent currency is fundamentally doomed to
failure. I didn't see that that's what the OP was doing, but if it
is, he should definitely reconsider, unless he doesn't actually care
about the actual results (which may well be the case if this something
like a homework assignment).

Mike Copeland

unread,
Feb 22, 2014, 6:50:26 PM2/22/14
to
> > Doubles are floating point and are inherently "in" scientific
> > notation.
> >
> > But if you've converted a double to a character format, you can
> > usually specify a precision, if the default (commonly 6) is not what
> > you want. With streams, for example, you can use std::setprecision().
>
> Yes, a combination of fixed, setw and setprecision do what I want:
> double inVal = 10000000.3;
> ostringstream ossw;
> ossw.str(""), ossw << fixed << setw(10) << setprecision(2) << inVal;
> str = ossw.str();

Actually, the "setw(10)" isn't needed.

jacob navia

unread,
Feb 23, 2014, 3:41:06 AM2/23/14
to
Writing a check of 10000.3e+34 dollars???????????

WOW, I think that goes even beyond the U.S. TOTAL debt!


James Kanze

unread,
Feb 23, 2014, 8:53:21 AM2/23/14
to
On Saturday, February 22, 2014 1:28:32 AM UTC, robert...@yahoo.com wrote:

> Attempting to use FP to represent currency is fundamentally doomed to
> failure.

That depends on what you are doing. If you're doing
risk analysis on futures contracts, for example, it's
perfectly appropriate (and you probably can't afford
the loss of performance a decimal solution would cost
you). After all, any rounding errors will be much
less than the variance of the Monte Carlo simulation
anyway.

If you're doing anything even closely related to
legally required bookkeeping, however (and I would
imagine writing checks comes into that providence),
then using machine floating point is probably illegal,
and could, in many jurisdictions, send you to jail.

Note that I say "machine floating point", and not just
FP. There's no problem with a well written decimal
floating point package here. For that matter, it's
possible to use machine floating point, *if* you scale
so that all actual values are exactly representable
whole numbers, and take the proper precautions. It's
anything but trivial, however, and I'd probably go
with a decimal package, even if I had to write it
myself, as being a lot simpler.

--
James

James Kanze

unread,
Feb 23, 2014, 8:57:28 AM2/23/14
to
On Friday, February 21, 2014 6:00:10 AM UTC, robert...@yahoo.com wrote:
> On Thu, 20 Feb 2014 17:25:50 -0700, mrc...@cox.net (Mike Copeland)
> wrote:

> > How can I express a large value as a double? (e.g. 1000000.3) Whereas
> > this compiles and executes, when I try to convert it to a
> >string value it converts as a scientific string (e.g. "1e+006", not
> >"1000000.3"). I want to process all the characters of the value of the data
> >as a std::string. Or is there a way to convert the double to assure it's
> >not expressed in scientific notation? TIA

> Doubles are floating point and are inherently "in" scientific
> notation.

No. Scientific notation, like pratically all other text
formats, is base 10. None of the floating point formats I know
of that are in use today are base 10. And the way machine
floating point typically represents the exponent is not
scientific notation either.

> But if you've converted a double to a character format, you can
> usually specify a precision, if the default (commonly 6) is not what
> you want. With streams, for example, you can use std::setprecision().

Or just call `precision` on the stream itself. (I don't think
I've ever `std::setprecision()`.)

--
James

James Kanze

unread,
Feb 23, 2014, 8:59:22 AM2/23/14
to
On Friday, February 21, 2014 2:51:27 PM UTC, Scott Lurndal wrote:

> man 3 snprintf
>
> (Yes, it works fine in C++)

Funny, because it never worked "fine" in C. In C, you use it,
because there's not really anything else, but C formatted output
has to be one of the worst designs ever.

--
James
Message has been deleted

jacob navia

unread,
Feb 23, 2014, 9:46:10 AM2/23/14
to
Of course. For instance in the evil C language you use:

printf("0x%08x\n", x);

In the much more advanced C++ language you use:

std::cout << std::hex << std::setfill('0') << std::setw(8) << x <<
std::dec << std::endl;

Of course C has ONE of the worst designs. But C++ has THE WORST!

:-)

jacob

woodb...@gmail.com

unread,
Feb 23, 2014, 1:09:48 PM2/23/14
to
We've discussed this a hundred times. They both have
weaknesses. The poor performance of iostream implementations
is on my list as far as the C++ weaknesses.

Brian
Ebenezer Enterprises - In G-d we trust.
http://webEbenezer.net

Juha Nieminen

unread,
Feb 24, 2014, 6:32:39 AM2/24/14
to
jacob navia <ja...@spamsink.net> wrote:
> Of course C has ONE of the worst designs. But C++ has THE WORST!

The C version is not type safe, cannot be expanded with new types, and
has poor abstraction, while the C++ version has all of those.

Just as an example of that, assume you have in one file

typedef int Integral;

and in another something along the lines of

void foo(Integral i)
{
printf("???", i); // What to put here?
}

If you put "%i" there, it will break if 'Integral' is ever changed to
a bigger or incompatible type.

With luck, the compiler will give you warnings for the format string
not matching the parameter types, so you can manually go and fix all
the instances. Excellent programming technique.

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---
Message has been deleted
Message has been deleted

Gerhard Fiedler

unread,
Feb 24, 2014, 8:14:49 AM2/24/14
to
jacob navia wrote:

> Le 23/02/2014 14:59, James Kanze a écrit :
>> On Friday, February 21, 2014 2:51:27 PM UTC, Scott Lurndal wrote:
>>
>>> man 3 snprintf
>>>
>>> (Yes, it works fine in C++)
>>
>> Funny, because it never worked "fine" in C. In C, you use it,
>> because there's not really anything else, but C formatted output
>> has to be one of the worst designs ever.
>>
>
> Of course. For instance in the evil C language you use:
>
> printf("0x%08x\n", x);
>
> In the much more advanced C++ language you use:
>
> std::cout << std::hex << std::setfill('0') << std::setw(8) << x <<
> std::dec << std::endl;

If you have a need to print this more often than once, then there are
other language features that you can use to encapsulate all this.

There are also libraries that use C++ features to provide something
similar in ways that avoid some of the problems of built-in streams.

OTOH, (type-safely) encapsulating printf is quite the challenge.

Gerhard
Message has been deleted

jacob navia

unread,
Feb 24, 2014, 8:29:34 AM2/24/14
to
Le 24/02/2014 12:32, Juha Nieminen a écrit :
> The C version is not type safe
Most modern C compilers will warn if you pass an incorrect type to
printf. please, no straw men here.

jacob navia

unread,
Feb 24, 2014, 8:49:38 AM2/24/14
to
Le 24/02/2014 12:32, Juha Nieminen a écrit :
> The C version is not type safe, cannot be expanded with new types,

In C++ you have to overload the operator << as far as I remember. In C
you have to write a "Print_XXX" function. I do not see why C++ is so
fundamentally better.

But I am afraid you will never be convinced (of course). Do as you wish,
but stop denigrating other computer languages that can be used as
effectively as C++.

Since its birth, C++ tried to be the "better C", "C with classes"
whatever. That is why it is fundamental for them to denigrate C to
convince everyone that C++ is the "better way".

Maybe you would stop doing that?

After 20 years of insults and lies, you have won. You have destroyed the
C language to the point that the C standards committee doesn't dare to
prescrive something for fear it would bother the C++ language, or make a
comptetition with C++. Thus, C has stagnated, nothing is being developed
and all efforts go to C++.

Look, now you have anonymous lambdas and all common lisp in your language.

Why go on pounding C?

Is it not enough already?

When I try to discuss a package I wrote ( a C containers library) in
comp.lang.c hordes of C++ people go there to "preach the good word" and
tell me that what I did (and run every day) is "impossible, I am lying C
can't do that" etc.

Just stop denigrating C.

Thanks in advance

jacob
Message has been deleted

jacob navia

unread,
Feb 24, 2014, 9:14:03 AM2/24/14
to
Le 24/02/2014 14:58, Stefan Ram a écrit :
> jacob navia <ja...@spamsink.net> writes:
>> Le 24/02/2014 12:32, Juha Nieminen a écrit :
>>> The C version is not type safe, cannot be expanded with new types,
>> In C++ you have to overload the operator << as far as I remember. In C
>> you have to write a "Print_XXX" function. I do not see why C++ is so
>> fundamentally better.
>
> Because in C++, the user can always use the same verb:
>
> ... << x ...
> ... << i ...
>
> while in C, he has to remember individual verbs per type
>
> print_double( x )
> print_int( x )
>

With a consistent naming convention I do not see how this could ever be
a problem.

print_xxx(XXX *data);

is quite easy to use, remember, etc, the same as <<.

> or cannot infer a static type at all, because the type is
> not know at compile time, in which case one needs to start
> to implement OO in C, which is already supplied by the
> language in C++.
>

As far as I remember C++ is statically typed language, i.e. everything
is known at compile time. Objective C, is not, and you use the method
lookup of the language to figure out dynamically what "print" function
would be called. There is no method lookup in c++ so the compiler
generates in the case of a virtual function a lookup in a specific class
hierarchy that must be given to it at compile time. True, there is a
genericity here that is not there in C.

Do I need that?

How much does that costs me in memory area in my cramped brain?

Do I want that?

Those are questions that everyone answers as he/she likes/must.
I would not blame anyone for choosing C++, I have even worked debugging
C++, everyone must try to feed his/her family somehow.

What bothers me precisely is this lack of respect from C++ programmers
that believe that because they have mastered some c++ trivialities they
are better than people that do not care about them.

Look at how java programmers are laughed at here. Or Fortran
programmers, or whatever. It is this attitude, this lack of respect that
I question.

Thanks


Victor Bazarov

unread,
Feb 24, 2014, 9:14:47 AM2/24/14
to
On 2/24/2014 8:49 AM, jacob navia wrote:
> Le 24/02/2014 12:32, Juha Nieminen a écrit :
>> The C version is not type safe, cannot be expanded with new types,
>
> In C++ you have to overload the operator << as far as I remember. In C
> you have to write a "Print_XXX" function. I do not see why C++ is so
> fundamentally better.

Too bad. Perhaps you can read more about overloading, it's one
important feature of C++ that sets it aside from C.

> But I am afraid you will never be convinced (of course). [..]

You took the words right out of my mouth (fingertips)... :-)

Wouter van Ooijen

unread,
Feb 24, 2014, 9:21:35 AM2/24/14
to
jacob navia schreef op 24-Feb-14 3:14 PM:

>> ... << x ...
>> ... << i ...
>
> There is no method lookup in c++ so the compiler
> generates in the case of a virtual function a lookup in a specific class
> hierarchy that must be given to it at compile time. True, there is a
> genericity here that is not there in C.

For the simple case of <<'ing a value no virtual function lookup is
needed, because the compiler knows the type of the rhs and hence which
method or function to call. A vft is needed only when the rhs is
(derived from) a base type that has a virtual << method.

Wouter van Ooijen

jacob navia

unread,
Feb 24, 2014, 9:30:27 AM2/24/14
to
Le 24/02/2014 15:14, Victor Bazarov a écrit :
> Perhaps you can read more about overloading, it's one important feature
> of C++ that sets it aside from C.

I have implemented function overloading in my compiler system lcc-win.
And true, I have read a lot of things about overloading, and also about
how overloading (like anything) can be ABUSED.

For example, the expression

String a,b,c;
c = a+b;

is an *abuse* of overloading.

Why?

Because there is no ADDITION being done when a and b are STRINGS but a
concatenation of two strings, what is *completely different*. If a and b
are strings we have

a+b != b+a

what goes against all the mathematical basis of addition as normal
people use that word.

That is why string "addition" is an ABUSE of overloading.

In the same vein, shifting left an object to print it just because the
opeartor << looks like the head of a left arrow or suggests "put into"
is NONSENSE and an abuse of the overloading concept.

This WRONG DESIGN DECISION is at the heart of a catastrophe in c++ i/o
as I showed in my example.

No, output has nothing to do (really *NOTHING*) with left shift, and the
whole concept precludes querying the state of the output machine,
precludes a simpler syntax, etc. This is so true that now there are C++
packages that output their data without operator overloading.

As I documented in the documentation of my compiler system, overloading
works best when used with NUMBERS or NUMERIC data. It is also a great
idea when used with arrays (overloading operator []). But in OTHER
applications it can be an incredibly BAD idea.

The world is a complex place and there is no magic bullets Mr Bazarov.
Things that are good in some contexts are BAD in another. Knives are
great for cutting bread, but they can cut your finger as easily too.

Beware!

:-)

jacob

P.S. It would be great if you wouldn't assume that other people that do
not agree with c++'s decisions are ignorants that "should read more".
Thanks.

jacob navia

unread,
Feb 24, 2014, 9:34:55 AM2/24/14
to
I know, I was speaking of the general case of course. In the << case the
compiler saves the programmer the effort of remembering the name of the
output function since all syntax is just <<.
As I said before, using a simple

print_xxx

naming convention makes this as easy to remember as the << syntax.

Besides, if you want to support SEVERAL print functions for instance for
formatting a customer with name, age or name, SS number, or just
initials, etc you will need anyway several print functions in C++ also,
if I remember correctly isn't it?

jacob

Scott Lurndal

unread,
Feb 24, 2014, 9:47:39 AM2/24/14
to
James Kanze <james...@gmail.com> writes:
>On Saturday, February 22, 2014 1:28:32 AM UTC, robert...@yahoo.com wrote:
>
>> Attempting to use FP to represent currency is fundamentally doomed to
>> failure.
>
>That depends on what you are doing. If you're doing
>risk analysis on futures contracts, for example, it's
>perfectly appropriate (and you probably can't afford
>the loss of performance a decimal solution would cost

Actually, scaled binary integers are probably the best
bet for this (given 64-bit integers). Performs better
than FP and no binary FP nonrepresentability issues.

Scale everything to mils and work accordingly.

>you). After all, any rounding errors will be much
>less than the variance of the Monte Carlo simulation
>anyway.
>
>If you're doing anything even closely related to
>legally required bookkeeping, however (and I would
>imagine writing checks comes into that providence),
>then using machine floating point is probably illegal,
>and could, in many jurisdictions, send you to jail.
>
>Note that I say "machine floating point", and not just

Note that several (now rare) processor architectures
included hardware support for decimal floating point. These
were the architectures used by banks and other financial
institutions (Burroughs (V-series), IBM (zSeries, pSeries),
et alia.)

Scott Lurndal

unread,
Feb 24, 2014, 9:49:20 AM2/24/14
to
One can count on microsoft to screw things up, I guess. sprintf is
a security problem waiting to catch a poor programmer and should have been
deprecated two decades ago.

Scott Lurndal

unread,
Feb 24, 2014, 9:50:56 AM2/24/14
to
Compared to the crapfest that C++ defines (operator overloading,
setw, setprecision, et alia;give me a break!), snprintf is a paragon of clarity.

I suppose you could always use to COBOL picture clauses :-)

Victor Bazarov

unread,
Feb 24, 2014, 9:54:52 AM2/24/14
to
On 2/24/2014 9:30 AM, jacob navia wrote:
> Le 24/02/2014 15:14, Victor Bazarov a écrit :
>> Perhaps you can read more about overloading, it's one important feature
>> of C++ that sets it aside from C.
>
> I have implemented function overloading in my compiler system lcc-win.
> And true, I have read a lot of things about overloading, and also about
> how overloading (like anything) can be ABUSED.
>
> For example, the expression
>
> String a,b,c;
> c = a+b;
>
> is an *abuse* of overloading.
> [.. rant about operator overloading removed ..]

You really need to stop taking everything as an attack, you know. When
I mentioned overloading, I did really mean *function* overloading. And,
curiously enough, as you do claim to have "implemented function
overloading", you immediately go on giving an example of *operator*
overloading as a feature that is prone to abuse...

Well, let me be a bit more verbose, as now I see that my *assumption* of
your somewhat skewed knowledge of overloading was most likely the cause
for your "disagreement".

When you define 'print' function for other types, the main advantage the
overloading gives you is that you don't need to name those functions
differently.

... print(const OneType& val);

can easily coexist in C++ with

... print(const SomeOtherType& val);

which gives you this important feature -- you can write in your code

print(someObject);

without having to remember what type 'someObject' has. The compiler
will pick the right function for you.

> P.S. It would be great if you wouldn't assume that other people that do
> not agree with c++'s decisions are ignorants that "should read more".

Even if you are not "an ignorant", the pattern of your disagreement
"with c++'s decisions" does indeed suggest that you should read more,
and I am not sorry that I assumed as much.

Scott Lurndal

unread,
Feb 24, 2014, 9:56:37 AM2/24/14
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:
>jacob navia <ja...@spamsink.net> writes:
>>Le 24/02/2014 12:32, Juha Nieminen a écrit :
>>>The C version is not type safe, cannot be expanded with new types,
>>In C++ you have to overload the operator << as far as I remember. In C
>>you have to write a "Print_XXX" function. I do not see why C++ is so
>>fundamentally better.
>
> Because in C++, the user can always use the same verb:
>
>... << x ...
>... << i ...
>
> while in C, he has to remember individual verbs per type
>
>print_double( x )
>print_int( x )
>
> or cannot infer a static type at all, because the type is
> not know at compile time, in which case one needs to start
> to implement OO in C, which is already supplied by the
> language in C++.


After a quarter century of writing production C++ code, I find your
complaints to be spurious. I use the standard C library formatting
utilities and I have no problem remembering anything about how to
use them.

Modern compilers are good at warning about varargs argument mismatches
with the format string. A good programmer seldom needs to change a
datatype for an existing variable when maintaining a program because
the correct type was chosen from the start.

You're inventing a problem that doesn't exist, just to denigrate another
language.

Modern C++ has become almost unreadable.

Wouter van Ooijen

unread,
Feb 24, 2014, 10:04:04 AM2/24/14
to
jacob navia schreef op 24-Feb-14 3:34 PM:
> Besides, if you want to support SEVERAL print functions for instance for
> formatting a customer with name, age or name, SS number, or just
> initials, etc you will need anyway several print functions in C++ also,
> if I remember correctly isn't it?

In true C++: if that is what you want it is cetainly possible, just like
you can have print_xxx functions if you want to.

I think I would prefer to reserve operator<<(person) for (debug)
printing of ALL data in person, and have separate getters for the items
that you might want to print, like

std::cout
<< std::setw( 30 ) << person.name()
<< " lives at "
<< std::setw( 60 ) << person.adress();

This keeps *what* you want to print separate from *how* you want to
print it.

Wouter van Ooijen

Scott Lurndal

unread,
Feb 24, 2014, 10:05:31 AM2/24/14
to
Gerhard Fiedler <gel...@gmail.com> writes:

>
>OTOH, (type-safely) encapsulating printf is quite the challenge.
>

See, that's the C++ programmer view. A real programmer will use
snprintf when and where it makes sense and not worry about "encapsulating"
it and doesn't care about spurious "language purity".

examples from C++ operating system:

snprintf(buf, sizeof(buf), "QM%05u", s->drive_serial);
snprintf(name, sizeof(name), "vdev-xen%u", index);
snprintf(ep, (varlen+vallen+2), "%s=%s", argv[1], argv[2]);

Letting the compiler check arguments, even on user-defined functions
is trivial with a good compiler:

class Console {

...
public:
void printf(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
};


console->printf("This warns if long long argument used %u\n", long_long_unsigned_int_var);

Paavo Helde

unread,
Feb 24, 2014, 10:13:00 AM2/24/14
to
sc...@slp53.sl.home (Scott Lurndal) wrote in
news:QZIOu.9571$sB7....@fx19.iad:
Agreed, but nobody has proposed using sprintf.

Cheers
Paavo

Wouter van Ooijen

unread,
Feb 24, 2014, 10:14:27 AM2/24/14
to
jacob navia schreef op 24-Feb-14 3:30 PM:> For example, the expression
>
> String a,b,c;
> c = a+b;
>
> is an *abuse* of overloading.

Maybe, but a maybe-not-so-pretty solution must be compared to the
alternatives. How would you prefer to add a lot of strings?

// C++, overloading +
msg = "M name[" + x.name + "],address[" + x.address + "] END";

// Python, with compile-time support for checking the format string
msg = "M [name[%s],address[%s] END" % ( x.name, x.address )

// No tricks, using nested concatenate function (LISP style??)
msg = concatenate(
"M name["
concatenate(
x.name
concatenate(
"],address["
concatenate(
x.address,
"] END")))));

// sequence of append calls (C style??)
msg = ""
append( msg, "M name[" );
append( msg, x.name );
append( msg, "],address[" );
append( msg, x.address );
append( msg, "] END" );

jacob navia

unread,
Feb 24, 2014, 10:23:20 AM2/24/14
to
Le 24/02/2014 15:54, Victor Bazarov a écrit :
> When I mentioned overloading, I did really mean *function* overloading.

Well, strange, since we were talking about the << syntax of c++ for
OUTPUT, what is operator overloading and NOT function overloading.

It is a pity that all my arguments are brushed aside as "a rant" and you
do not even go into them.

This is convenient for you of course, since the sorry state of affairs
in c++ because precisely too much operator overloading when formatting
is at the center of this dicussion.

Now, to come back to a function overload solution:

Having a SINGLE print function to print ANY object looks great at first
but then... how do you remember which one to use?


Suppose

void print(XXX *data1);
void print(XXX *data1, FILE *sink);
void print(XXX *data1, int printFlags, FILE *sink);
void print(XXX *data1, int printFlags, int linewidth); // Uses stdout
void print(YYY *data2, long long printflags);
void print(YYY *data2, CUSTOMER *c, long long flags);

etc.

Now the programmer must remember which arguments/argument order is
necessary for each function... And since all have the SAME name
remembering them is MUCH more difficult than

void print_noargs(XXX *data1);
void printWithSink(XXX *data1, FILE *sink);
void printFlagsSink(XXX *data1, int flags, FILE *sink);

or other similar simple naming schema.

You see?

IT DEPENDS!

If you have few "print" functions with identical number of arguments
overloading is OK, but as the print functions proliferate, it becomes
more and more difficult to use the correct one!

*IT DEPENDS*

That is what many C++ heads do not understand. The world is very complex
and single solutions are good in some contexts, bad in another,
the same as I said from operator overloading.

Thanks for your input.

Wouter van Ooijen

unread,
Feb 24, 2014, 10:25:30 AM2/24/14
to
Scott Lurndal schreef op 24-Feb-14 3:56 PM:
> Modern compilers are good at warning about varargs argument mismatches
> with the format string.

That might be the case, but it is a mechanism that is closed to the
programmer (or library developer).

> Modern C++ has become almost unreadable.

Y ain't seen nothing yet! Try template metaprogramming :)

Wouter van Ooijen



Message has been deleted

jacob navia

unread,
Feb 24, 2014, 10:28:08 AM2/24/14
to
Please, this is beginner level question


Solution 1: (preferred)
-----------------------
int strcatMany(char *first,...);

calling sequence:

strcatMany(a,b,c,NULL);

or another:

Solution 2
----------
strcatMany(int n,...);

calling sequence:

strcatMany(4,"1","2,"3","4");
This is not so good because you can make a mistake counting the strings.

jacob

jacob navia

unread,
Feb 24, 2014, 10:36:03 AM2/24/14
to
Le 24/02/2014 16:26, Stefan Ram a écrit :
> Wouter van Ooijen <wou...@voti.nl> writes:
>> Maybe, but a maybe-not-so-pretty solution must be compared to the
>> alternatives. How would you prefer to add a lot of strings?
>> // C++, overloading +
>> msg = "M name[" + x.name + "],address[" + x.address + "] END";
>
> // Perl, overloading .
> msg = "M name[" . name . "],address[" . address . "] END";
>
> // VBA, overloading &
> msg = "M name[" & name & "],address[" & address & "] END"
>
> This solves the objection of overloading »+« against its
> supposed semantics of the mathematical addition, while it
> keeps the other advantages of a notation with a binary
> operator for concatenation.
>
> Yet, I have never observed any real problems with
> overloading »+« to mean string concatenation.
>

What about the problem of the intermediate results?

When using

zz=a+b+c+d;

the compiler must realize that it is better to avoid intermediate
results! This makes the compiler specialize in a special case of
operator overloading. Is this justified?

And another problem

zz = a + b + 12;

b+12 is defined in C (and C++) since it is a pointer+integer addition
giving a pointer to 12 characters after the start of b.

What happens there? Will the compiler silently accept that mistake?

You see?

The INTERACTIONS between features are also a problem.

Wouter van Ooijen

unread,
Feb 24, 2014, 10:43:00 AM2/24/14
to
jacob navia schreef op 24-Feb-14 4:28 PM:
> Solution 1: (preferred)
> -----------------------
> int strcatMany(char *first,...);
>
> calling sequence:
>
> strcatMany(a,b,c,NULL);

strcatMany( a, b, c );

:(

Wouter van Ooijen

PS Jacob, why are you hanging out of a C++ forum?

Victor Bazarov

unread,
Feb 24, 2014, 10:51:41 AM2/24/14
to
On 2/24/2014 10:23 AM, jacob navia wrote:
> Le 24/02/2014 15:54, Victor Bazarov a écrit :
>> When I mentioned overloading, I did really mean *function* overloading.
>
> Well, strange, since we were talking about the << syntax of c++ for
> OUTPUT, what is operator overloading and NOT function overloading.

If you care to reread the thread, I decided to reply to you when you stated

On 2/24/2014 8:49 AM, jacob navia wrote:
> Le 24/02/2014 12:32, Juha Nieminen a écrit :
>> The C version is not type safe, cannot be expanded with new types,
>
> In C++ you have to overload the operator << as far as I remember. In C
> you have to write a "Print_XXX" function. I do not see why C++ is so
> fundamentally better.

So, let me repeat.

C++ is so "fundamentally better" that you don't have to write Print_XXX
function with different XXX for every different type.

Moreover, making 'print_whatnot' a stand-alone function would probably
be a design mistake in that case anyway. Most likely it's better to
split the responsibilities between three parts of the design -- the
class that needs to be printed, the sink that handles the actual output
and the template that binds the two.

But again, this discussion is not about how to design an output for a
combination of object types and sinks, is it?

>
> It is a pity that all my arguments are brushed aside as "a rant" and you
> do not even go into them.

There is no depth in them that would allow anybody to "go into them",
unfortunately.

> This is convenient for you of course, since the sorry state of affairs
> in c++ because precisely too much operator overloading when formatting
> is at the center of this dicussion.
>
> Now, to come back to a function overload solution:
>
> Having a SINGLE print function to print ANY object looks great at first
> but then... how do you remember which one to use?

"Are you saying that I can dodge bullets?"
"I am saying that when you are ready, you won't have to."

(or something like that). You're still thinking in C terms. You don't
have to remember which function to use *when* your output subsystem is
designed and implemented properly, using not C but C++ mechanisms as
they are intended to be used.

>
>
> Suppose
>
> void print(XXX *data1);
> void print(XXX *data1, FILE *sink);
> void print(XXX *data1, int printFlags, FILE *sink);
> void print(XXX *data1, int printFlags, int linewidth); // Uses stdout
> void print(YYY *data2, long long printflags);
> void print(YYY *data2, CUSTOMER *c, long long flags);
>
> etc.
>
> Now the programmer must remember which arguments/argument order is
> necessary for each function... And since all have the SAME name
> remembering them is MUCH more difficult than
>
> void print_noargs(XXX *data1);
> void printWithSink(XXX *data1, FILE *sink);
> void printFlagsSink(XXX *data1, int flags, FILE *sink);
>
> or other similar simple naming schema.
>
> You see?

No, I don't see. What I see is a C approach to designing C++
interfaces, and *that* is the most common problem leading to the
dismissal of C++ features by those who come from long (too long if you
ask me) time use of C.

It's not impossible for C programmers to adopt the correct approach and
learn C++ ways -- I've seen it happen, but more often than not it's due
to what seems their lack of interest or fear to have to apply effort or
to leave the comfort of well-learned C idioms that they stay in their
playpen and keep trying to use their trusted building blocks instead of
getting to know a complex erector set.

>
> IT DEPENDS!
>
> If you have few "print" functions with identical number of arguments
> overloading is OK, but as the print functions proliferate, it becomes
> more and more difficult to use the correct one!
>
> *IT DEPENDS*
>
> That is what many C++ heads do not understand. The world is very complex
> and single solutions are good in some contexts, bad in another,
> the same as I said from operator overloading.
>
> Thanks for your input.

You're welcome.

It looks that you're just starting on the journey that is C++. You have
made a few wrong steps and your feet start to ache or perhaps you
twisted your ankle because you weren't watchful enough for rocks just
underneath the surface. Two thoughts come to mind. Don't let a small
pain divert you from the right path. And, when in shallows, don't
pretend you're treading water -- others who have already passed that
part of the way will see right through that.

Good luck in your studies!
Message has been deleted

Victor Bazarov

unread,
Feb 24, 2014, 10:57:37 AM2/24/14
to
On 2/24/2014 10:36 AM, jacob navia wrote:
> Le 24/02/2014 16:26, Stefan Ram a écrit :
>> Wouter van Ooijen <wou...@voti.nl> writes:
>>> Maybe, but a maybe-not-so-pretty solution must be compared to the
>>> alternatives. How would you prefer to add a lot of strings?
>>> // C++, overloading +
>>> msg = "M name[" + x.name + "],address[" + x.address + "] END";
>>
>> // Perl, overloading .
>> msg = "M name[" . name . "],address[" . address . "] END";
>>
>> // VBA, overloading &
>> msg = "M name[" & name & "],address[" & address & "] END"
>>
>> This solves the objection of overloading »+« against its
>> supposed semantics of the mathematical addition, while it
>> keeps the other advantages of a notation with a binary
>> operator for concatenation.
>>
>> Yet, I have never observed any real problems with
>> overloading »+« to mean string concatenation.
>>
>
> What about the problem of the intermediate results?
>
> When using
>
> zz=a+b+c+d;
>
> the compiler must realize that it is better to avoid intermediate
> results! This makes the compiler specialize in a special case of
> operator overloading. Is this justified?

You make it sound that the existence of move c-tors is somehow
unjustified in C++. Using proper technique helps the compiler to avoid
having to "realize that it is better". The compiler is but a tool, and
it is *you* who realize (or not, like in this case) *what* is *better*
and what isn't.

>
> And another problem
>
> zz = a + b + 12;
>
> b+12 is defined in C (and C++) since it is a pointer+integer addition
> giving a pointer to 12 characters after the start of b.
>
> What happens there? Will the compiler silently accept that mistake?

No. You can't overload operators for built-in types. If 'b' is a
pointer, b + 12 is a pointer. If 'b' is a string type with an
overloaded '+' operator, it will either have an overloaded variation
that accepts 'int' as its argument, or the compiler will report an error.

> You see?

All I see is ignorance so far.

> The INTERACTIONS between features are also a problem.

Perhaps you care to post a complete C++ program that illustrates that.

Victor Bazarov

unread,
Feb 24, 2014, 11:03:43 AM2/24/14
to
You can make a mistake of providing a wrong variable in that list and
the compiler is unfortunately *impotent* to help you:

int fortytwo = 42;
char* two = "2";
char* here = "1";
...
strcatMany(here, two, fortytwo, NULL);

(not to mention that 'here' probably has not enough room to contain the
entire string, and you *need to remember that*). There is so much that
is wrong with those approaches.

Martin Shobe

unread,
Feb 24, 2014, 11:10:03 AM2/24/14
to
On 2/24/2014 9:36 AM, jacob navia wrote:
> Le 24/02/2014 16:26, Stefan Ram a écrit :
>> Wouter van Ooijen <wou...@voti.nl> writes:
>>> Maybe, but a maybe-not-so-pretty solution must be compared to the
>>> alternatives. How would you prefer to add a lot of strings?
>>> // C++, overloading +
>>> msg = "M name[" + x.name + "],address[" + x.address + "] END";
>>
>> // Perl, overloading .
>> msg = "M name[" . name . "],address[" . address . "] END";
>>
>> // VBA, overloading &
>> msg = "M name[" & name & "],address[" & address & "] END"
>>
>> This solves the objection of overloading »+« against its
>> supposed semantics of the mathematical addition, while it
>> keeps the other advantages of a notation with a binary
>> operator for concatenation.
>>
>> Yet, I have never observed any real problems with
>> overloading »+« to mean string concatenation.
>>
>
> What about the problem of the intermediate results?
>
> When using
>
> zz=a+b+c+d;
>
> the compiler must realize that it is better to avoid intermediate
> results! This makes the compiler specialize in a special case of
> operator overloading. Is this justified?

Why must it realize that? It's certainly allowed to, but "must"?

> And another problem
>
> zz = a + b + 12;
>
> b+12 is defined in C (and C++) since it is a pointer+integer addition
> giving a pointer to 12 characters after the start of b.
>
> What happens there? Will the compiler silently accept that mistake?

The precedence rules say that 12 is added to the results of a + b. So
that particular mistake doesn't occur. Since you appear to be
overloading "+" for "char *", zz would now contain the address of a[12],
while a would contain the concatenation of a + b.

Unintuitive, certainly. It's why I wouldn't overload + on "char *". For
a string class, this wouldn't be an issue.

Martin Shobe

Martin Shobe

unread,
Feb 24, 2014, 11:23:28 AM2/24/14
to
Aside from using names that have been reserved, this is silently
undefined behavior if we try the following (a situation you used to
denigrate overloading +):

strcatMany(a, b, 12);

Even that aside, the only way you've left to get the concatenated string
is through a global variable. I find that to be a serious deficiency,
though one that can be fixed.

int Concatenate(char * dest, char const * first, ...);
int ConcatenateN(char * dest, int n, ...);

Martin Shobe

Geoff

unread,
Feb 24, 2014, 11:40:47 AM2/24/14
to
On Mon, 24 Feb 2014 14:47:39 GMT, sc...@slp53.sl.home (Scott Lurndal)
wrote:

>Scale everything to mils and work accordingly.

Tell that to Intuit, the largest publisher of financial software on
the PC. They appear to be using float for their currency values.

jacob navia

unread,
Feb 24, 2014, 11:57:20 AM2/24/14
to
Le 24/02/2014 16:57, Victor Bazarov a écrit :

>
> All I see is ignorance so far.

Of course. You win. This discussion is finished.

Paavo Helde

unread,
Feb 24, 2014, 12:03:58 PM2/24/14
to
Wouter van Ooijen <wou...@voti.nl> wrote in news:530b61cd$0$25294
$e4fe...@dreader34.news.xs4all.nl:

> jacob navia schreef op 24-Feb-14 3:30 PM:> For example, the expression
> >
> > String a,b,c;
> > c = a+b;
> >
> > is an *abuse* of overloading.
>
> Maybe, but a maybe-not-so-pretty solution must be compared to the
> alternatives. How would you prefer to add a lot of strings?
>
> // C++, overloading +
> msg = "M name[" + x.name + "],address[" + x.address + "] END";

One could argue this is not the best way to do this in C++. On one hand
it may be unnecessarily slow and on the other hand the structure of the
result is not readily visible. So, depending on circumstances I would
write this in different ways in C++. In performance-critical code:

std::string msg = "M name[";
msg += x.name;
msg += "],address[";
msg += x.address;
msg += "] END";

If the speed is not critical, I would use my nifty typesafe wrapper of
snprintf(), which checks the format string and converts the arguments as
needed:

std::string msg = Sprintf("M [name[%s],address[%s] END")(x.name)
(x.address);

Cheers
Paavo

David Brown

unread,
Feb 24, 2014, 12:07:23 PM2/24/14
to
On 24/02/14 16:43, Wouter van Ooijen wrote:
> jacob navia schreef op 24-Feb-14 4:28 PM:
>> Solution 1: (preferred)
>> -----------------------
>> int strcatMany(char *first,...);
>>
>> calling sequence:
>>
>> strcatMany(a,b,c,NULL);
>
> strcatMany( a, b, c );
>
> :(

gcc would solve that with:

extern int strcatMany(char *first, ...)
__attribute__((sentinel));

and compiling with -Wformat (or -Wall).

I don't know if lcc-win has such useful features.


(Personally, I prefer the C++ "overloaded +" syntax.)

Scott Lurndal

unread,
Feb 24, 2014, 12:41:10 PM2/24/14
to
Wouter van Ooijen <wou...@voti.nl> writes:
snprintf(msg, sizeof(msg), "M name[%s],address[%s] END", x.name, x.address);

Even avoids buffer overflow regardless of the length of x.name or x.address.

scott

Scott Lurndal

unread,
Feb 24, 2014, 12:44:36 PM2/24/14
to
Wouter van Ooijen <wou...@voti.nl> writes:
>Scott Lurndal schreef op 24-Feb-14 3:56 PM:
>> Modern compilers are good at warning about varargs argument mismatches
>> with the format string.
>
>That might be the case, but it is a mechanism that is closed to the
>programmer (or library developer).

Not in the gcc, wherein __attribute__((format)) can be used by both.

>
>> Modern C++ has become almost unreadable.
>
>Y ain't seen nothing yet! Try template metaprogramming :)

I have. Between templates and lambdas, the language has become
unreadable :-)

scott

Ian Collins

unread,
Feb 24, 2014, 1:53:41 PM2/24/14
to
jacob navia wrote:
> Le 24/02/2014 12:32, Juha Nieminen a écrit :
>> The C version is not type safe, cannot be expanded with new types,
>
> In C++ you have to overload the operator << as far as I remember. In C
> you have to write a "Print_XXX" function. I do not see why C++ is so
> fundamentally better.

How would you use Print_XXX in a class or function template? Even
outside of a template, being able to output the contents of an object
without having to look up each member's type is a bonus. Let the
compiler do the lookup and avoid the inevitable human errors.

As for the iostream formatting, yes, it is a mess!

> But I am afraid you will never be convinced (of course). Do as you wish,
> but stop denigrating other computer languages that can be used as
> effectively as C++.
>
> Since its birth, C++ tried to be the "better C", "C with classes"
> whatever. That is why it is fundamental for them to denigrate C to
> convince everyone that C++ is the "better way".

None of the C++ programmers I know "denigrate C". Most of them are also
C programmers would happily use C string formatting functions where
appropriate.

> When I try to discuss a package I wrote ( a C containers library) in
> comp.lang.c hordes of C++ people go there to "preach the good word" and
> tell me that what I did (and run every day) is "impossible, I am lying C
> can't do that" etc.

Care to quote one? I didn't see any. Constructive criticism for sure,
but nothing about you lying.

> Just stop denigrating C.

Just stop interpreting all critical comments as personal attacks.

--
Ian Collins

Barry Schwarz

unread,
Feb 24, 2014, 2:25:41 PM2/24/14
to
On Sun, 23 Feb 2014 05:57:28 -0800 (PST), James Kanze
<james...@gmail.com> wrote:

>On Friday, February 21, 2014 6:00:10 AM UTC, robert...@yahoo.com wrote:
>> On Thu, 20 Feb 2014 17:25:50 -0700, mrc...@cox.net (Mike Copeland)
>> wrote:
>
>> > How can I express a large value as a double? (e.g. 1000000.3) Whereas
>> > this compiles and executes, when I try to convert it to a
>> >string value it converts as a scientific string (e.g. "1e+006", not
>> >"1000000.3"). I want to process all the characters of the value of the data
>> >as a std::string. Or is there a way to convert the double to assure it's
>> >not expressed in scientific notation? TIA
>
>> Doubles are floating point and are inherently "in" scientific
>> notation.
>
>No. Scientific notation, like pratically all other text
>formats, is base 10. None of the floating point formats I know
>of that are in use today are base 10. And the way machine
>floating point typically represents the exponent is not
>scientific notation either.

IBM has been and is still selling machines with decimal floating point
built into the hardware. In fact, they have three floating point
formats that the user can choose to use.

--
Remove del for email

jacob navia

unread,
Feb 24, 2014, 3:14:34 PM2/24/14
to
Le 24/02/2014 17:10, Martin Shobe a écrit :
> Unintuitive, certainly.
Well that is the point

Overloading should help the reader better undrestand what the program is
doing.

When you can "add" two strings and an integer the reader must be forced
to understand what is being added. Obviously for many people here it is
SO OBVIOUS that this counterintuitive behavior is "normal" that they
can't understand even why someone from outside finds it disconcerting.


jacob navia

unread,
Feb 24, 2014, 3:18:14 PM2/24/14
to
Le 24/02/2014 16:43, Wouter van Ooijen a écrit :
> jacob navia schreef op 24-Feb-14 4:28 PM:
> > Solution 1: (preferred)
> > -----------------------
> > int strcatMany(char *first,...);
> >
> > calling sequence:
> >
> > strcatMany(a,b,c,NULL);
>
> strcatMany( a, b, c );

actually
c = strcatMany(a,b,NULL);
>
> :(
>
> Wouter van Ooijen
>
> PS Jacob, why are you hanging out of a C++ forum?
>

I read it often, I am not a religious person that believes that because
I use (and like) C other languages are all bad. C++ is an interesting
language. What is a pity is that in these forums no real discussion (in
the sense of exchanging arguments, learning from each other's opinion)
seems possible since people here are very "religious" about "their"
language, as you would expect in a political forum.

Victor Bazarov

unread,
Feb 24, 2014, 3:40:52 PM2/24/14
to
On 2/24/2014 3:18 PM, jacob navia wrote:
> Le 24/02/2014 16:43, Wouter van Ooijen a écrit :
>> jacob navia schreef op 24-Feb-14 4:28 PM:
>> > Solution 1: (preferred)
>> > -----------------------
>> > int strcatMany(char *first,...);
>> >
>> > calling sequence:
>> >
>> > strcatMany(a,b,c,NULL);
>>
>> strcatMany( a, b, c );
>
> actually
> c = strcatMany(a,b,NULL);

What Wouter wrote was to show you that to make a mistake using the
"preferred" form is just as easy as with the other form, and it's just
as _undiagnosable_.

While *printf functions are so common that some compilers now have a
mechanism to attempt argument matching and warn you in case you use the
wrong format specification, any other function that uses ellipsis is
*not* subjected to the same scrutiny and as such is an almost assured
source of hard to identify mistakes.

>>
>> :(
>>
>> Wouter van Ooijen
>>
>> PS Jacob, why are you hanging out of a C++ forum?
>>
>
> I read it often, I am not a religious person that believes that because
> I use (and like) C other languages are all bad. C++ is an interesting
> language. What is a pity is that in these forums no real discussion (in
> the sense of exchanging arguments, learning from each other's opinion)
> seems possible since people here are very "religious" about "their"
> language, as you would expect in a political forum.
>

jacob navia

unread,
Feb 24, 2014, 4:05:44 PM2/24/14
to
Le 24/02/2014 21:40, Victor Bazarov a écrit :
> What Wouter wrote was to show you that to make a mistake using the
> "preferred" form is just as easy as with the other form, and it's just
> as _undiagnosable_.
Yes.

There is no way to specify a list of arguments of the same type in C (or
in C++ for that matter).

So, that could crash.

Contrary to what many people here believe, I do not think that a trivial
error like that is very difficult to solve/fix/find.

Yes, it is a PITA, as all bugs, but not as bad as MANY other bugs that
can happen also with the overloaded functions. For instance typing a
wrong variable name in a function call, etc. The compiler can warn you
if the type is wrong, but if it is right that is also

_undiagnosable_

Let's face it, the perfect compiler/language combination doesn't exist.

My point was that operator overloading is NOT the best paradigm for
output formatting, to come back to the original discussion. The C
paradigm in *that* case is (for the time being) much better.

C gives you a mini-language and a fast run time interpreter for it. This
is a very fast and flexible solution that can be used in the C++
context. It wouldn't be very hard to figure out a standard way of
expanding the mini-language with wild cards that would give it the
possibility of formatting arrays/ new types/ etc.

But no, C++ got driven away from sanity by an initial WRONG DESIGN
DECISION that persists to this day.

That's all I am saying.

Printf extensions have been proposed and implemented. The trio printf
proposed array formatting for instance. Having implemented printf in my
compiler system I find the whole idea simple yet incredibly powerful.

Like the C language. A simple yet powerful language.

It would be more productive for everyone if C++recognized that design
mistake and would work towards a better implementation of output
formatting (maybe) using that simple idea:

A simple and small formatting LANGUAGE and an associated run time
interpreter.

Thanks for your attention.

Message has been deleted

Robert Wessel

unread,
Feb 24, 2014, 4:49:33 PM2/24/14
to
On Mon, 24 Feb 2014 14:47:39 GMT, sc...@slp53.sl.home (Scott Lurndal)
wrote:

>James Kanze <james...@gmail.com> writes:
>>On Saturday, February 22, 2014 1:28:32 AM UTC, robert...@yahoo.com wrote:
>>
>>> Attempting to use FP to represent currency is fundamentally doomed to
>>> failure.
>>
>>That depends on what you are doing. If you're doing
>>risk analysis on futures contracts, for example, it's
>>perfectly appropriate (and you probably can't afford
>>the loss of performance a decimal solution would cost
>
>Actually, scaled binary integers are probably the best
>bet for this (given 64-bit integers). Performs better
>than FP and no binary FP nonrepresentability issues.
>
>Scale everything to mils and work accordingly.


While 64 bit are enough for almost all stored currency values, they're
not enough for intermediate results. Consider multiplying a dollar
amount (stored in pennies) by a percentage with three digits in front
of, and four digits after, the decimal point. You'll overflow your
intermediate results somewhere around a billion dollars.

The Cobol folks, who, if nothing else, care about currency, have long
required longer intermediates. And FWIW, recent standards have
increased the minimum number of decimal digits supported in a number
from 18 to 36 (and those limits are independent of representation - an
implementation could implement 128 bit binary numbers, or 19 byte
packed numbers, or both, to support that).


>>you). After all, any rounding errors will be much
>>less than the variance of the Monte Carlo simulation
>>anyway.
>>
>>If you're doing anything even closely related to
>>legally required bookkeeping, however (and I would
>>imagine writing checks comes into that providence),
>>then using machine floating point is probably illegal,
>>and could, in many jurisdictions, send you to jail.
>>
>>Note that I say "machine floating point", and not just
>
>Note that several (now rare) processor architectures
>included hardware support for decimal floating point. These
>were the architectures used by banks and other financial
>institutions (Burroughs (V-series), IBM (zSeries, pSeries),
>et alia.)


I think there were a couple of *really* old IBM architectures that
supported decimal FP, but most of IBM's pre-360 machines were either
binary FP or decimal fixed point (depending on their target market).
S/360 has always supported fixed point decimal. Z and POWER have
fairly recently added IEEE decimal FP support. Fujitsu recently
announced SPARC 64 X also adds IEEE decimal FP.

IEEE binary FP is defined in such a way that you can actually use it
in a mostly non-FP way so long as the values don't get too large.

Ian Collins

unread,
Feb 24, 2014, 4:57:16 PM2/24/14
to
jacob navia wrote:
>
> My point was that operator overloading is NOT the best paradigm for
> output formatting, to come back to the original discussion. The C
> paradigm in *that* case is (for the time being) much better.

In some contexts it is, in generic (template) code it's pretty useless.

> C gives you a mini-language and a fast run time interpreter for it. This
> is a very fast and flexible solution that can be used in the C++
> context. It wouldn't be very hard to figure out a standard way of
> expanding the mini-language with wild cards that would give it the
> possibility of formatting arrays/ new types/ etc.

The still doesn't address the template case, a topic you appear very
keen to avoid discussing.

--
Ian Collins

Robert Wessel

unread,
Feb 24, 2014, 5:04:18 PM2/24/14
to
On Mon, 24 Feb 2014 22:05:44 +0100, jacob navia <ja...@spamsink.net>
wrote:
I don't think anyone really thinks C++ streams are pretty. IMO,
they're darn ugly. And overloading the shift operators is at least a
little perverse. OTOH, the shift operators as such are fairly rare in
code, so while a new operator might have been a bit better, it's
really not that big a deal.

OTOH, streams *are* type safe and extensible (please don't bother
reiterating your argument that many compilers add partial type safety
to the printf functions, I've heard you, and, IMO, the argument is
insufficient, but we're unlikely to convince each other).

But type safety and extensibility are important, and better mechanism
needs to support both, or it will pretty much be flatly rejected. That
makes it difficult to hand too much function off to a runtime format
interpreter. Something like boost::format is likely to get a much
better reception.

Victor Bazarov

unread,
Feb 24, 2014, 5:05:44 PM2/24/14
to
On 2/24/2014 4:05 PM, jacob navia wrote:
> [..]
> Printf extensions have been proposed and implemented. The trio printf
> proposed array formatting for instance. Having implemented printf in my
> compiler system I find the whole idea simple yet incredibly powerful.
>
> Like the C language. A simple yet powerful language.

<sigh> I suppose you have a point somewhere here. I just can't seem to
figure out what it is.

> It would be more productive for everyone if C++recognized that design
> mistake

<shrug> You keep saying it as if repeating it somehow makes it true.

> and would work towards a better implementation of output
> formatting (maybe) using that simple idea:
>
> A simple and small formatting LANGUAGE and an associated run time
> interpreter.

First off, if you don't like (or don't understand, don't trust, don't
feel comfortable with) the mechanisms C++ *adds* to provide standard
output, don't use them. There is no law in the land that says that you
*must* use standard ostream object for formatted output. Just like *if*
you think that manual transmission in an automobile is superior to
automatic, then nobody forces you to drive automatic. It's a choice.
You've made it. Just stop trying to prove that it's the *only right way*.

And if you want to sustain the argument, start *listening*. You need to
(a) refute the claims others have made about the advantages of the
type-safe system before the other party will consider your own claims of
the advantage of the C way and (b) support your claims of the
superiority of the C way with *real* arguments, not your feelings or how
many people have been using it.

Second, C++ does not preclude you from using 'printf' for your needs.
The family of those interpreter functions *is* a part of C++ Standard
library. Not its best part, by any means, and those who understand
*why* it is so, use it with caution, but hey, nobody can tell you what
to do, right? Throw the caution into the wind!

Third, if some kind of special language similar to what 'printf' uses is
appealing to you, just *create one* for your purposes. C++ makes such
extension relatively easy (probably easier than C, although I've not
attempted to implement it to the full extent in either language). And
if others find your mechanism somehow satisfying the requirements that
are important to them and see how it fixes the deficiencies of *both*
'std::ostream' *and* 'printf', they will want to use it too. *That*
what will shut everybody up, not your praises to C and unsubstantiated
claims of 'printf' superiority.

> Thanks for your attention.

If it helps, you're welcome. I doubt it, though, I'm sorry to say.

woodb...@gmail.com

unread,
Feb 24, 2014, 5:08:38 PM2/24/14
to
On Monday, February 24, 2014 8:14:03 AM UTC-6, jacob navia wrote:
>
> What bothers me precisely is this lack of respect from C++ programmers
> that believe that because they have mastered some c++ trivialities they
> are better than people that do not care about them.
>
> Look at how java programmers are laughed at here. Or Fortran
> programmers, or whatever. It is this attitude, this lack of respect that
> I question.
>


Here's my ranking:

C++ programmers
Fortran programmers
Java Programmers

Years ago I felt a little bit left behind cause
I wasn't getting high on Java. Now it's clear
I wasn't missing anything.

Brian
Ebenezer Enterprises - John 3:16.
http://webEbenezer.net

jacob navia

unread,
Feb 24, 2014, 5:39:34 PM2/24/14
to
Le 24/02/2014 22:57, Ian Collins a écrit :
> The still doesn't address the template case, a topic you appear very
> keen to avoid discussing.

One way of addressing this is to have a set of elements that represent
the formatting string for each elementary type as in C. (The PRIxXX macros)

Since we have typeof(x) we could also have printtypeof(x) or a similar
construct.

For instance you can write:

printf("The integer is" PRId64 "\n",intvar);

Now, the string behind this macro PRId64 could be then the result of a
computation, i.e. some type-based property that can be determined when
the template is being expanded, a "basic" property that could be further
customized within the intepreter language to have a maximum width, a
"precision" equivalent, whatever.

As with constructors and destructors, each class/struct type can have
easily a printed representation provided by default by the compiler. You
just print the basic types forming the aggregate separated by a single
space. That would be the default printed representation. You can write
your own fancy one as with constructors, copy-constructors, etc.

Note that a default printed representation of a type would go a long way
to easing serialization problems. But this is a disgression.

Of course this is a complex task that shouldn't be done by somebody like
me but by an expert group that pushes the idea of a mini *language* and
a run time interpreter further. The goals could be:

* concise
* extensible
* reasonable defaults for the basic types.
* SIMPLE, not much beyond a sophisticated printf! C++ people have a
tendency to complexify everything until nobody understands anything but
the people that wrote the specs :-)

When defining a class you would add (if you want) a string for the
format interpreter. If you don't the compiler adds the default for the type.

It could be possible also to add other formatting characteristics to the
system since we are no longer in the time of 80 characters green and
black 3270 terminals... Characteristics like colour, bold, italic, for
instance something the C++ system (and the C also) do NOT do today in 2014!

THAT would be a real progress in formatting your output isn't it?

For such a SIMPLE thing like outputting text in red we have now to get
into completely unportable stuff. Why?

printf("%__red__bold %s\n","WRONG!");
printf("%__green__italic %s\n", "OK. Let's go on\n");

The gcc compiler manages to do that for its error messages in the
Macintosh. It would be nice if user programs would benefit also. And
please, this is not really NEW technology isn't it?

The material basis for doing that is at least 30 years old. (Termcap
data base, bit mapped screens)

Thanks for your attention Ian.




Miami_Vice

unread,
Feb 24, 2014, 5:44:16 PM2/24/14
to
On Friday, February 21, 2014 12:25:50 AM UTC, Mike Copeland wrote:
> How can I express a large value as a double? (e.g. 1000000.3)
>
> Whereas this compiles and executes, when I try to convert it to a
>
> string value it converts as a scientific string (e.g. "1e+006", not
>
> "1000000.3"). I want to process all the characters of the value of the
>
> data as a std::string.
>
> Or is there a way to convert the double to assure it's not expressed
>
> in scientific notation? TIA
>
>
>
> ---
>
> This email is free from viruses and malware because avast! Antivirus protection is active.
>
> http://www.avast.com

You have to use <iomanip> as suggested by the solution by Paavo Helde.
Message has been deleted

jacob navia

unread,
Feb 24, 2014, 5:50:46 PM2/24/14
to
Le 24/02/2014 23:05, Victor Bazarov a écrit :
> I suppose you have a point somewhere here. I just can't seem to figure
> out what it is.

See my answer to Mr Ian Collins in this same thread. Thanks

Dombo

unread,
Feb 24, 2014, 6:39:16 PM2/24/14
to
Op 24-Feb-14 15:30, jacob navia schreef:
> Le 24/02/2014 15:14, Victor Bazarov a écrit :
>> Perhaps you can read more about overloading, it's one important feature
>> of C++ that sets it aside from C.
>
> I have implemented function overloading in my compiler system lcc-win.
> And true, I have read a lot of things about overloading, and also about
> how overloading (like anything) can be ABUSED.
>
> For example, the expression
>
> String a,b,c;
> c = a+b;
>
> is an *abuse* of overloading.
>
> Why?
>
> Because there is no ADDITION being done when a and b are STRINGS but a
> concatenation of two strings, what is *completely different*. If a and b
> are strings we have
>
> a+b != b+a
>
> what goes against all the mathematical basis of addition as normal
> people use that word.

In many programming languages, including C, one can write: a=a+1;
From the mathematical perspective that is just nonsense.

In C or C++ one could write a while loop like this:

int a = 10;
while(a=a-1)
{
printf("%d", a);
}

Using the mathematical notation semantics statements inside the loop
should never be executed because a never equals a-1, thus the expression
a=a-1 should always be evaluated as being false.

The point I'm trying to make here that the syntax of a programming
language should not be confused with mathematical notation; there is
little point in assuming the same semantics for a given expression.

IMO a good programming language should allow common operations to be
expressed as clearly and as concisely as reasonably possible. I think
very few software engineers will have trouble understanding what your
string example does, regardless of the programming languages they know.
Rewrite the the same code using just C functions, including those needed
for the memory allocation and freeing, and chances are that people
without a C background are struggling to understand what the code does,
and even people proficient in C would likely need more time to
understand the code.

Overloading in general (not necessarily operator overloading) has the
benefit that it makes it a lot easier to write generic (template) code.
When postfixes are added to the function name to differentiate between
parameter types, there is no real practical way to use them in template
functions or -classes. Even if you (or whoever is using your functions)
don't use templates, overloading still has the benefit that it relieves
the user of the function from worrying about types and having to
memorize the postfixed names; just pass the parameter and let the
compiler figure out which function to call.

Truth to be told I do dislike the iostream syntax. I do like its type
safety, extendability and the flexibility where the output goes to (or
the input comes from). But when it comes to formatting iostream just
sucks IHMO, as clearly demonstrated by your example. As far as
formatting is concerned I would have liked to see C and C++ meet
somewhere in the middle; e.g. like the approach chosen by the Boost
Format library.





Message has been deleted

jacob navia

unread,
Feb 24, 2014, 6:52:13 PM2/24/14
to
Le 25/02/2014 00:39, Dombo a écrit :
> while(a=a-1)
> {
> printf("%d", a);
> }
>
> Using the mathematical notation semantics statements inside the loop
> should never be executed because a never equals a-1

As you know the equality operator is "==" and NOT "=" that means store
the right hand side in the left hand side...

All your reasoning should have been done with

a == a-1

and I would be really surprised if THAT would be true in some machine :-)

The discussion is about overusing overloading for output, and I think
most participants agree that it is a PITA. Now, could a "printf" based
approach: a (mini) "language" and a run time interpreter/formatter be
better suited to output than an overloaded operator?

That is my point.

Robert Wessel

unread,
Feb 24, 2014, 7:08:09 PM2/24/14
to
On Tue, 25 Feb 2014 00:52:13 +0100, jacob navia <ja...@spamsink.net>
wrote:

>Le 25/02/2014 00:39, Dombo a écrit :
>> while(a=a-1)
>> {
>> printf("%d", a);
>> }
>>
>> Using the mathematical notation semantics statements inside the loop
>> should never be executed because a never equals a-1
>
>As you know the equality operator is "==" and NOT "=" that means store
>the right hand side in the left hand side...
>
>All your reasoning should have been done with
>
> a == a-1
>
>and I would be really surprised if THAT would be true in some machine :-)


On most implementations:

double a=1e30;
if (a == a-1)
printf("would be true!\n");

Ian Collins

unread,
Feb 24, 2014, 8:09:58 PM2/24/14
to
jacob navia wrote:
> Le 24/02/2014 22:57, Ian Collins a écrit :
>> The still doesn't address the template case, a topic you appear very
>> keen to avoid discussing.
>
> One way of addressing this is to have a set of elements that represent
> the formatting string for each elementary type as in C. (The PRIxXX macros)
>
> Since we have typeof(x) we could also have printtypeof(x) or a similar
> construct.
>
> For instance you can write:
>
> printf("The integer is" PRId64 "\n",intvar);

I've had some interesting discussions on (C) project mail lists
regarding PRIxXX macros. I was trying to encourage people to use them,
but most of the developers found them "too ugly". I lost..

> Now, the string behind this macro PRId64 could be then the result of a
> computation, i.e. some type-based property that can be determined when
> the template is being expanded, a "basic" property that could be further
> customized within the intepreter language to have a maximum width, a
> "precision" equivalent, whatever.
>
> As with constructors and destructors, each class/struct type can have
> easily a printed representation provided by default by the compiler. You
> just print the basic types forming the aggregate separated by a single
> space. That would be the default printed representation. You can write
> your own fancy one as with constructors, copy-constructors, etc.

I can see this working in simple cases, but not for a class that
specialised output formatting (anything which currently has a
non-trivial output operator). What does the "fancy" specifier offer
over the current (admittedly not great) streaming operators? Yes it
could be made type safe with the compiler spotting a mismatch between
the specifier and the type, but why not let the compiler do this for you
as it does now?

You would lose (or at lease make even more ugly) one of the useful
features of streaming: chaining.

> Note that a default printed representation of a type would go a long way
> to easing serialization problems. But this is a disgression.

Indeed it would..

> Of course this is a complex task that shouldn't be done by somebody like
> me but by an expert group that pushes the idea of a mini *language* and
> a run time interpreter further. The goals could be:
>
> * concise
> * extensible
> * reasonable defaults for the basic types.
> * SIMPLE, not much beyond a sophisticated printf! C++ people have a
> tendency to complexify everything until nobody understands anything but
> the people that wrote the specs :-)
>
> When defining a class you would add (if you want) a string for the
> format interpreter. If you don't the compiler adds the default for the type.
>
> It could be possible also to add other formatting characteristics to the
> system since we are no longer in the time of 80 characters green and
> black 3270 terminals... Characteristics like colour, bold, italic, for
> instance something the C++ system (and the C also) do NOT do today in 2014!
>
> THAT would be a real progress in formatting your output isn't it?

Real progress is typified by the separation of presentation from the
data, CSS + HTML for example.

--
Ian Collins

Ike Naar

unread,
Feb 25, 2014, 1:45:41 AM2/25/14
to
On 2014-02-24, jacob navia <ja...@spamsink.net> wrote:
> Le 24/02/2014 16:43, Wouter van Ooijen a ?crit :
>> jacob navia schreef op 24-Feb-14 4:28 PM:
>> > Solution 1: (preferred)
>> > -----------------------
>> > int strcatMany(char *first,...);
>> >
>> > calling sequence:
>> >
>> > strcatMany(a,b,c,NULL);
>>
>> strcatMany( a, b, c );
>
> actually
> c = strcatMany(a,b,NULL);

What's the type of c in the line above?
(Note that strcatMany returns an int).

Scott Lurndal

unread,
Feb 25, 2014, 9:41:41 AM2/25/14
to
I think one might argue that type-safety is a red-herring in the
snprintf case, but YMMV.

Scott Lurndal

unread,
Feb 25, 2014, 9:45:38 AM2/25/14
to
The system that I first did OS development work on supported 100 digit
intermediaries for COBOL (hardware BCD, addressed to the digit/nibble).

http://vseries.lurndal.org/doku.php

Isn't your example (233.5555%) a bit contrived?


>I think there were a couple of *really* old IBM architectures that
>supported decimal FP, but most of IBM's pre-360 machines were either

Well, most of them supported decimal _fixed point_, not floating point.

They were business machines after all, not scientific (although the 360's
were abused for that purpose - which is why IBM had optional binary
floating point functionality).

Scott Lurndal

unread,
Feb 25, 2014, 9:49:19 AM2/25/14
to
woodb...@gmail.com writes:
>On Monday, February 24, 2014 8:14:03 AM UTC-6, jacob navia wrote:
>>
>> What bothers me precisely is this lack of respect from C++ programmers
>> that believe that because they have mastered some c++ trivialities they
>> are better than people that do not care about them.
>>
>> Look at how java programmers are laughed at here. Or Fortran
>> programmers, or whatever. It is this attitude, this lack of respect that
>> I question.
>>
>
>
>Here's my ranking:
>
>C++ programmers
>Fortran programmers
>Java Programmers
>

That's pretty silly, ranking programmers by language instead of by
ability to produce a viable program regardless of the language. Good
programmers don't really care which language they use, they use the
proper language for the problem.

It would be quite odd for someone to write a servlet in C++, when
one can do it much more rapidly, efficiently and correctly in Java, for example.

Python, perl, ruby, Fortran, Assembler, Visual Basic all have their
niche.

>Years ago I felt a little bit left behind cause
>I wasn't getting high on Java. Now it's clear
>I wasn't missing anything.

A strange paragraph, to be sure.

Gerhard Fiedler

unread,
Feb 25, 2014, 1:27:38 PM2/25/14
to
Scott Lurndal wrote:

> Gerhard Fiedler <gel...@gmail.com> writes:
>>OTOH, (type-safely) encapsulating printf is quite the challenge.
>
> See, that's the C++ programmer view. A real programmer will use ...

This sounds as if you think that a C++ programmer is not a real
programmer :)

> ... snprintf when and where it makes sense ...

Sure... I thought that was a given.

> ... and not worry about "encapsulating" it ...

Well, when programming, I rarely think in single programming lines but
more about bigger concepts. And there, "encapsulation" is always
important, no matter the language.

> ... and doesn't care about spurious "language purity".

That idea of "language purity" seems to be yours; it definitely wasn't
part of my post. Does that make you an "unreal" programmer? :)


> examples from C++ operating system:

Not sure what a "C++ operating system" is. But I do understand (and
occasionally use) the printf-family of functions, if that was the point.

> Letting the compiler check arguments, even on user-defined functions
> is trivial with a good compiler:

Try letting the compiler check the argument types when using a variable
as formatting string.

Gerhard

Scott Lurndal

unread,
Feb 25, 2014, 2:21:15 PM2/25/14
to
Gerhard Fiedler <gel...@gmail.com> writes:

>Try letting the compiler check the argument types when using a variable
>as formatting string.

I've never seen a case where it makes sense to use a variable as a
formatting string[*]. Can you describe a case where it does make sense
and it doesn't cause a potential security problem?

[*] absent a wrapper function that uses __attribute__((printf(x,y))), anyway.

Victor Bazarov

unread,
Feb 25, 2014, 3:07:18 PM2/25/14
to
On 2/25/2014 2:21 PM, Scott Lurndal wrote:
> Gerhard Fiedler <gel...@gmail.com> writes:
>
>> Try letting the compiler check the argument types when using a variable
>> as formatting string.
>
> I've never seen a case where it makes sense to use a variable as a
> formatting string[*]. Can you describe a case where it does make sense
> and it doesn't cause a potential security problem?

<shrug> All you need to imagine is selection between different formats
based on a run-time expression, like

const char* fmt[] = { "%d", "%p", "%s" };
...
int i = some_runtime_value;
...
printf(fmt[i % (sizeof(fmt)/sizeof(*fmt))], whatever);

What security problem do you see here?

> [*] absent a wrapper function that uses __attribute__((printf(x,y))), anyway.

Dombo

unread,
Feb 25, 2014, 3:38:17 PM2/25/14
to
Op 25-Feb-14 0:52, jacob navia schreef:
> Le 25/02/2014 00:39, Dombo a écrit :
>> while(a=a-1)
>> {
>> printf("%d", a);
>> }
>>
>> Using the mathematical notation semantics statements inside the loop
>> should never be executed because a never equals a-1
>
> As you know the equality operator is "==" and NOT "=" that means store
> the right hand side in the left hand side...

In C it is, not in mathematical notation. So how come you could easily
make this distinction in this example, but not in case of your string
example?

> The discussion is about overusing overloading for output, and I think
> most participants agree that it is a PITA.

If have no problems with the use of function overloading for output, in
fact I believe it is a good choice since it allows it to be extended
transparently for the user. That doesn't mean I particularly like the
overloading of the << operator (minor gripe) or how iostreams deals with
formatting (big gripe).

> Now, could a "printf" based
> approach: a (mini) "language" and a run time interpreter/formatter be
> better suited to output than an overloaded operator?
>
> That is my point.

Why a runtime interpreter? I'd much rather see as much as reasonably can
be done at compile time, including checks and with type safety. The
Boost Format library seems to be a nice compromise between the ease of
formatting of printf and the extendability, type safety and flexibility
of the iostreams.

Ian Collins

unread,
Feb 25, 2014, 3:39:11 PM2/25/14
to
Scott Lurndal wrote:
> Gerhard Fiedler <gel...@gmail.com> writes:
>
>> Try letting the compiler check the argument types when using a variable
>> as formatting string.
>
> I've never seen a case where it makes sense to use a variable as a
> formatting string[*]. Can you describe a case where it does make sense
> and it doesn't cause a potential security problem?

Simple internationalisation. I've worked on embedded projects where we
used different sets of format strings for different languages. No
security risks there.

> [*] absent a wrapper function that uses __attribute__((printf(x,y))), anyway.

Where is that defined in the C++ standard?

--
Ian Collins

David Brown

unread,
Feb 25, 2014, 5:33:13 PM2/25/14
to
On 25/02/14 21:39, Ian Collins wrote:
> Scott Lurndal wrote:
>> Gerhard Fiedler <gel...@gmail.com> writes:
>>
>>> Try letting the compiler check the argument types when using a variable
>>> as formatting string.
>>
>> I've never seen a case where it makes sense to use a variable as a
>> formatting string[*]. Can you describe a case where it does make sense
>> and it doesn't cause a potential security problem?
>
> Simple internationalisation. I've worked on embedded projects where we
> used different sets of format strings for different languages. No
> security risks there.

That would be my thought. You might have something like this:

typedef enum { formatUK, formatUS } dateFormatChoices;
static const char dateFormatStrings[] = {
"%1$02d/%2$02d/%3$04d", "%2$02d/%1$02d/%3$04d"
}
void printDate(dateFormatChoices i, int day, int month, int year) {
printf(dateFormatStrings[i], day, month, year);
}

(That particular example relies on posix printf with parameters - if you
can't re-arrange parameter order like that, variable format strings are,
I think, significantly less useful.)

Robert Wessel

unread,
Feb 25, 2014, 7:42:53 PM2/25/14
to
On Tue, 25 Feb 2014 14:45:38 GMT, sc...@slp53.sl.home (Scott Lurndal)
All simple examples are contrived.

But not that much. A fairly simple requirement (multiply a currency
value by a percentage), with not unreasonable ranges, leads to
overflow problems on not unreasonable inputs. Admittedly in most real
multiplications by percentages, you probably have two or three
additional usable digits to play with.


>>I think there were a couple of *really* old IBM architectures that
>>supported decimal FP, but most of IBM's pre-360 machines were either
>
>Well, most of them supported decimal _fixed point_, not floating point.


The 704s and descendents were binary FP, the 7070s had decimal FP.
Many of the commercial machines supported fixed point decimal,
although the 7070s were more in the commercial line, and FP feature
was optional.


>They were business machines after all, not scientific (although the 360's
>were abused for that purpose - which is why IBM had optional binary
>floating point functionality).


It's hard to say that S/360's were "abused" for scientific purposes,
when they were specifically designed to unify both the commercial and
scientific lines of IBM's computers. Specific models were built only
for the scientific community (the four machines in the 91/95/195
groups). You might as well claim that these machines were abused for
commercial purposes leading to IBM having the optional decimal
instructions. Even the chosen name reflects the "all around" purpose
of the machines.

Robert Wessel

unread,
Feb 25, 2014, 7:46:38 PM2/25/14
to
On Wed, 26 Feb 2014 09:39:11 +1300, Ian Collins <ian-...@hotmail.com>
wrote:

>Scott Lurndal wrote:
>> Gerhard Fiedler <gel...@gmail.com> writes:
>>
>>> Try letting the compiler check the argument types when using a variable
>>> as formatting string.
>>
>> I've never seen a case where it makes sense to use a variable as a
>> formatting string[*]. Can you describe a case where it does make sense
>> and it doesn't cause a potential security problem?
>
>Simple internationalisation. I've worked on embedded projects where we
>used different sets of format strings for different languages. No
>security risks there.


Unfortunately the strictly positional nature of the input parameters
in the printf functions has always led us to use our own replacement.

Ian Collins

unread,
Feb 25, 2014, 7:50:23 PM2/25/14
to
David Brown wrote:
> On 25/02/14 21:39, Ian Collins wrote:
>> Scott Lurndal wrote:
>>> Gerhard Fiedler <gel...@gmail.com> writes:
>>>
>>>> Try letting the compiler check the argument types when using a variable
>>>> as formatting string.
>>>
>>> I've never seen a case where it makes sense to use a variable as a
>>> formatting string[*]. Can you describe a case where it does make sense
>>> and it doesn't cause a potential security problem?
>>
>> Simple internationalisation. I've worked on embedded projects where we
>> used different sets of format strings for different languages. No
>> security risks there.
>
> That would be my thought. You might have something like this:
>
> typedef enum { formatUK, formatUS } dateFormatChoices;
> static const char dateFormatStrings[] = {
> "%1$02d/%2$02d/%3$04d", "%2$02d/%1$02d/%3$04d"
> }
> void printDate(dateFormatChoices i, int day, int month, int year) {
> printf(dateFormatStrings[i], day, month, year);
> }
>
> (That particular example relies on posix printf with parameters - if you
> can't re-arrange parameter order like that, variable format strings are,
> I think, significantly less useful.)

The case I was thinking of was a monitoring device that displayed the
name of a unit (such as "Battery Time Remaining") or menu items in the
language selected by the user. Nothing fancy.

--
Ian Collins

Robert Wessel

unread,
Feb 25, 2014, 8:09:10 PM2/25/14
to
On Tue, 25 Feb 2014 14:41:41 GMT, sc...@slp53.sl.home (Scott Lurndal)
wrote:
Just don't use %n...

But seriously, while on (many) systems messing up the match between
the format string and the parameters results in nothing worse than
garbage output (memory overflows on sprintf and the like excepted),
that's still a place where type safety is useful in allowing the
compiler to diagnose that problem.

David Brown

unread,
Feb 26, 2014, 4:09:18 AM2/26/14
to
In cases like that (if I am reading you correctly), for printing a
variable char* p

printf(p);

you could use

printf("%s", p);

That version is arguably safer (it is /definitely/ safer if your strings
come from elsewhere, but I don't expect that applies in your case), and
probably runs faster.

David Brown

unread,
Feb 26, 2014, 4:10:38 AM2/26/14
to
If you've got a posix extended printf, then the input parameters don't
have to be strictly positional (see my example).

Gerhard Fiedler

unread,
Feb 26, 2014, 7:00:00 AM2/26/14
to
Scott Lurndal wrote:

> Gerhard Fiedler <gel...@gmail.com> writes:
>
>> Try letting the compiler check the argument types when using a
>> variable as formatting string.
>
> I've never seen a case where it makes sense to use a variable as a
> formatting string[*]. Can you describe a case where it does make
> sense and it doesn't cause a potential security problem?

Not sure what you call a security problem, but user-selectable output
languages are a pretty common requirement.

Gerhard

Scott Lurndal

unread,
Feb 26, 2014, 9:46:57 AM2/26/14
to
I've seen poorly written software where user-input is provided as the
format string. That's a security problem waiting to happen.

I81n is a legitimate use, in which case the compiler cannot verify
the correctness of the format string with respect to the arguments.

Seungbeom Kim

unread,
Feb 26, 2014, 2:51:37 PM2/26/14
to
On 2014-02-24 06:30, jacob navia wrote:
> Because there is no ADDITION being done when a and b are STRINGS but a
> concatenation of two strings, what is *completely different*. If a and
> b are strings we have
>
> a+b != b+a
>
> what goes against all the mathematical basis of addition as normal
> people use that word.
>
> That is why string "addition" is an ABUSE of overloading.

Mathematical operators do not define the abuse of C++ operator
overloading. If they did,
* '=' as assignment (instead of equality),
* '<<' as left-shift (instead of 'much less than'),
* '%' as remainder (instead of percent), or
* '|' as bitwise OR (instead of 'divides'), etc.
would all be an abuse as well.

> In the same vein, shifting left an object to print it just because the
> opeartor << looks like the head of a left arrow or suggests "put into"
> is NONSENSE and an abuse of the overloading concept.

'<<' is defined both as a left-shift operator and a stream insert
operator in the same document that defines C++. The fact that << is
used for one doesn't automatically make the other usage an abuse.

--
Seungbeom Kim

Jorgen Grahn

unread,
Feb 26, 2014, 5:30:11 PM2/26/14
to
On Mon, 2014-02-24, Wouter van Ooijen wrote:
> jacob navia schreef op 24-Feb-14 3:34 PM:
>> Besides, if you want to support SEVERAL print functions for instance for
>> formatting a customer with name, age or name, SS number, or just
>> initials, etc you will need anyway several print functions in C++ also,
>> if I remember correctly isn't it?
>
> In true C++: if that is what you want it is cetainly possible, just like
> you can have print_xxx functions if you want to.
>
> I think I would prefer to reserve operator<<(person) for (debug)
> printing of ALL data in person, and have separate getters for the items
> that you might want to print, like
>
> std::cout
> << std::setw( 30 ) << person.name()
> << " lives at "
> << std::setw( 60 ) << person.adress();
>
> This keeps *what* you want to print separate from *how* you want to
> print it.

I think what jacob navia is after would be better done as a bunch of
classes which only know how to format a Customer, each in its unique
fashion:

std::cout << ForMailingLabel(some_customer);
std::cout << ForGreetingMessage(some_customer);
std::cout << ForTheNSA(some_customer);

(Sorry about the bad naming; I don't deal with customers so I don't
know what you want to print or why.)

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
It is loading more messages.
0 new messages