By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,088 Members | 1,501 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,088 IT Pros & Developers. It's quick & easy.

right padding

P: n/a
Hello,

Is it possible to right pad with "0" (or other character != blank) ?
for example :
1 , length 10 ="1000000000"
I've tried with sprintf but I can only left pad with "0" or right pad
with blanks =>
"0000000001"
"1 "

Thanks.
Oct 21 '08 #1
Share this Question
Share on Google+
52 Replies


P: n/a
marc said:
Hello,

Is it possible to right pad with "0" (or other character != blank) ?
for example :
1 , length 10 ="1000000000"
I've tried with sprintf but I can only left pad with "0" or right pad
with blanks =>
"0000000001"
"1 "
sprintf doesn't let you choose the padding character. But it's pretty easy
to write a function to do the padding for you:

#include <stdio.h>
#include <assert.h>
#include <limits.h>

char *pad(char *s, int n, size_t width, int padch)
{
int count = 0;
char *t = s;
assert(width (sizeof n * CHAR_BIT + 5) / 3);
count = sprintf(t, "%d", n);
t += count;
while(count < len)
{
*t++ = padch;
}
*t = '\0';
return s;
}

In keeping with the spirit of comp.lang.c, the above is untested (because
I'm in a hurry).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 21 '08 #2

P: n/a
On Oct 21, 4:17*am, Richard Heathfield <rj*@see.sig.invalidwrote:
marc said:
Hello,
Is it possible to right pad with "0" (or other character != blank) ?
for example :
1 , length 10 ="1000000000"
I've tried with sprintf but I can only left pad with "0" or right pad
with blanks =>
"0000000001"
"1 * * * * "

sprintf doesn't let you choose the padding character. But it's pretty easy
to write a function to do the padding for you:

#include <stdio.h>
#include <assert.h>
#include <limits.h>

char *pad(char *s, int n, size_t width, int padch)
{
* int count = 0;
* char *t = s;
* assert(width (sizeof n * CHAR_BIT + 5) / 3);
What's the purpose of this? Let's say that int is four bytes long. The
expression on the right side of the '>' will yield 37 / 3 (12). What
does 'width' represent? (You aren't using it anywhere else in the
function.)
* count = sprintf(t, "%d", n);
* t += count;
* while(count < len)
'len' is undefined.
* {
* * *t++ = padch;
* }
And that will yield an infinite loop.
* *t = '\0';
* return s;

}

In keeping with the spirit of comp.lang.c, the above is untested (because
I'm in a hurry).
Here's a safer and tested version:

char *PadSnprintf(char *str, // the buffer
int n, // sizeof(str)
int item, // the item to convert
char paddingChar) // the padding character
{
snprintf(str, n, "%d", item);

char *p = str + strlen(str);
while (p < str + n - 1)
*p++ = paddingChar;

*p = '\0';
return str;
}

Sebastian

Oct 21 '08 #3

P: n/a
s0****@gmail.com said:
On Oct 21, 4:17 am, Richard Heathfield <rj*@see.sig.invalidwrote:
<snip>
>assert(width (sizeof n * CHAR_BIT + 5) / 3);

What's the purpose of this? Let's say that int is four bytes long. The
expression on the right side of the '>' will yield 37 / 3 (12).
No, for four-byte ints it yields *at least* 12. If bytes are wider than
eight bits, which is legal, it will give a larger value.
What does 'width' represent?
It represents the width of the buffer starting at s. It must be big enough
to hold the text representation of an integer. If int is four octets in
size, then it could hold a value whose base ten text representation is as
large as -2147483648, which is eleven bytes long, so the buffer must be at
least twelve bytes long (one for the null terminator).
(You aren't using it anywhere else in the function.)
I did mean to use it...
>count = sprintf(t, "%d", n);
t += count;
while(count < len)

'len' is undefined.
....here. I meant width, not len.
>
>{
*t++ = padch;
}

And that will yield an infinite loop.
Well, now you're just being picky. :-)
Here's a safer and tested version:

char *PadSnprintf(char *str, // the buffer
int n, // sizeof(str)
If the comment is correct, why do you need n? Why not just use sizeof(str)?
But I suspect the comment is wrong.
int item, // the item to convert
char paddingChar) // the padding character
{
snprintf(str, n, "%d", item);
Right away, your "safer and tested version" fails to link on a vast number
of C installations that don't have access to snprintf.

The two bugs that you spotted in my code (and I thank you for that) are
trivial to fix. It's rather less trivial to implement snprintf on systems
that lack it.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 21 '08 #4

P: n/a
On Oct 21, 1:59*pm, Richard Heathfield <rj*@see.sig.invalidwrote:
s0****@gmail.com said:
On Oct 21, 4:17 am, Richard Heathfield <rj*@see.sig.invalidwrote:
(You aren't using it anywhere else in the function.)

I did mean to use it...
count = sprintf(t, "%d", n);
t += count;
while(count < len)
'len' is undefined.

...here. I meant width, not len.
{
*t++ = padch;
}
And that will yield an infinite loop.

Well, now you're just being picky. *:-)
A bit :-) Well, even if you would have used 'width' instead of 'len',
'count' isn't being incremented anywhere.
Here's a safer and tested version:
char *PadSnprintf(char *str, * * * * // the buffer
* * * * * * * * * int n, * * * * * * // sizeof(str)

If the comment is correct, why do you need n? Why not just use sizeof(str)?
But I suspect the comment is wrong.
Perhaps the comment is a bit misleading. The confusion is that if you
have an array declared like 'char str[10];', sizeof(str) will yield
10, whereas sizeof(str) inside PadSnprintf() will only yield the size
of a pointer (4 bytes or so), regardless of the size of the array to
which it points.
* * * * * * * * * int item, * * * * *// theitem to convert
* * * * * * * * * char paddingChar) *// the paddingcharacter
{
* * snprintf(str, n, "%d", item);

Right away, your "safer and tested version" fails to link on a vast number
of C installations that don't have access to snprintf.

The two bugs that you spotted in my code (and I thank you for that) are
trivial to fix. It's rather less trivial to implement snprintf on systems
that lack it.
Well, I wouldn't call them "a vast number." Even some non-C99
compilers support it (e.g., MSVC++).

Sebastian

Oct 21 '08 #5

P: n/a
s0****@gmail.com said:
On Oct 21, 1:59 pm, Richard Heathfield <rj*@see.sig.invalidwrote:
>s0****@gmail.com said:
<snip>
Here's a safer and tested version:
char *PadSnprintf(char *str, // the buffer
int n, // sizeof(str)

If the comment is correct, why do you need n? Why not just use
sizeof(str)? But I suspect the comment is wrong.

Perhaps the comment is a bit misleading. The confusion is that if you
have an array declared like 'char str[10];', sizeof(str) will yield
10, whereas sizeof(str) inside PadSnprintf() will only yield the size
of a pointer (4 bytes or so),
Or 1, or 2, or whatever. Yes.
regardless of the size of the array to which it points.
It doesn't point to an array. It points to the first member of an array.
int item, // the item to convert
char paddingChar) // the padding character
{
snprintf(str, n, "%d", item);

Right away, your "safer and tested version" fails to link on a vast
number of C installations that don't have access to snprintf.

The two bugs that you spotted in my code (and I thank you for that) are
trivial to fix. It's rather less trivial to implement snprintf on
systems that lack it.

Well, I wouldn't call them "a vast number."
I have quite a few implementations installed on various bits of kit around
here, and only *one* of them provides snprintf (and only when invoked in
non-conforming mode, and with different semantics to C99).
Even some non-C99 compilers support it (e.g., MSVC++).
I checked. My copy doesn't.

Obviously the call is legal C99. And C99, like the Ritz Hotel, is open to
all.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 21 '08 #6

P: n/a
s0****@gmail.com wrote:
Richard Heathfield <rj*@see.sig.invalidwrote:
.... snip ...
>
>If the comment is correct, why do you need n? Why not just use
sizeof(str)? But I suspect the comment is wrong.

Perhaps the comment is a bit misleading. The confusion is that if
you have an array declared like 'char str[10];', sizeof(str) will
yield 10, whereas sizeof(str) inside PadSnprintf() will only yield
the size of a pointer (4 bytes or so), regardless of the size of
the array to which it points.
However you can apply the esoteric strlen(s) function to get the
length of the passed string.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Oct 21 '08 #7

P: n/a
CBFalconer <cb********@yahoo.comwrites:
s0****@gmail.com wrote:
>Richard Heathfield <rj*@see.sig.invalidwrote:
... snip ...
>>
>>If the comment is correct, why do you need n? Why not just use
sizeof(str)? But I suspect the comment is wrong.

Perhaps the comment is a bit misleading. The confusion is that if
you have an array declared like 'char str[10];', sizeof(str) will
yield 10, whereas sizeof(str) inside PadSnprintf() will only yield
the size of a pointer (4 bytes or so), regardless of the size of
the array to which it points.

However you can apply the esoteric strlen(s) function to get the
length of the passed string.
That's unlikely to be useful in this case. The pointer need not point
at a string -- in fact it would very unusual to require that a
function of this sort be passed a pointer to string.

--
Ben.
Oct 21 '08 #8

P: n/a
CBFalconer said:
s0****@gmail.com wrote:
>Richard Heathfield <rj*@see.sig.invalidwrote:
... snip ...
>>
>>If the comment is correct, why do you need n? Why not just use
sizeof(str)? But I suspect the comment is wrong.

Perhaps the comment is a bit misleading. The confusion is that if
you have an array declared like 'char str[10];', sizeof(str) will
yield 10, whereas sizeof(str) inside PadSnprintf() will only yield
the size of a pointer (4 bytes or so), regardless of the size of
the array to which it points.

However you can apply the esoteric strlen(s) function to get the
length of the passed string.
What passed string?

Has it ever occurred to you to read threads before trying to participate in
them?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 21 '08 #9

P: n/a
Richard Heathfield wrote:
CBFalconer said:
>s0****@gmail.com wrote:
>>Richard Heathfield <rj*@see.sig.invalidwrote:
... snip ...
>>>
If the comment is correct, why do you need n? Why not just use
sizeof(str)? But I suspect the comment is wrong.

Perhaps the comment is a bit misleading. The confusion is that
if you have an array declared like 'char str[10];', sizeof(str)
will yield 10, whereas sizeof(str) inside PadSnprintf() will
only yield the size of a pointer (4 bytes or so), regardless of
the size of the array to which it points.

However you can apply the esoteric strlen(s) function to get the
length of the passed string.

What passed string?

Has it ever occurred to you to read threads before trying to
participate in them?
The following was the function under discussion. If str is not a
string, it should be. Do try to control your love of petty
objections.
>>>>char *PadSnprintf(char *str, // the buffer
--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
Oct 22 '08 #10

P: n/a
CBFalconer said:
Richard Heathfield wrote:
>CBFalconer said:
>>s0****@gmail.com wrote:
Richard Heathfield <rj*@see.sig.invalidwrote:

... snip ...

If the comment is correct, why do you need n? Why not just use
sizeof(str)? But I suspect the comment is wrong.

Perhaps the comment is a bit misleading. The confusion is that
if you have an array declared like 'char str[10];', sizeof(str)
will yield 10, whereas sizeof(str) inside PadSnprintf() will
only yield the size of a pointer (4 bytes or so), regardless of
the size of the array to which it points.

However you can apply the esoteric strlen(s) function to get the
length of the passed string.

What passed string?

Has it ever occurred to you to read threads before trying to
participate in them?

The following was the function under discussion. If str is not a
string, it should be.
It isn't, and it shouldn't be. It is *to become* a string. What's wrong
with this buggy code that I just buggily wrote to illustrate this point?

char iamnotastring[32];
iamnotastring[0] = '\0'; /* optional - doesn't affect my point */
if(fgets(iamnotastring, strlen(iamnotastring), stdin) != NULL)
{
...
Do try to control your love of petty objections.
You consider the distinction between a string and an array of char "petty"?
>>>>>char *PadSnprintf(char *str, // the buffer
str is a pointer to the first character in a buffer that is *going to
become* a string. You can't find out how long that buffer is with strlen.
You have to be told.

And in your case, you have to be told repeatedly.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 22 '08 #11

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
You consider the distinction between a string and an array of char "petty"?
Richard, you're hereby invited to the 'Banks and the Economy'
thread which I invited to be moved here rather than continue
off-topic in alt.lang.asm. (Being about C, rather than asm,
or banks.)

Phil
--
The fact that a believer is happier than a sceptic is no more to the
point than the fact that a drunken man is happier than a sober one.
The happiness of credulity is a cheap and dangerous quality.
-- George Bernard Shaw (1856-1950), Preface to Androcles and the Lion
Oct 22 '08 #12

P: n/a
Phil Carmody said:
Richard Heathfield <rj*@see.sig.invalidwrites:
>You consider the distinction between a string and an array of char
"petty"?

Richard, you're hereby invited to the 'Banks and the Economy'
thread which I invited to be moved here rather than continue
off-topic in alt.lang.asm. (Being about C, rather than asm,
or banks.)
It's kind of you, but I had a quick look and I think I'll decline, since
it's not obvious what the issue is. (I got as far as discovering that it's
about formal parameters, and someone seems to be confused about in what
contexts char [] means char [] and in what contexts it means char *.)

Why not present the issue as a simple question or statement, in a new
thread? Throwing out all the background noise will probably help
immensely.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 22 '08 #13

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
Phil Carmody said:
>Richard Heathfield <rj*@see.sig.invalidwrites:
>>You consider the distinction between a string and an array of char
"petty"?

Richard, you're hereby invited to the 'Banks and the Economy'
thread which I invited to be moved here rather than continue
off-topic in alt.lang.asm. (Being about C, rather than asm,
or banks.)

It's kind of you, but I had a quick look and I think I'll decline, since
it's not obvious what the issue is. (I got as far as discovering that it's
about formal parameters, and someone seems to be confused about in what
contexts char [] means char [] and in what contexts it means char *.)

Why not present the issue as a simple question or statement, in a new
thread? Throwing out all the background noise will probably help
immensely.
It appears that he's admitted he misunderstood C, so it's not just
in decline - it's over. Quite why he had to struggle and wriggle
so much on a.l.a I don't know, I thought he'd never get the point.
It appears that he misunderstood what follow-ups are too.

It's nice to know that you're here when needed though!

Cheers,
Phil
(Hi Ian!)
--
The fact that a believer is happier than a sceptic is no more to the
point than the fact that a drunken man is happier than a sober one.
The happiness of credulity is a cheap and dangerous quality.
-- George Bernard Shaw (1856-1950), Preface to Androcles and the Lion
Oct 22 '08 #14

P: n/a
Phil Carmody wrote:
>
Cheers,
Phil
(Hi Ian!)
G'day Phil!

--
Ian Collins
Oct 22 '08 #15

P: n/a
Phil Carmody wrote:
Richard Heathfield <rj*@see.sig.invalidwrites:
Phil Carmody said:
Richard Heathfield <rj*@see.sig.invalidwrites:
You consider the distinction between a string and an array of char
"petty"?

Richard, you're hereby invited to the 'Banks and the Economy'
thread which I invited to be moved here rather than continue
off-topic in alt.lang.asm. (Being about C, rather than asm,
or banks.)
....
It appears that he's admitted he misunderstood C, so it's not just
I presume that "he" refers to s_dubrov...@yahoo.com? (I'm using Google
Groups right now, which replaced the rest of his user name with
"..."). I can't find any such admission. In fact, according to Google
he hasn't posted anything, anywhere, since posting that message to
c.l.c.
Oct 22 '08 #16

P: n/a
ja*********@verizon.net writes:
Phil Carmody wrote:
>Richard Heathfield <rj*@see.sig.invalidwrites:
Phil Carmody said:

Richard Heathfield <rj*@see.sig.invalidwrites:
You consider the distinction between a string and an array of char
"petty"?

Richard, you're hereby invited to the 'Banks and the Economy'
thread which I invited to be moved here rather than continue
off-topic in alt.lang.asm. (Being about C, rather than asm,
or banks.)
...
>It appears that he's admitted he misunderstood C, so it's not just

I presume that "he" refers to s_dubrov...@yahoo.com? (I'm using Google
Groups right now, which replaced the rest of his user name with
"..."). I can't find any such admission. In fact, according to Google
he hasn't posted anything, anywhere, since posting that message to
c.l.c.
That message contained:
"You both point out that I'm wrong, I accept that.";
"I don't deny my misunderstandings of C, for sure.";
"So I'm wrong to the standard, (shrug)"; and
"Yes, I had missed that."

Which was good enough for me, and what I think can be
called such an admission. His previous responses on
alt.lang.asm lead me to believe that he wasn't
persuadable by the simple reasoning of one poster (me).

Phil
--
The fact that a believer is happier than a sceptic is no more to the
point than the fact that a drunken man is happier than a sober one.
The happiness of credulity is a cheap and dangerous quality.
-- George Bernard Shaw (1856-1950), Preface to Androcles and the Lion
Oct 22 '08 #17

P: n/a
On Tue, 21 Oct 2008 02:03:50 -0700 (PDT), marc
<ma*********@caramail.comwrote:
>Hello,

Is it possible to right pad with "0" (or other character != blank) ?
for example :
1 , length 10 ="1000000000"
I've tried with sprintf but I can only left pad with "0" or right pad
with blanks =>
"0000000001"
"1 "

Thanks.
While the Imperial Judges of clc were busy throwing insults and slurs at
each other, the OP's question went unanswered.

I have used my petty talents to code the following function 'padd()',
which will pad a string on either the left or right with any (?)
character you wish. It will not overflow your buffer, since it allocates
one for you. (You should free it after use.) It may not be the
prettiest coding, but it works, and it gave me the opportunity of
learning something about pointers.

Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)

--------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

#define PAD_LEFT 1
#define PAD_RIGHT 0

int padd(
char stin[], /* input string */
char ** strout, /* ptr to place for output */
size_t leno, /* length of output */
char pad, /* padding character */
int rl) /* pad right (0) or left (1)*/
{
int len = strlen(stin);
int i = 0;
int c=leno-len; /* length of padding string */
assert(c >= 0);
char *padstr = NULL; /* for padding string */

/* make output buffer */
*strout = (char *)malloc(leno+1);
if (*strout == NULL) {
free(*strout);
return (-1);
}

/* make padding string */
padstr = (char *)malloc(c+1);
if (padstr == NULL) {
free(padstr);
return (-1);
}
char *t = padstr; /* save ptr */
while(i++ < c)
*padstr++ = pad;
*padstr = '\0';
padstr = t; /* restore ptr */

if(rl == PAD_LEFT) {
strcpy(*strout,padstr);
strcat(*strout,stin);
}else{
strcpy(*strout,stin);
strcat(*strout,padstr);
}
free (padstr);
return(0);
}

#ifdef TEST_IT

int abrt(void)
{
puts("ouch!");
exit (-1);
}
int main(void)
{
int ret;
char * s1 = NULL; /* for output */
char * s2 = NULL; /* ditto */
char s[] = "abc"; /* string to pad */
ret = padd(s, &s1, 10, '*', PAD_RIGHT);
if(ret != 0) abrt();
printf("[%s]\n",s1);
ret = padd(s1, &s2, 15, '=', PAD_LEFT);
if(ret != 0) abrt();
printf("[%s]\n",s2);
free(s1);
free(s2);
ret = padd(s, &s1, 10, '*', PAD_LEFT);
if(ret != 0) abrt();
printf("[%s]\n",s1);
ret = padd(s1, &s2, 15, '=', PAD_RIGHT);
if(ret != 0) abrt();
printf("[%s]\n",s2);
free(s1);
free(s2);

}
#endif
--------------------------------------------------------------------

Oct 26 '08 #18

P: n/a
Pilcrow <Pi******@gmail.comwrites:
On Tue, 21 Oct 2008 02:03:50 -0700 (PDT), marc
<ma*********@caramail.comwrote:
>>Hello,

Is it possible to right pad with "0" (or other character != blank) ?
for example :
1 , length 10 ="1000000000"
I've tried with sprintf but I can only left pad with "0" or right pad
with blanks =>
"0000000001"
"1 "

Thanks.

While the Imperial Judges of clc were busy throwing insults and slurs at
each other, the OP's question went unanswered.
Eh? I was about to post a solution but the first one I saw was posted
14 minutes after the question so I did not bother. OK, that had a
type in it, but that was corrected quite quickly.

A second solution was posted within 9 hours. That used snprintf so it
may not have been suitable depending on the library the OP was using.
I have used my petty talents to code the following function 'padd()',
which will pad a string on either the left or right with any (?)
character you wish. It will not overflow your buffer, since it allocates
one for you. (You should free it after use.) It may not be the
prettiest coding, but it works, and it gave me the opportunity of
learning something about pointers.
An excellent reason to write code but your function does not do what
the OP wanted, so by your reasoning, the questions is *still*
unanswered.
Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)
I don't know if I am one of the people you are being rude about, but I
don't want to be thought of throwing rotten tomatoes so I will leave
your code un-commented on.

--
Ben.
Oct 26 '08 #19

P: n/a
On Sun, 26 Oct 2008 13:42:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>Pilcrow <Pi******@gmail.comwrites:
>On Tue, 21 Oct 2008 02:03:50 -0700 (PDT), marc
<ma*********@caramail.comwrote:
>>>Hello,

Is it possible to right pad with "0" (or other character != blank) ?
for example :
1 , length 10 ="1000000000"
I've tried with sprintf but I can only left pad with "0" or right pad
with blanks =>
"0000000001"
"1 "

Thanks.

While the Imperial Judges of clc were busy throwing insults and slurs at
each other, the OP's question went unanswered.

Eh? I was about to post a solution but the first one I saw was posted
14 minutes after the question so I did not bother. OK, that had a
type in it, but that was corrected quite quickly.
Well, I copied out what was posted, since I was interested in the
problem, but I was unable to make it work (possibly my fault), so I
tried doing it on my own. I had many difficulties along the way. Then,
assuming that the OP had the same trouble I had, I posted my working,
tested, but unpretty solution.

There's always more than one way to do it.
>
A second solution was posted within 9 hours. That used snprintf so it
may not have been suitable depending on the library the OP was using.
>I have used my petty talents to code the following function 'padd()',
which will pad a string on either the left or right with any (?)
character you wish. It will not overflow your buffer, since it allocates
one for you. (You should free it after use.) It may not be the
prettiest coding, but it works, and it gave me the opportunity of
learning something about pointers.

An excellent reason to write code but your function does not do what
the OP wanted, so by your reasoning, the questions is *still*
unanswered.
I fail to understand this remark. My code does what the OP wanted, and
it does more. It pads any string, such as one that might have been the
result of sprintf, with any padding character, either on the left or
right. But, even if it failed to do what was requested, you might give
the community code that is better suited to the request.
>
>Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)

I don't know if I am one of the people you are being rude about, but I
don't want to be thought of throwing rotten tomatoes so I will leave
your code un-commented on.
"rotten tomatoes" is my way of characterizing carping complaints that
fail to show a better way. As to rudeness, that seems to be the norm in
clc.

Are you a Brit, by any chance?
Oct 26 '08 #20

P: n/a
On Sun, 26 Oct 2008 13:42:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>Pilcrow <Pi******@gmail.comwrites:
>On Tue, 21 Oct 2008 02:03:50 -0700 (PDT), marc
<ma*********@caramail.comwrote:
>>>Hello,

Is it possible to right pad with "0" (or other character != blank) ?
for example :
1 , length 10 ="1000000000"
I've tried with sprintf but I can only left pad with "0" or right pad
with blanks =>
"0000000001"
"1 "

Thanks.

While the Imperial Judges of clc were busy throwing insults and slurs at
each other, the OP's question went unanswered.

Eh? I was about to post a solution but the first one I saw was posted
14 minutes after the question so I did not bother. OK, that had a
type in it, but that was corrected quite quickly.

A second solution was posted within 9 hours. That used snprintf so it
may not have been suitable depending on the library the OP was using.
>I have used my petty talents to code the following function 'padd()',
which will pad a string on either the left or right with any (?)
character you wish. It will not overflow your buffer, since it allocates
one for you. (You should free it after use.) It may not be the
prettiest coding, but it works, and it gave me the opportunity of
learning something about pointers.

An excellent reason to write code but your function does not do what
the OP wanted, so by your reasoning, the questions is *still*
unanswered.
>Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)

I don't know if I am one of the people you are being rude about, but I
don't want to be thought of throwing rotten tomatoes so I will leave
your code un-commented on.
Ok, now I see, you are a Brit. In my experience, Brits fail to percieve
that criticizing others for their rudeness is, in itself, rude.

Oct 26 '08 #21

P: n/a
Pilcrow said:
On Sun, 26 Oct 2008 13:42:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>Pilcrow <Pi******@gmail.comwrites:
<snip>
>>
>>Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)

I don't know if I am one of the people you are being rude about, but I
don't want to be thought of throwing rotten tomatoes so I will leave
your code un-commented on.

Ok, now I see, you are a Brit. In my experience, Brits fail to percieve
that criticizing others for their rudeness is, in itself, rude.
May we deduce that you, too, are a "Brit"?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 26 '08 #22

P: n/a
On Sun, 26 Oct 2008 21:05:36 +0000, Richard Heathfield
<rj*@see.sig.invalidwrote:
>Pilcrow said:
>On Sun, 26 Oct 2008 13:42:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>>Pilcrow <Pi******@gmail.comwrites:
<snip>
>>>
Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)

I don't know if I am one of the people you are being rude about, but I
don't want to be thought of throwing rotten tomatoes so I will leave
your code un-commented on.

Ok, now I see, you are a Brit. In my experience, Brits fail to percieve
that criticizing others for their rudeness is, in itself, rude.

May we deduce that you, too, are a "Brit"?
Some kind of a logic falacy here. But, yes, I also was guilty. And I
apologize. I put mouth in motion before brain was engaged.
Oct 26 '08 #23

P: n/a
Pilcrow <Pi******@gmail.comwrites:
On Sun, 26 Oct 2008 13:42:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>Pilcrow <Pi******@gmail.comwrites:
>>On Tue, 21 Oct 2008 02:03:50 -0700 (PDT), marc
<ma*********@caramail.comwrote:

Hello,

Is it possible to right pad with "0" (or other character != blank) ?
for example :
1 , length 10 ="1000000000"
I've tried with sprintf but I can only left pad with "0" or right pad
with blanks =>
"0000000001"
"1 "

Thanks.

While the Imperial Judges of clc were busy throwing insults and slurs at
each other, the OP's question went unanswered.

Eh? I was about to post a solution but the first one I saw was posted
14 minutes after the question so I did not bother. OK, that had a
type in it, but that was corrected quite quickly.

Well, I copied out what was posted, since I was interested in the
problem, but I was unable to make it work (possibly my fault), so I
tried doing it on my own. I had many difficulties along the way. Then,
assuming that the OP had the same trouble I had, I posted my working,
tested, but unpretty solution.
If it had been me, I'd have posted back to say "this does not work for
me, is there something wrong?". The error was a mis-typed variable
name (len instead of width if I recall correctly) but this was pointed
out very quickly.
There's always more than one way to do it.
>>
A second solution was posted within 9 hours. That used snprintf so it
may not have been suitable depending on the library the OP was using.
>>I have used my petty talents to code the following function 'padd()',
which will pad a string on either the left or right with any (?)
character you wish. It will not overflow your buffer, since it allocates
one for you. (You should free it after use.) It may not be the
prettiest coding, but it works, and it gave me the opportunity of
learning something about pointers.

An excellent reason to write code but your function does not do what
the OP wanted, so by your reasoning, the questions is *still*
unanswered.

I fail to understand this remark. My code does what the OP wanted, and
it does more. It pads any string, such as one that might have been the
result of sprintf, with any padding character, either on the left or
right.
All I can say is that I disagree. There is evidence that the OP
wanted to write the decimal representation of an int, padded on the
right, into an existing array -- which is not what your code does.
But, even if it failed to do what was requested, you might give
the community code that is better suited to the request.
There were posted solutions that satisfied me but I am happy supply my
own take on the function:

#include <stdio.h>
#include <string.h>

char *ipadright(char *buf, int i, char pad, int min_width)
{
int int_width = sprintf(buf, "%d", i);
if (int_width < min_width) {
memset(buf + int_width, pad, min_width - int_width);
buf[min_width] = 0;
}
return buf;
}

This assumes that the caller takes responsibility for there being
enough room in the buffer.

<snip>

--
Ben.
Oct 27 '08 #24

P: n/a
Pilcrow <Pi******@gmail.comwrites:
On Sun, 26 Oct 2008 13:42:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>Pilcrow <Pi******@gmail.comwrites:
<snip>
>>Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)

