How to use asprintf consecutively

P

pozz

I have to create a long string composed by many fields, for example
integers. I don't know the numbers of fields, so I don't know the
length of the string.

I think asprintf() could be useful for such thing, so I started
writing the following code:

char *
create_string(int *array, size_t asize)
{
char *str;
while(asize--) {
if (asprintf(&str, "%s %d", str, *array++) < 0) {
return NULL;
}
}
return str;
}

I have two doubts here:
- may I use str for output string and as one of asprintf argument?
- after the second (the third...), how can I free the previous
allocated string?

Moreover, how I can free all the allocated space if one of asprintf
return a negative number?
 
I

Ike Naar

char *
create_string(int *array, size_t asize)
{
char *str;
while(asize--) {
if (asprintf(&str, "%s %d", str, *array++) < 0) {
return NULL;
}
}
return str;
}

I have two doubts here:
- may I use str for output string and as one of asprintf argument?

On at least one common platform, the manual page for asprintf says:

The functions asprintf and vasprintf are analogues of sprintf and
vsprintf, except that they allocate a string large enough to hold the
output including the terminating NUL, and return a pointer to it via
the first parameter.

and the manual page for sprintf says:

If copying takes place between objects that overlap as a result of a
call to sprintf() or snprintf(), the results are undefined.

So, it's probably not a good idea to use asprintf that way.
 
M

Martin Ambuhl

I have to create a long string composed by many fields, for example
integers. I don't know the numbers of fields, so I don't know the
length of the string.

I think asprintf() could be useful for such thing, so I started
writing the following code:

Was I asleep when asprintf() was added to the standard library?
 
B

Ben Bacarisse

pozz said:
I have to create a long string composed by many fields, for example
integers. I don't know the numbers of fields, so I don't know the
length of the string.

I think asprintf() could be useful for such thing, so I started
writing the following code:

char *
create_string(int *array, size_t asize)
{
char *str;
while(asize--) {
if (asprintf(&str, "%s %d", str, *array++) < 0) {
return NULL;
}
}
return str;
}

I have two doubts here:
- may I use str for output string and as one of asprintf argument?
- after the second (the third...), how can I free the previous
allocated string?

I don't know aprintf well enough (it's non-standard) but I think you'd
have to use a pair of pointers swapping them over and freeing the one
that acted a source each time. Take care with initial conditions!

However, here's another way...

Allocate one string for them all. You don't need more than

const size_t dec_chars = (CHAR_BIT * sizeof(int)) / 3 + 2;

bytes for the decimal representation of an int (including sign). Thus
you can allocate:

asize * dec_chars + asize

bytes for the whole thing (asize - 1 separators plus one for the null).
You can then

size_t position = 0;
for (int i = 0; i < asize; i++) {
position += sprintf(buffer + position,
"%s%d", i ? " " : "", array);

Finally, you can use position to resize the buffer if you feel you need
to. This is a sketch so, you'll have to check the details... I don't
have time to test it.

<snip>
 
S

Seebs

I think asprintf() could be useful for such thing, so I started
writing the following code:

Don't use asprintf(), it's not standard and it isn't a good design.

Fundamentally, any time you have something which isn't malloc/calloc/realloc
which is returning pointers you have to free(), you're probably screwing
yourself over.
I have two doubts here:

These are not doubts, they are questions. At least, in most varieties of
English. I think there's a word, probably in one of the languages spoken
in India, which gets translated into English as "doubt" but is also used
for something that ought to be "question".

A "doubt" is the state of having been given a piece of information, but
distrusting it or not believing it. A question is not a kind of doubt.
- may I use str for output string and as one of asprintf argument?

That seems suicidal.
- after the second (the third...), how can I free the previous
allocated string?

You can't, which is another reason this is a bad design.
Moreover, how I can free all the allocated space if one of asprintf
return a negative number?

This is one of the ways you can tell that your design is probably wrong.

Look into snprintf, and manage your own allocation. You may want to consider
the very real possibility that you are going about this entirely the wrong
way. For instance, perhaps you should scan the inputs to decide how much
total space you need in advance.

-s
 
K

Kenny McCormack

Was I asleep when asprintf() was added to the standard library?

Charming as always, I see...

--
"The anti-regulation business ethos is based on the charmingly naive notion
that people will not do unspeakable things for money." - Dana Carpender

Quoted by Paul Ciszek (pciszek at panix dot com). But what I want to know
is why is this diet/low-carb food author doing making pithy political/economic
statements?

Nevertheless, the above quote is dead-on, because, the thing is - business
in one breath tells us they don't need to be regulated (which is to say:
that they can morally self-regulate), then in the next breath tells us that
corporations are amoral entities which have no obligations to anyone except
their officers and shareholders, then in the next breath they tell us they
don't need to be regulated (that they can morally self-regulate) ...
 

Ask a Question

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.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,053
Latest member
BrodieSola

Latest Threads

Top