C
CBFalconer
Richard said:arnuld said:
.... snip ...
Then stick with snprintf. In fact, stick with Visual Basic.
Now that is unnecessary nasty treatment of a newbie.
Richard said:arnuld said:
.... snip ...
Then stick with snprintf. In fact, stick with Visual Basic.
Nick said:[RCH doesn't seem to like snprintf()]
[I must admit its lack of portability puts me off]
how?
santosh said:Richard Heathfield wrote:
.... snip ...
That's the ideal. But assuming that 'pereges' cannot do that
(since if he could, he obviously wouldn't be misusing getch like
this), getchar provides the behaviour he needs (block just before
return from main) without rendering the code nonportable.
CBFalconer said:He can. He just hasn't learned how.
Perhaps, but teaching him to open a shell is off-topic for this group,
as is getch(), hence the advise to use getchar().
Richard Heathfield said:santosh said: [...]Of course the 'p' specifier throws an additional spanner into the works.
I think it throws a spanner into snprintf's works, too - I could be wrong,
but is there any *obligation* on implementations to choose the same
textual representation for a pointer on every invocation? If not, then
snprintf's "let me tell you how big a buffer you would have needed *this*
time" doesn't really mean a lot where %p is concerned.
Richard said:santosh said:
Okay, so let's take the classic example of unspecified behaviour -
order of evaluation. The Standard doesn't impose an ordering of any
kind, and therefore implicitly provides gazillions of possible
orderings. Implementations are free to do what they like, and don't
have to document it.
By extension, here the Standard provides (possibly a subset of)
infinitely many possibilities, but requires the implementation to
document its choice. For example, for UINT_MAX the Standard requires
that it's an integer constant AND has a value that is at least 65535
AND (IIRC) is a power-of-two-less-one, but that still leaves
infinitely many possibilities.
Implementations are perfectly free to
document this choice along lines such as "if the -foo switch is set,
UINT_MAX is 131071, otherwise if -bar is set it's 262143, otherwise
it's 37778931862957161709567".
For iscntrl, implementations are free
to specify just about anything they like as a control character, and I
can find no prohibition on this choice being made dynamically, as long
as the rules are clearly specified (i.e. the implementation documents
how the choice is made).
3.4
1 behavior
external appearance or action
Here "unspecified value" is not defined, as far as I can see. However
for each instance of unspecified behaviour it seems that the Standard
provides all possible courses of action and the implementation is
merely required to choose one course from this list,
But the Standard may, instead of providing all possible courses of
action, define a rule that places a constraint on the choice (or
several such rules). UINT_MAX is a good example of this. As long as
the implementation obeys those rules, it is free to use further rules
of its own, which need not be static ("the value is X") but could
instead be dynamic ("the value is a consequence of the application of
such-and-such rules with such-and-such parameters, subject to the
[normally minimal] limitations imposed by the Standard").
In light of this interpretation (though I'm sure I've overlooked
something important somewhere),
I think you've overlooked the point that the range of possible
behaviours doesn't actually have to be written down anywhere in the
Standard for it to constitute a valid range. For example, the Standard
doesn't have to say: "The value of UINT_MAX shall be 65535 OR 131071
OR 262143 OR 524287 OR ... [snip infinitely many possibilities]..." -
and a good job too, or it would have to have infinitely many pages.
<snip>
Richard Heathfield said:santosh said:
What's wrong with:
open a shell, find the program, run the program from the shell.
santosh said:Richard Heathfield wrote: [...]Implementations are perfectly free to
document this choice along lines such as "if the -foo switch is set,
UINT_MAX is 131071, otherwise if -bar is set it's 262143, otherwise
it's 37778931862957161709567".
Wouldn't that actually make them three different implementations, in
effect?
But the forms of behaviour must be derivable, or otherwise, it would be
undefined.
So, in view of all this, how is one, as an implementor, to derive the
valid forms of behaviour for the implementation defined output for
the 'p' type specifier in printf? The final choice of the
implementation must be one from a set of 2 to N choices that the
Standard must specify literally or implicitly through it's constraints.
But what constraints can one apply to this case? Any ideas?
Keith said:.... snip ...
There's no portable way to determine the maximum length of the result
of a "%p" *printf conversion.
With snprintf, you can make a reasonable guess. The consequence of
guessing wrong is that the resulting string is truncated, and you can
either accept that or try again with a bigger buffer. Even if you're
given an even bigger string on the second attempt, the consequences
are still no worse than a truncated result.
Richard Heathfield said:Keith Thompson said: [...]With sprintf, you can make a reasonable guess, but the consequence of
guessing wrong is undefined behavior.
If we're allowed a preliminary length-determining operation (as in your
first call to snprintf), we can use fprintf to write the pointer's text
representation to a temporary file and, at the same time, find out how
long it is; then we can seek back in the file and read from the file into
the string. Easy.
No, not really. We can say "our application is required to support values
in such-and-such a range, so we'll do that, and perhaps provide a bit of
leeway, and then we'll treat anything that won't fit as an exception to be
reported upon and investigated, but in the meantime we're not going to
accept it as part of our string". We have to do this anyway for other
reasons - for example, if we're dealing with ages of living humans we
don't bother supporting ages of, say, 1000+ - so we range-check it and use
%3d and don't care that our super-amazing-ints can hold 85-digit values
because we still only spec three bytes for the text rep of the age value.
(Yes, I know we need one more for the null character.) If we come across
an age of 1000+, we flag that record as needing attention and we move on
to other things /without/ printing it.
Um, sure. It seems unlikely that anyone would do that in real-world
code.
Creating a new file is likely to have have substantially
greater overhead than whatever in-memory formatting is done for "%p".
Using fprintf to write to a temporary file is one of those solutions
that's 100% portable rather than 99.9% portable, but at the cost of
substantial performance penalties.
Keith Thompson said:
If we're allowed a preliminary length-determining operation (as in your
first call to snprintf), we can use fprintf to write the pointer's text
representation to a temporary file and, at the same time, find out how
long it is; then we can seek back in the file and read from the file into
the string. Easy.
No, not really. We can say "our application is required to support values
in such-and-such a range, so we'll do that, and perhaps provide a bit of
leeway, and then we'll treat anything that won't fit as an exception to be
reported upon and investigated, but in the meantime we're not going to
accept it as part of our string". We have to do this anyway for other
reasons - for example, if we're dealing with ages of living humans we
don't bother supporting ages of, say, 1000+ - so we range-check it and use
%3d and don't care that our super-amazing-ints can hold 85-digit values
because we still only spec three bytes for the text rep of the age value.
(Yes, I know we need one more for the null character.) If we come across
an age of 1000+, we flag that record as needing attention and we move on
to other things /without/ printing it.
CBFalconer said:Keith Thompson wrote:
... snip ...
I disagree, and published the following elsethread:
Assuming the parameters specifying the elements to be printed do
not change between the calls, call snprintf twice. The first time
replace the string with NULL and the size with 0. The returned
value will specify how many chars are needed. Add 1 (for the '\0'
mark), find or make a buffer with that space, and do the second
call.
If the items are likely to change between calls, copy them to
appropriate locations first. Then check and print from those.
^^^^^^^^Nick said:[RCH doesn't seem to like snprintf()]
[I must admit its lack of portability puts me off]
What's non-portable? It is specified in the C99 standard.how?
Assuming the parameters specifying the elements to be printed do
not change between the calls, call snprintf twice.
Keith said:Right, but I'm not sure what you're disagreeing with.
Martien said:^^^^^^^^
I think you may have missed the point of the question.
CBFalconer said:You can always replace the second call to snprintf with a call to
sprintf. The method answers Mr Keighleys 'how' response.
santosh said:CBFalconer wrote:
.... snip ...
I think that Nick Keighley was questioning how one would determine
the storage needed in the *absence* of snprintf (this is because
Richard Heathfield's numbered points were explaining the steps
necessary to correctly use sprintf, which implies that snprintf is
not available for use, for one reason or another.) And the answer
was given by Richard earlier in the thread: use fprintf with a
temporary file and read back the characters written (and match
with the return value to be doubly sure), then allocate the
necessary storage for sprintf.
CBFalconer said:In that case I suggest using the %n feature in the format string.
Want to reply to this thread or ask your own question?
You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.