I don't know if I am one of the people you are being rude about, but I
don't want to be thought of throwing rotten tomatoes so I will leave
your code un-commented on.

Ok, now I see, you are a Brit. In my experience, Brits fail to percieve
that criticizing others for their rudeness is, in itself, rude.
I, however, am not one of them.

--
Ben.
Oct 27 '08 #25

P: n/a
Pilcrow said:
On Sun, 26 Oct 2008 21:05:36 +0000, Richard Heathfield
<rj*@see.sig.invalidwrote:
>>Pilcrow said:
>>On Sun, 26 Oct 2008 13:42:27 +0000, Ben Bacarisse
<be********@bsb.me.ukwrote:

Pilcrow <Pi******@gmail.comwrites:
<snip>
>>>>
Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)

I don't know if I am one of the people you are being rude about, but I
don't want to be thought of throwing rotten tomatoes so I will leave
your code un-commented on.

Ok, now I see, you are a Brit. In my experience, Brits fail to
percieve that criticizing others for their rudeness is, in itself,
rude.

May we deduce that you, too, are a "Brit"?

Some kind of a logic falacy here.
Yes - the fallacy was in the premise. It is simply not true that
criticising others for their rudeness is in itself rude.
But, yes, I also was guilty. And I
apologize. I put mouth in motion before brain was engaged.
You also put your code in motion before your brain was engaged. A solution
had already been presented. I know this because I presented it. It was
flawed (at the time I wrote it, I lacked the time to test it, and this
showed through rather clearly), but the flaws were quickly identified and
corrected. Applying the suggested corrections led to a working solution to
the OP's problem. Your own "solution" also has flaws. Because you've
insulted those who provide useful critiques (labelling them "Imperial
Judges" and accusing them of "throwing rotten tomatoes"), you should not
be surprised if they don't feel particularly in the mood for providing a
useful critique of your code. This has saved everyone a lot of time, since
the critique would have been a long one.

Your apology does you credit, but your attempt to share the blame does not.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 27 '08 #26

P: n/a
On Sun, 26 Oct 2008 14:44:09 -0700, Pilcrow <Pi******@gmail.comwrote:
>On Sun, 26 Oct 2008 21:05:36 +0000, Richard Heathfield
<rj*@see.sig.invalidwrote:
>>Pilcrow said:
>>On Sun, 26 Oct 2008 13:42:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:

Pilcrow <Pi******@gmail.comwrites:
<snip>
>>>>
Now the Imperial Judges can have the opportunity of throwing rotten
tomatoes at me. (It wouldn't be the first time.)

I don't know if I am one of the people you are being rude about, but I
don't want to be thought of throwing rotten tomatoes so I will leave
your code un-commented on.

Ok, now I see, you are a Brit. In my experience, Brits fail to percieve
that criticizing others for their rudeness is, in itself, rude.

May we deduce that you, too, are a "Brit"?

Some kind of a logic falacy here. But, yes, I also was guilty. And I
apologize. I put mouth in motion before brain was engaged.
The falacy, I have found, is called the 'undistributed middle'. An
example: Humans are bipedal. Birds are bipedal. Birds are humans.
Oct 27 '08 #27

P: n/a
Pilcrow wrote:
On Sun, 26 Oct 2008 14:44:09 -0700, Pilcrow <Pi******@gmail.comwrote:
>On Sun, 26 Oct 2008 21:05:36 +0000, Richard Heathfield
<rj*@see.sig.invalidwrote:
>>Pilcrow said:
.....
>>>Ok, now I see, you are a Brit. In my experience, Brits fail to percieve
that criticizing others for their rudeness is, in itself, rude.
May we deduce that you, too, are a "Brit"?
Some kind of a logic falacy here. But, yes, I also was guilty. And I
apologize. I put mouth in motion before brain was engaged.

The falacy, I have found, is called the 'undistributed middle'. An
example: Humans are bipedal. Birds are bipedal. Birds are humans.
Richard's response was merely intended to highlight the bigoted
stupidity of your premise by using it as the basis for an equally
illogical deduction. A better analogy would reflect that:

Humans have red hair. Orangutangs have red hair. Orangutangs are humans.
Oct 27 '08 #28

P: n/a
On Mon, 27 Oct 2008 10:32:22 GMT, James Kuyper <ja*********@verizon.net>
wrote:
>Pilcrow wrote:
>On Sun, 26 Oct 2008 14:44:09 -0700, Pilcrow <Pi******@gmail.comwrote:
>>On Sun, 26 Oct 2008 21:05:36 +0000, Richard Heathfield
<rj*@see.sig.invalidwrote:

Pilcrow said:
....
>>>>Ok, now I see, you are a Brit. In my experience, Brits fail to percieve
that criticizing others for their rudeness is, in itself, rude.
May we deduce that you, too, are a "Brit"?
Some kind of a logic falacy here. But, yes, I also was guilty. And I
apologize. I put mouth in motion before brain was engaged.

The falacy, I have found, is called the 'undistributed middle'. An
example: Humans are bipedal. Birds are bipedal. Birds are humans.

Richard's response was merely intended to highlight the bigoted
stupidity of your premise by using it as the basis for an equally
illogical deduction. A better analogy would reflect that:

Humans have red hair. Orangutangs have red hair. Orangutangs are humans.
Sorry, only one apology per incident. Come back again when I do
something else stupid, and, if you are the first to point it out, I will
be happy to give you your very own apology.

Oct 27 '08 #29

P: n/a
Pilcrow said:

<snip>
Sorry, only one apology per incident. Come back again when I do
something else stupid,
Well, that didn't take long, did it?

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 27 '08 #30

P: n/a
On Mon, 27 Oct 2008 12:40:35 +0000, Richard Heathfield
<rj*@see.sig.invalidwrote:
>Pilcrow said:

<snip>
>Sorry, only one apology per incident. Come back again when I do
something else stupid,

Well, that didn't take long, did it?
You may have noticed that I have no problem with making an apology when
it allows us to move on.

But, to get back to the topic. I have been working on your
(Heathfield's) submission in response to the OP's query. I fixed what I
regarded as a bug (the assert statement), used a malloc to guard against
buffer overflow, and expanded its capability to allow for padding on
either the left or right. Here is my current version, followed by some
remarks and questions.

------------------------------------------------------------------------
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#define PAD_RIGHT 0
#define PAD_LEFT 1

int digits(int n) /* how many digits in an integer */
{
int ct = 0;
int pow = 10;
while(n 0) {
n -= n % pow;
pow *= 10;
ct++;
}
return ct;
}

char *pad( /* func returns ptr to start of string */
char *s, /* buffer for output string */
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
int dig = digits(n); /* space required for the number */
assert(dig <= width); /* must have at least that space */
int count = 0; /* count of characters */
s = malloc(width+1); /* get necessary memory */
char *t = s; /* save ptr */
if (rl == PAD_RIGHT) {
count = sprintf(t, "%d", n); /* insert num */
t += count; /* bump ptr */
while(count++ < width) /* pad on right */
*t++ = padch;
*t = '\0'; /* finish string */
}else{
while(count++ < width-dig) /* pad on left */
*t++ = padch;
sprintf(t, "%d", n); /* insert num */
}
return s; /* return ptr to start of string */
}

#ifdef TEST_IT

int main(void)
{
char *here = NULL;
int num = 123;
printf("[%s]\n",pad(here, num, 20, '*', PAD_RIGHT));
free (here);
printf("[%s]\n",pad(here, num, 13, '*', PAD_LEFT));
free (here);
printf("[%s]\n",pad(here, num, 3, '*', PAD_RIGHT));
free (here);
}
#endif
------------------------------------------------------------------------

My first problem with this is that the sprintf is hard-coded, which is
inappropriate for a library function.

Secondly, I was able to print the results, as you see, but I cannot
figure out how to save the result for later use. For example,

------------------------------------------------------------------------

int main(void)
{
char *here = NULL;
int num = 123;
printf("[%s]\n",pad(here, num, 20, '*', PAD_RIGHT));

------------------------------------------------------------------------
should leave the result in 'here', but I can't 'puts' it (surely my
fault?). I even tried something like this:
------------------------------------------------------------------------

int main(void)
{
char *here = NULL;
char *t = here;
int num = 123;
pad(here, num, 20, '*', PAD_RIGHT);
puts(t); /* or puts(*t) or ... */

------------------------------------------------------------------------
Now, what am I missing???
Oct 27 '08 #31

P: n/a
Pilcrow <Pi******@gmail.comwrites:

<snip>
But, to get back to the topic. I have been working on your
(Heathfield's) submission in response to the OP's query. I fixed what I
regarded as a bug (the assert statement), used a malloc to guard against
buffer overflow, and expanded its capability to allow for padding on
either the left or right. Here is my current version, followed by some
remarks and questions.

------------------------------------------------------------------------
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#define PAD_RIGHT 0
#define PAD_LEFT 1

int digits(int n) /* how many digits in an integer */
I prefer to make this sort of helper function static.
{
int ct = 0;
int pow = 10;
while(n 0) {
n -= n % pow;
pow *= 10;
ct++;
}
return ct;
}
This goes wrong for all n <= 0. It also goes wrong for those large n
that cause pow to overflow.
>
char *pad( /* func returns ptr to start of string */
I'd suggest a more descriptive name.
char *s, /* buffer for output string */
This parameter is pointless. I think (from the call you make below)
that you've forgotten that C is pass-by-value.
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
int dig = digits(n); /* space required for the number */
assert(dig <= width); /* must have at least that space */
int count = 0; /* count of characters */
You have now switched to C99 but mixing declarations and statements.
s = malloc(width+1); /* get necessary memory */
I'd check the return.
char *t = s; /* save ptr */
if (rl == PAD_RIGHT) {
count = sprintf(t, "%d", n); /* insert num */
t += count; /* bump ptr */
while(count++ < width) /* pad on right */
*t++ = padch;
*t = '\0'; /* finish string */
}else{
while(count++ < width-dig) /* pad on left */
*t++ = padch;
sprintf(t, "%d", n); /* insert num */
}
return s; /* return ptr to start of string */
}

#ifdef TEST_IT

int main(void)
{
char *here = NULL;
int num = 123;
printf("[%s]\n",pad(here, num, 20, '*', PAD_RIGHT));
free (here);
here is NULL at this point. The free does nothing.
printf("[%s]\n",pad(here, num, 13, '*', PAD_LEFT));
free (here);
printf("[%s]\n",pad(here, num, 3, '*', PAD_RIGHT));
free (here);
}
#endif
------------------------------------------------------------------------

My first problem with this is that the sprintf is hard-coded, which is
inappropriate for a library function.

Secondly, I was able to print the results, as you see, but I cannot
figure out how to save the result for later use. For example,

------------------------------------------------------------------------

int main(void)
{
char *here = NULL;
int num = 123;
printf("[%s]\n",pad(here, num, 20, '*', PAD_RIGHT));

------------------------------------------------------------------------
should leave the result in 'here', but I can't 'puts' it (surely my
fault?). I even tried something like this:
------------------------------------------------------------------------

int main(void)
{
char *here = NULL;
char *t = here;
int num = 123;
pad(here, num, 20, '*', PAD_RIGHT);
puts(t); /* or puts(*t) or ... */

------------------------------------------------------------------------
Now, what am I missing???
C is call-by-value. You should just leave off the first parameter and
call ths function like this:

here = pad(num, 20, '*', PAD_RIGHT);

but I would advice a different interface where the caller passes in
the buffer to be used.

--
Ben.
Oct 28 '08 #32

P: n/a
On Mon, 27 Oct 2008 23:58:47 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>Pilcrow <Pi******@gmail.comwrites:

<snip>
>But, to get back to the topic. I have been working on your
(Heathfield's) submission in response to the OP's query. I fixed what I
regarded as a bug (the assert statement), used a malloc to guard against
buffer overflow, and expanded its capability to allow for padding on
either the left or right. Here is my current version, followed by some
remarks and questions.

------------------------------------------------------------------------
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#define PAD_RIGHT 0
#define PAD_LEFT 1

int digits(int n) /* how many digits in an integer */

I prefer to make this sort of helper function static.
>{
int ct = 0;
int pow = 10;
while(n 0) {
n -= n % pow;
pow *= 10;
ct++;
}
return ct;
}

This goes wrong for all n <= 0. It also goes wrong for those large n
that cause pow to overflow.
Quite true, but ok for n>0. pow overflow? Just counting digits. So i
should make pow a longlong? ok. And change for n <= 0 should be easy.
Thanks.
>
>>
char *pad( /* func returns ptr to start of string */

I'd suggest a more descriptive name.
> char *s, /* buffer for output string */

This parameter is pointless. I think (from the call you make below)
that you've forgotten that C is pass-by-value.
don't understand your point
>
> int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
int dig = digits(n); /* space required for the number */
assert(dig <= width); /* must have at least that space */
int count = 0; /* count of characters */

You have now switched to C99 but mixing declarations and statements.
Using gcc in mingw on a windows machine.. All these varying 'standards'
have me dizzy.
>
> s = malloc(width+1); /* get necessary memory */

I'd check the return.
ok
>
> char *t = s; /* save ptr */
if (rl == PAD_RIGHT) {
count = sprintf(t, "%d", n); /* insert num */
t += count; /* bump ptr */
while(count++ < width) /* pad on right */
*t++ = padch;
*t = '\0'; /* finish string */
}else{
while(count++ < width-dig) /* pad on left */
*t++ = padch;
sprintf(t, "%d", n); /* insert num */
}
return s; /* return ptr to start of string */
}

#ifdef TEST_IT

int main(void)
{
char *here = NULL;
int num = 123;
printf("[%s]\n",pad(here, num, 20, '*', PAD_RIGHT));
free (here);

here is NULL at this point. The free does nothing.
But I built the string in 'here', didn't I?
>
> printf("[%s]\n",pad(here, num, 13, '*', PAD_LEFT));
free (here);
printf("[%s]\n",pad(here, num, 3, '*', PAD_RIGHT));
free (here);
}
#endif
------------------------------------------------------------------------

My first problem with this is that the sprintf is hard-coded, which is
inappropriate for a library function.

Secondly, I was able to print the results, as you see, but I cannot
figure out how to save the result for later use. For example,

------------------------------------------------------------------------

int main(void)
{
char *here = NULL;
int num = 123;
printf("[%s]\n",pad(here, num, 20, '*', PAD_RIGHT));

------------------------------------------------------------------------
should leave the result in 'here', but I can't 'puts' it (surely my
fault?). I even tried something like this:
------------------------------------------------------------------------

int main(void)
{
char *here = NULL;
char *t = here;
int num = 123;
pad(here, num, 20, '*', PAD_RIGHT);
puts(t); /* or puts(*t) or ... */

------------------------------------------------------------------------
Now, what am I missing???

C is call-by-value. You should just leave off the first parameter and
call ths function like this:

here = pad(num, 20, '*', PAD_RIGHT);
But then I would have to declare and use another buffer inside the
subroutine, no? And then how could it be free'd? And depend on the
user to define 'here' of sufficient size.
>
but I would advice a different interface where the caller passes in
the buffer to be used.
Didn't 'the user pass in the buffer to be used' in my code? I was
following Mr Heathfield's manner, or so I thought.

But now I see that Mr H did not dynamically allocate the memory for the
buffer from inside the function, so the user had to do it. I thought I
made an improvement.

So, should i have defined the function so?

------------------------------------------------------------------
char *pad (char **s ...
------------------------------------------------------------------

and called it:

------------------------------------------------------------------
something = pad(&here, ...
------------------------------------------------------------------

I tried that on a previous attempt, and got into trouble..

Lemme look at that again ...

Confusing
Oct 28 '08 #33

P: n/a
On Mon, 27 Oct 2008 21:34:36 -0700, Pilcrow <Pi******@gmail.comwrote:
>On Mon, 27 Oct 2008 23:58:47 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>Pilcrow <Pi******@gmail.comwrites:
[snip]

OK, I now have attempted to make corrections suggested by Mr Bacarisse,
and have the code below. I also have some questions.
1) Isn't there a memory leak, since the buffer is not free'd?
1a) I can't see how I can free that memory.
2) Does every invocation of malloc cumulatively increase the amount of
memory allocated?
3) Now I see that I was not using a user defined buffer with my previous
version. But I *want* to use such a buffer, and return the result via
that buffer. (And define 'void pad(' etc.) How do I do that?
4) I am still dissatisfied with the hard-coded sprintf, since I want,
eventually, to make this a library function, but that is not such a big
problem.
------------------------------------------------------------------------
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#define PAD_RIGHT 0
#define PAD_LEFT 1

int digits(int n) /* how many digits in an integer */
{
int ct = 0;
int sign = n;
int m = abs(n);
long long pow = 10;
while(m 0) {
m -= m % pow;
pow *= 10;
ct++;
}
if (sign < 0) ct++;
return ct;
}

char *pad( /* func returns ptr to start of string */
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
char *s; /* buffer */
int dig = digits(n); /* space required for the number */
assert(dig <= width); /* must have at least that space */
int count = 0; /* count of characters */

/* IS THE FOLLOWING CODE LINE A MEMORY LEAK? (never free'd) */
/* does each execution of malloc increase the memory allocated? */
s = malloc(width+1); /* get necessary memory */
assert(s != NULL);

char *t = s; /* save ptr */
if (rl == PAD_RIGHT) {
count = sprintf(t, "%d", n); /* insert num */
t += count; /* bump ptr */
while(count++ < width) /* pad on right */
*t++ = padch;
*t = '\0'; /* finish string */
}else{
while(count++ < width-dig) /* pad on left */
*t++ = padch;
sprintf(t, "%d", n); /* insert num */
}
return s; /* return ptr to start of string */
}

#ifdef TEST_IT

int main(void)
{
int num = -2147483647;
printf("[%s]\n",pad( num, 20, '*', PAD_RIGHT));
printf("[%s]\n",pad( -num, 13, '*', PAD_LEFT));
printf("[%s]\n",pad( 0, 11, '*', PAD_RIGHT));
}
#endif
------------------------------------------------------------------------

Oct 28 '08 #34

P: n/a
Pilcrow said:
On Mon, 27 Oct 2008 21:34:36 -0700, Pilcrow <Pi******@gmail.comwrote:
>>On Mon, 27 Oct 2008 23:58:47 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>>Pilcrow <Pi******@gmail.comwrites:
[snip]

OK, I now have attempted to make corrections suggested by Mr Bacarisse,
and have the code below. I also have some questions.
1) Isn't there a memory leak, since the buffer is not free'd?
1a) I can't see how I can free that memory.
The solution is simple:

(i) document the purpose and interface of your function;
(ii) in that documentation, stress that a suitably large buffer is
allocated dynamically;
(iii) further stress that it is the caller's responsibility to free the
buffer when it is no longer required.
2) Does every invocation of malloc cumulatively increase the amount of
memory allocated?
Every *successful* invocation of malloc with a non-zero argument expression
does so, yes. Freeing stuff will cumulatively decrease the amount of
memory allocated, of course.
3) Now I see that I was not using a user defined buffer with my previous
version. But I *want* to use such a buffer, and return the result via
that buffer.
That's a perfectly good approach, but it has a cost - i.e. the caller must
know how much space to allocate, rather than rely on you to work it out on
the caller's behalf. There isn't just one right answer. (There are plenty
of wrong answers, too.)
(And define 'void pad(' etc.) How do I do that?
By trusting the caller to provide sufficient bytes for you to store the
result (and, if you're wise, accepting a size_t parameter that allows the
caller to tell you how big the buffer is, so that - if he doesn't lie to
you - you can find out whether it will fit, and refuse to perform the
operation if it won't).
4) I am still dissatisfied with the hard-coded sprintf, since I want,
eventually, to make this a library function, but that is not such a big
problem.
It isn't hard to remove the sprintf (but I'll grant that it's harder than
it looks).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 28 '08 #35

P: n/a
Pilcrow <Pi******@gmail.comwrites:
On Mon, 27 Oct 2008 23:58:47 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>Pilcrow <Pi******@gmail.comwrites:
<snip>
>>int digits(int n) /* how many digits in an integer */
{
int ct = 0;
int pow = 10;
while(n 0) {
n -= n % pow;
pow *= 10;
ct++;
}
return ct;
}

This goes wrong for all n <= 0. It also goes wrong for those large n
that cause pow to overflow.

Quite true, but ok for n>0. pow overflow? Just counting digits. So i
should make pow a longlong? ok. And change for n <= 0 should be easy.
Thanks.
long long is (a) C99 and (b) overkill. You can count digits by making
the number smaller by a factor of 10 at every step so there is no
danger of overflow. There are other ways (you could simply stop when
n/pow < 10 for example) but long long is not called for in my opinion.
>>char *pad( /* func returns ptr to start of string */
char *s, /* buffer for output string */

This parameter is pointless. I think (from the call you make below)
that you've forgotten that C is pass-by-value.

don't understand your point
This is the key point and rather that discuss it here, I'll try to
explain below when you raise it again in another guise.
>> int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
int dig = digits(n); /* space required for the number */
assert(dig <= width); /* must have at least that space */
int count = 0; /* count of characters */

You have now switched to C99 but mixing declarations and statements.

Using gcc in mingw on a windows machine.. All these varying 'standards'
have me dizzy.
If you pick two sets of strict options, one for C90 and one for C99
the compiler will tell you if you have used C99 features when you
don't mean to, or (in the second case) when you use implementation
specific features when you don't want to. This is one of the most
helpful things a compiler can do if you are writing library code like
this that should compile "almost everywhere". (For gcc and
derivatives -std=c89 -pedantic -Wall -Wextra is a good starting
point).

<snip>
>> printf("[%s]\n",pad(here, num, 20, '*', PAD_RIGHT));
free (here);

here is NULL at this point. The free does nothing.

But I built the string in 'here', didn't I?
No. May be a non-pointer example will help:

void set_me(int x) { x = 42; }

int here = 0;
set_me(here);

What value will 'here' have at this point? It won't be 42. I won't
labour the point (I and others will say more if you ask, I am sure)
but you need to get this first. Once you do, it is a simple matter so
that is makes no difference what type here has. It can be a double a
struct or a char *. In all cases the function can't change the value
that is passed.

Of course, a function *can* change the value of characters pointed to
*by* a char * parameter, and that is what my version (and RH's
version) did. This is of no use if you want to change the pointer
itself. For that you have to pass a pointer to the thing you want to
change (in this case the parameter would become a char **) but that
makes the function clumsy to use. It is alost always better to simple
return the char * that the function has built or otherwise computed.

<snip>
>>Now, what am I missing???

C is call-by-value. You should just leave off the first parameter and
call ths function like this:

here = pad(num, 20, '*', PAD_RIGHT);

But then I would have to declare and use another buffer inside the
subroutine, no? And then how could it be free'd? And depend on the
user to define 'here' of sufficient size.
Now it is my turn not to understand. In my call, the function mallocs
storage and returns pointer to it. It gets freed y the called just as
you tried to do in your code: free(here);. The code does not depend
on the user to define here of any size at all -- 'here' is defined
only as a char *.
>>but I would advice a different interface where the caller passes in
the buffer to be used.

Didn't 'the user pass in the buffer to be used' in my code? I was
following Mr Heathfield's manner, or so I thought.
No. You passed here having set it to NULL. That means "I don't point
at anything".
But now I see that Mr H did not dynamically allocate the memory for the
buffer from inside the function, so the user had to do it. I thought I
made an improvement.
That is not clear cut. Library functions that allocate storage can be
a good idea, but often are not. If this pad function is used to
generate lost of padded output, your version with all the free calls
is more complex than one that can just re-use the same local buffer:

char buf[sizeof(int) * CHAR_BIT + 5) / 3];
printf(".... %s ....", pad(buf, w, 12, ' ', PAD_LEFT));
printf(".... %s ....", pad(buf, x, 12, ' ', PAD_LEFT));
printf(".... %s ....", pad(buf, y, 12, ' ', PAD_LEFT));
printf(".... %s ....", pad(buf, z, 12, ' ', PAD_LEFT));
So, should i have defined the function so?

------------------------------------------------------------------
char *pad (char **s ...
------------------------------------------------------------------

and called it:

------------------------------------------------------------------
something = pad(&here, ...
------------------------------------------------------------------

I tried that on a previous attempt, and got into trouble..
Yes, that is one way, but it makes using the function much more
complex than it needs to be.

--
Ben.
Oct 28 '08 #36

P: n/a
On Tue, 28 Oct 2008 13:20:11 +0000, Richard Heathfield
<rj*@see.sig.invalidwrote:
>Pilcrow said:
>On Mon, 27 Oct 2008 21:34:36 -0700, Pilcrow <Pi******@gmail.comwrote:
>>>On Mon, 27 Oct 2008 23:58:47 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:

Pilcrow <Pi******@gmail.comwrites:
[snip]

OK, I now have attempted to make corrections suggested by Mr Bacarisse,
and have the code below. I also have some questions.
1) Isn't there a memory leak, since the buffer is not free'd?
1a) I can't see how I can free that memory.

The solution is simple:

(i) document the purpose and interface of your function;
(ii) in that documentation, stress that a suitably large buffer is
allocated dynamically;
(iii) further stress that it is the caller's responsibility to free the
buffer when it is no longer required.
>2) Does every invocation of malloc cumulatively increase the amount of
memory allocated?

Every *successful* invocation of malloc with a non-zero argument expression
does so, yes. Freeing stuff will cumulatively decrease the amount of
memory allocated, of course.
>3) Now I see that I was not using a user defined buffer with my previous
version. But I *want* to use such a buffer, and return the result via
that buffer.

That's a perfectly good approach, but it has a cost - i.e. the caller must
know how much space to allocate, rather than rely on you to work it out on
the caller's behalf. There isn't just one right answer. (There are plenty
of wrong answers, too.)
>(And define 'void pad(' etc.) How do I do that?

By trusting the caller to provide sufficient bytes for you to store the
result (and, if you're wise, accepting a size_t parameter that allows the
caller to tell you how big the buffer is, so that - if he doesn't lie to
you - you can find out whether it will fit, and refuse to perform the
operation if it won't).
>4) I am still dissatisfied with the hard-coded sprintf, since I want,
eventually, to make this a library function, but that is not such a big
problem.

It isn't hard to remove the sprintf (but I'll grant that it's harder than
it looks).
I see that I didn't express myself clearly enough. I want the user to
provide a pointer for a buffer, but not actally to provide space for it.
I want my function to allocate memory for that buffer. I will put the
result in that buffer. I want the user to free that memory when he/she
is done with it.

In the function, as written, I cannot see how the user can free the
buffer, since it is internal to the function. I have, however, dealt
with the problem of ever-increasing memory allocation by saying:
--------------------------------------------------------------------
free(s);
s = malloc(width+1);
assert(s != NULL);
--------------------------------------------------------------------

As for removing the sprintf; I would have the user provide a string
(which might be the result of sprintf) as input to the function. This
has the minor problem of defining an additional variable.

By the way, I can, with the function as it stands, do the following:
--------------------------------------------------------------------
char z[21];
sprintf(z, "[%s]", pad(INT_MAX - 5000, 20, '=', PAD_LEFT));
--------------------------------------------------------------------
but this still leaves the problem of buffer overflow, which I'm trying
to minimize.
Oct 28 '08 #37

P: n/a
Pilcrow said:

<snip>
I see that I didn't express myself clearly enough. I want the user to
provide a pointer for a buffer, but not actally to provide space for it.
I want my function to allocate memory for that buffer. I will put the
result in that buffer. I want the user to free that memory when he/she
is done with it.
Fine, so pass a pointer to a pointer.

On my Web site, I have a routine that takes an arbitrarily long line from
the user. It accepts a pointer to pointer from the caller, and uses that
as an existing buffer, UNLESS it's a null pointer, in which case it
allocates a nice shiny new one.

That code doesn't have the same functionality you need, but it illustrates
the technique that you're asking about.

http://www.cpax.org.uk/prg/writings/fgetdata.php
free(s);
s = malloc(width+1);
assert(s != NULL);
Bad idea. Use assertions only when the program is incorrectly written.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -http://www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Oct 28 '08 #38

P: n/a
On Tue, 28 Oct 2008 13:48:05 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>
Using gcc in mingw on a windows machine.. All these varying 'standards'
have me dizzy.

If you pick two sets of strict options, one for C90 and one for C99
the compiler will tell you if you have used C99 features when you
don't mean to, or (in the second case) when you use implementation
specific features when you don't want to. This is one of the most
helpful things a compiler can do if you are writing library code like
this that should compile "almost everywhere". (For gcc and
derivatives -std=c89 -pedantic -Wall -Wextra is a good starting
point).
Thank you.

char buf[sizeof(int) * CHAR_BIT + 5) / 3];
I assume that you meant
char buf[(sizeof(int) * CHAR_BIT +) /3];
but I fail to understand the significance of the value between the
square brackets. It evaluates to 12 on my system.

==============================

Ok, Mr H & Mr B. I have my current code for the function below. And I
can now call it like this:
---------------------------------------------
char *str;
int num = 123;
str = pad(num, 20, '*', PAD_RIGHT);
puts(str);
str = pad(INT_MAX - 5000, 20, '=', PAD_LEFT);
puts(str);
---------------------------------------------

and I think I understand that, if I now say free(str), since the pointer
*str points to the same area as the ptr *s in the subroutine, that the
area of memory freed is the area that was allocated in the subroutine.
No?

But what if I said
--------------------------------------------
printf("%s",pad(INT_MAX - 5000, 20, '=', PAD_LEFT));
--------------------------------------------
which I have found to work, how would I free the memory allocated in the
function?

And, Mr H, your <http://www.cpax.org.uk/prg/writings/fgetdata.phpwas
what I had in mind, but I was incapable of using it.. I'll try again.
"We live to learn".

Oh, here's the current code. As you see, I have taken your comments to
heart, both of you, and I thank you both,
-----------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

#define PAD_RIGHT 0
#define PAD_LEFT 1

int digits(int n) /* how many digits in an integer */
{
if(n==0) return 1;
int sign = n;
n = abs(n);
int ct = 0;
while(n 0) {
n /= 10;
ct++;
}
if(sign < 0) ct++;
return ct;
}

char *pad( /* func returns ptr to start of string */
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
char *s; /* ptr to output string */
int count = 0; /* count of characters */
int dig = digits(n); /* space required for the number */
if(dig width) {
fputs("Field not big enough for data");
exit (EXIT_FAILURE); /* maybe I should truncate? */
}

free(s);
s = malloc(width+1); /* get necessary memory */
if(s == NULL){
fputs("Inadequate memory!", stderr);
exit (EXIT_FAILURE);
}

char *t = s; /* save ptr */
if (rl == PAD_RIGHT) {
count = sprintf(t, "%d", n); /* insert num */
t += count; /* bump ptr */
while(count++ < width) /* pad on right */
*t++ = padch;
*t = '\0'; /* finish string */
}else{
while(count++ < width-dig) /* pad on left */
*t++ = padch;
sprintf(t, "%d", n); /* insert num */
}
return s; /* return ptr to start of string */
}
-----------------------------------------------------------------------

Oct 28 '08 #39

P: n/a
Pilcrow <Pi******@gmail.comwrites:
On Tue, 28 Oct 2008 13:48:05 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
<snip>
> char buf[sizeof(int) * CHAR_BIT + 5) / 3];
I assume that you meant
char buf[(sizeof(int) * CHAR_BIT +) /3];
You got the missing '(' but you've made your own typo! I think we both
mean:

char buf[(sizeof(int) * CHAR_BIT + 5) / 3];
but I fail to understand the significance of the value between the
square brackets. It evaluates to 12 on my system.
It is one way to get a number the is bound to be big enough for the
decimal representation of an int (including sign and terminating
null). It is usually a bit too big but that hardly ever matters.
There are other expressions you can use -- search the archives of this
list to see some but most involve dividing by 3 as an approximation of
the base-2 log of 10 which is the conversion factor between the number
bits and the number of decimal digits.
==============================

Ok, Mr H & Mr B. I have my current code for the function below. And I
can now call it like this:
---------------------------------------------
char *str;
int num = 123;
str = pad(num, 20, '*', PAD_RIGHT);
puts(str);
str = pad(INT_MAX - 5000, 20, '=', PAD_LEFT);
puts(str);
---------------------------------------------

and I think I understand that, if I now say free(str), since the pointer
*str points to the same area as the ptr *s in the subroutine, that the
area of memory freed is the area that was allocated in the subroutine.
No?
Yes, but you need one call to free for each call of pad.
But what if I said
--------------------------------------------
printf("%s",pad(INT_MAX - 5000, 20, '=', PAD_LEFT));
--------------------------------------------
which I have found to work, how would I free the memory allocated in the
function?
You just need to remember the returned pointer:

printf("%s", (s = pad(INT_MAX - 5000, 20, '=', PAD_LEFT)));
free(s);

<snip>

--
Ben.
Oct 28 '08 #40

P: n/a
Pilcrow <Pi******@gmail.comwrites:
On Tue, 28 Oct 2008 18:40:49 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
>>Pilcrow <Pi******@gmail.comwrites:
<snip>
>>---------------------------------------------
char *str;
int num = 123;
str = pad(num, 20, '*', PAD_RIGHT);
puts(str);
str = pad(INT_MAX - 5000, 20, '=', PAD_LEFT);
puts(str);
---------------------------------------------

and I think I understand that, if I now say free(str), since the pointer
*str points to the same area as the ptr *s in the subroutine, that the
area of memory freed is the area that was allocated in the subroutine.
No?

Yes, but you need one call to free for each call of pad.

I think I'm right this time, since I have, in the function,
-------------------------------------------------------------
free(s);
s = malloc(width+1);
-------------------------------------------------------------
so I don't need to say free until after the last call to pad
No, sorry, but I am right about this. Inside pad, the call to free is
an error. You have, in essence, this code:

char *s;
/* code that does not set s */
free(s);

This is undefined behaviour because s is indeterminate. By using
'static' you could arrange for s to be remembered between calls but
the would not be the right thing to do. I might need 30 padded
strings all available at once -- a call to pad must not free the last
string allocated, even if you can arrange for it to do so.

The user of pad must call free, once for each use of pad.

--
Ben.
Oct 29 '08 #41

P: n/a
On Wed, 29 Oct 2008 11:14:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
[snip]
>No, sorry, but I am right about this. Inside pad, the call to free is
an error. You have, in essence, this code:

char *s;
/* code that does not set s */
free(s);

This is undefined behaviour because s is indeterminate. By using
'static' you could arrange for s to be remembered between calls but
the would not be the right thing to do. I might need 30 padded
strings all available at once -- a call to pad must not free the last
string allocated, even if you can arrange for it to do so.

The user of pad must call free, once for each use of pad.
Well, did some tests. Am now really confused. I hope somebody can
explain this?!
-----------------------------------------------------------------------
C:\test>cat *
/* pad.h */
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

#define PAD_RIGHT 0
#define PAD_LEFT 1

int digits(int n) /* how many digits in an integer */
{
if(n==0) return 1;
int sign = n;
n = abs(n);
int ct = 0;
while(n 0) {
n /= 10;
ct++;
}
if(sign < 0) ct++;
return ct;
}

char *pad( /* func returns ptr to start of string */
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
char *s; /* ptr to output string */
int count = 0; /* count of characters */
int dig = digits(n); /* space required for the number */
if(dig width) {
fputs("Field not big enough for data", stderr);
exit (EXIT_FAILURE);
}

free(s);
s = malloc(width+1); /* get necessary memory */
if(s == NULL){
fputs("Inadequate memory!", stderr);
exit (EXIT_FAILURE);
}

char *t = s; /* save ptr */
if (rl == PAD_RIGHT) {
count = sprintf(t, "%d", n); /* insert num */
t += count; /* bump ptr */
while(count++ < width) /* pad on right */
*t++ = padch;
*t = '\0'; /* finish string */
}else{
while(count++ < width-dig) /* pad on left */
*t++ = padch;
sprintf(t, "%d", n); /* insert num */
}
return s; /* return ptr to start of string */
}

/* tst1.c */
#include "pad.h"

int main(void)
{
puts("this is tst1.c");
char *a;
a = pad(1, 3, '*', PAD_LEFT);
char *b;
b = pad(2, 3, '*', PAD_LEFT);
char *c;
c = pad(3, 3, '*', PAD_LEFT);
puts(a);
puts(b);
puts(c);

}
/* tst2.c */
#include "pad.h"

int main(void)
{
puts("this is tst2.c");
char *a;
a = pad(1, 3, '*', PAD_LEFT);
puts(a);
char *b;
b = pad(2, 3, '*', PAD_LEFT);
puts(b);
char *c;
c = pad(3, 3, '*', PAD_LEFT);
puts(a);
puts(b);
puts(c);

}

C:\test>gcc tst1.c -otst1

C:\test>gcc tst2.c -otst2

C:\test>tst1
this is tst1.c
**3
**3
**3

C:\test>tst2
this is tst2.c
**1
**2
**1
**2
**3

C:\test>
-----------------------------------------------------------------------
Oct 29 '08 #42

P: n/a
Pilcrow <Pi******@gmail.comwrites:
char *pad( /* func returns ptr to start of string */
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
char *s; /* ptr to output string */
int count = 0; /* count of characters */
int dig = digits(n); /* space required for the number */
if(dig width) {
fputs("Field not big enough for data", stderr);
exit (EXIT_FAILURE);
}

free(s);
I sense a demonsneeze coming.

Phil
--
Christianity has such a contemptible opinion of human nature that it does
not believe a man can tell the truth unless frightened by a belief in God.
No lower opinion of the human race has ever been expressed.
-- Robert Green Ingersoll (1833-1899), American politician and scientist
Oct 29 '08 #43

P: n/a
Pilcrow wrote:
On Wed, 29 Oct 2008 11:14:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
[snip]
No, sorry, but I am right about this. Inside pad, the call to free is
an error. You have, in essence, this code:

char *s;
/* code that does not set s */
free(s);

This is undefined behaviour because s is indeterminate.
....
Well, did some tests. Am now really confused. I hope somebody can
explain this?!
Well, that's simple. The behavior of your program is undefined. As a
result, there is nothing that counts as incorrect output from your
program. It could print out the text of "Hamlet", and that would be
correct output. Only when you've fixed the bug that has been
repeatedly brought to your attention will it be possible to talk
meaningfully about what the behavior of your program should be.

....
{
char *s; /* ptr to output string */
's' has not been initialized here. As a result, it's value is
indterminate.
int count = 0; /* count of characters */
int dig = digits(n); /* space required for the number */
if(dig width) {
fputs("Field not big enough for data", stderr);
exit (EXIT_FAILURE);
}
's' has still not been given a value.
free(s);
One of the possibilities for objects with an indeterminate value is
that they may contain a trap representation. If that's the case, any
use of the value of 's' has undefined behavior, regardless of whether
it is passed to free(). Even if 's' doesn't have a trap
representation, you're still passing a value to free() about which you
know absolutely nothing. You should never pass a value to free() which
was not returned by either malloc(), calloc(), or realloc(); if you
pass it any other value, the behavior is undefined. You have no way of
knowing what value is being passed to free(), which means it's
overwhelmingly likely to be a value that cannot be safely passed to
free().
Oct 29 '08 #44

P: n/a
On Wed, 29 Oct 2008 19:42:23 +0200, Phil Carmody
<th*****************@yahoo.co.ukwrote:
>Pilcrow <Pi******@gmail.comwrites:
>char *pad( /* func returns ptr to start of string */
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
char *s; /* ptr to output string */
int count = 0; /* count of characters */
int dig = digits(n); /* space required for the number */
if(dig width) {
fputs("Field not big enough for data", stderr);
exit (EXIT_FAILURE);
}

free(s);

I sense a demonsneeze coming.

Phil
Your remarks are always so helpful and so clearly expressed! I always
wait for your input.

PS: Robert Green Ingersoll was a renowned orator, free-thinker,
politician and lawyer.. I never heard that he was a scientist.

Oct 29 '08 #45

P: n/a
Pilcrow <Pi******@gmail.comwrites:
On Wed, 29 Oct 2008 19:42:23 +0200, Phil Carmody
<th*****************@yahoo.co.ukwrote:
>>Pilcrow <Pi******@gmail.comwrites:
>>char *pad( /* func returns ptr to start of string */
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
char *s; /* ptr to output string */
int count = 0; /* count of characters */
int dig = digits(n); /* space required for the number */
if(dig width) {
fputs("Field not big enough for data", stderr);
exit (EXIT_FAILURE);
}

free(s);

I sense a demonsneeze coming.

Your remarks are always so helpful and so clearly expressed! I always
wait for your input.
Well you should be idly waiting, you should be reading and learning.

Google for "demons fly out of your nose", and also read all the
other responses correcting you in this thread. If you refuse to
learn, there's no point trying to teach you.

Phil
--
Christianity has such a contemptible opinion of human nature that it does
not believe a man can tell the truth unless frightened by a belief in God.
No lower opinion of the human race has ever been expressed.
-- Robert Green Ingersoll (1833-1899), American politician and orator
(Thank you for the correction. See - learning from others is easy!)
Oct 29 '08 #46

P: n/a
On Wed, 29 Oct 2008 22:29:10 +0200, Phil Carmody
<th*****************@yahoo.co.ukwrote:
>Pilcrow <Pi******@gmail.comwrites:
>On Wed, 29 Oct 2008 19:42:23 +0200, Phil Carmody
<th*****************@yahoo.co.ukwrote:
>>>Pilcrow <Pi******@gmail.comwrites:
char *pad( /* func returns ptr to start of string */
int n, /* number to print */
size_t width, /* pad to this width */
int padch, /* character to pad with */
int rl) /* pad on right (0) or left (1) */
{
char *s; /* ptr to output string */
int count = 0; /* count of characters */
int dig = digits(n); /* space required for the number */
if(dig width) {
fputs("Field not big enough for data", stderr);
exit (EXIT_FAILURE);
}

free(s);

I sense a demonsneeze coming.

Your remarks are always so helpful and so clearly expressed! I always
wait for your input.

Well you should be idly waiting, you should be reading and learning.

Google for "demons fly out of your nose", and also read all the
other responses correcting you in this thread. If you refuse to
learn, there's no point trying to teach you.

Phil
<http://www.urbandictionary.com/define.php?term=demonsneeze>
<http://www.urbandictionary.com/define.php?term=Demonophobia>
<http://www.noisebot.com/images/darkside2-thumb.gif>
<http://www.noisebot.com/images/roundhouse-thumb.gif>

Want to buy a duck?
Oct 29 '08 #47

P: n/a
On Wed, 29 Oct 2008 11:37:18 -0700 (PDT), jameskuyper
<ja*********@verizon.netwrote:
>Pilcrow wrote:
>On Wed, 29 Oct 2008 11:14:27 +0000, Ben Bacarisse <be********@bsb.me.uk>
wrote:
[snip]
>No, sorry, but I am right about this. Inside pad, the call to free is
an error. You have, in essence, this code:

char *s;
/* code that does not set s */
free(s);

This is undefined behaviour because s is indeterminate.
...
>Well, did some tests. Am now really confused. I hope somebody can
explain this?!

Well, that's simple. The behavior of your program is undefined. As a
result, there is nothing that counts as incorrect output from your
program. It could print out the text of "Hamlet", and that would be
correct output. Only when you've fixed the bug that has been
repeatedly brought to your attention will it be possible to talk
meaningfully about what the behavior of your program should be.

...
>{
char *s; /* ptr to output string */

's' has not been initialized here. As a result, it's value is
indterminate.
> int count = 0; /* count of characters */
int dig = digits(n); /* space required for the number */
if(dig width) {
fputs("Field not big enough for data", stderr);
exit (EXIT_FAILURE);
}

's' has still not been given a value.
> free(s);

One of the possibilities for objects with an indeterminate value is
that they may contain a trap representation. If that's the case, any
use of the value of 's' has undefined behavior, regardless of whether
it is passed to free(). Even if 's' doesn't have a trap
representation, you're still passing a value to free() about which you
know absolutely nothing. You should never pass a value to free() which
was not returned by either malloc(), calloc(), or realloc(); if you
pass it any other value, the behavior is undefined. You have no way of
knowing what value is being passed to free(), which means it's
overwhelmingly likely to be a value that cannot be safely passed to
free().
Thank you very much. I have learned. Fixed code.

--
You are a gentleman and a scholar
and a judge of fine whiskey.
Oct 29 '08 #48

P: n/a
Pilcrow wrote:
....
... criticizing others for their rudeness is, in itself, rude.
Miss Manners (Judith Martin) 2008-11-05: "It is not uncommon for rude
people to act offended when their rudeness is not tolerated. Miss
Manners assures you that this does not make it rude to refule to
tolerate rudeness, so long as this is not done with retaliatory
rudeness."

I don't think Ben's remarks can be described as having been done "with
retaliatory rudeness". He just said " I don't know if I am one of the
people you are being rude about,".
Nov 5 '08 #49

P: n/a
Richard Heathfield <rj*@see.sig.invalidwrites:
Pilcrow said:
free(s);
s = malloc(width+1);
assert(s != NULL);

Bad idea. Use assertions only when the program is incorrectly written.
Using assertions inappropriately means the program is incorrectly
written, wouldn't you say? ;) ;) ;)
Nov 10 '08 #50

52 Replies

This discussion thread is closed

Replies have been disabled for this discussion.