Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C Programming (http://www.velocityreviews.com/forums/f42-c-programming.html)
-   -   vsprintf(char *str, const char *format, va_list ap, ...)? (http://www.velocityreviews.com/forums/t442757-vsprintf-char-str-const-char-format-va_list-ap.html)

goldfita@signalsguru.net 05-14-2006 11:19 PM

vsprintf(char *str, const char *format, va_list ap, ...)?
 
My last post -
http://groups.google.com/group/comp....df6ab20a6007d0

I have a little bit more challenging question this time. Suppose I
have

write_cmd(struct ast_connection *conn, char *msg, ...);

I want to call it like (forgive the syntax)

write_cmd(conn, str, p1, p2, ..., pn, k1, k2, ..., km);

The parameters p1 to pn must be passed to write_cmd every time. The
parameters k1 to km are not actually constant, but they are accessible
from conn; so, I don't really need to pass them in. It would be better
to call

write_cmd(conn, str, p1, p2, ..., pn);

However, as noted in the last post, I want to print the parameters
using vsprintf, which means they all need to be in the list. I could
follow vsprintf with sprintf to get the rest of k1 to Km, and thus
roughly double both the buffer space and processing time. But this
seems silly given that I could get those parameters into the list by
calling the first write_cmd.

I have some code which obviously doesn't work. But you can probably
see what I'm aiming for. I could probably also do it with a vsprintf
that took a list and a variable number of parameters, if there were
such a thing...

#include <stdio.h>
#include <stdarg.h>

void vvfunc(char *msg, va_list argp, va_list argp2)
{
char buf[128];

vsprintf(buf,msg,argp); //argp2 goes here
puts(buf);
}

void vfunc2(char *msg, va_list argp, ...)
{
va_list argp2;

va_start(argp2,argp);
vvfunc(msg,argp,argp2);
va_end(argp2);
}

void func(char *msg, ...)
{
va_list argp;

va_start(argp,msg);
vfunc2(msg,argp,10); //k1
va_end(argp);
}

int main(void)
{
func("hello %s %d\n","there"); //p1
return 0;
}


JesusWaffle@gmail.com 05-15-2006 02:07 AM

Re: vsprintf(char *str, const char *format, va_list ap, ...)?
 
I don't think there's any way to do this portably. The only solution I
can think of is to implement your own vvsprintf() function which takes
two va_lists.


goldfita@signalsguru.net 05-15-2006 02:46 AM

Re: vsprintf(char *str, const char *format, va_list ap, ...)?
 

JesusWaffle@gmail.com wrote:
> I don't think there's any way to do this portably. The only solution I
> can think of is to implement your own vvsprintf() function which takes
> two va_lists.


Darn, that's kind of what I figured. I thought about implementing a
vvsprintf, but it's not worth it.


kyle.tk 05-15-2006 04:10 AM

Re: vsprintf(char *str, const char *format, va_list ap, ...)?
 

goldfita@signalsguru.net wrote:
> My last post -
> http://groups.google.com/group/comp....df6ab20a6007d0
>
> I have a little bit more challenging question this time. Suppose I
> have
>
> write_cmd(struct ast_connection *conn, char *msg, ...);
>
> I want to call it like (forgive the syntax)
>
> write_cmd(conn, str, p1, p2, ..., pn, k1, k2, ..., km);
>


Variable lists are, well, variable. There would be no way to know where
the first variable list ends and the next one begins.

va_arg lists always have to have "..." as the last argument in the
function argument list.

-kyle


rory.brandybuck@gmail.com 05-15-2006 03:03 PM

Re: vsprintf(char *str, const char *format, va_list ap, ...)?
 
There is a portable way to do it.
Replace va_arg lists by arrays and use initializers to init. the arrays
before the function call:

write_cmd(Connection_t* conn, char* str,
PParameter_t p[], int p_size,
KParameter_t k[], int k_size) ;
....
KParameter_t k[] = {{INT,1}, {INT,2}};
....
write_cmd(conn, str, p, p_size, k, SIZEOF(k)) ;
....


See example:
#include <stdio.h>

#define SIZEOF(array) \
sizeof(array) / sizeof((array)[0])

/*NOTE: belowed struct/union(s) members' names make no sense.
They have taken just for example.
*/
typedef enum{
FAKE_ARRAY, INT, STRING
} Typecode; /* use the same Typecode type in both
PParameter and KParameter for simplicity */

typedef struct Connection{
/* ... */
int fake_int;
char* fake_pchar;
} Connection_t;


typedef struct PParameter {
Typecode type;
union{
/* ... */
int fake_array[2];
char* fake_pch;
} u;
} PParameter_t;

typedef struct KParameter {
Typecode type;
union{
/* ... */
int int_fake;
char* pchar_fake;
} u;
} KParameter_t;

void
write_cmd(Connection_t* conn, char* str,
PParameter_t p[], int p_size,
KParameter_t k[], int k_size) {
int i;

printf("str: \t%s\n", str);

/* print p[] */
printf("p: ");
for (i = 0; i < p_size; ++i)
switch(p[i].type) {
case STRING:
printf("\tstring: %s\n", p[i].u.fake_pch);
break;
case FAKE_ARRAY:{
int j;
printf("\tarray: ");
for(j = 0; j < SIZEOF(p[i].u.fake_array); ++j)
printf("%d, ", p[i].u.fake_array[j]);
printf("\n");
break;
}
};

/* print k[] */
printf("k: ");
for (i = 0; i < k_size; ++i)
switch(k[i].type) {
case INT:
printf("\tint: %d\n", k[i].u.int_fake);
break;
case STRING:
printf("\tstring: %s\n", k[i].u.pchar_fake);
break;
};
}
int main() {
Connection_t conn;
/* Tested on:

Comeau C/C++ 4.3.3 (Aug 6 2003 15:13:37) for
ONLINE_EVALUATION_BETA1
MODE:strict errors C99

And:

gcc.exe (GCC) 3.4.4 (mingw special)
default compiler settings
*/
PParameter_t p[] = {{STRING, .u.fake_pch = "a string"},
{FAKE_ARRAY, {1,10}},
{STRING, .u.fake_pch = "another string"}
}; /* C99 mode initializer used */
KParameter_t k[] = {{INT,1}, {INT,2}};

write_cmd(&conn, "just a string", p, SIZEOF(p), k, SIZEOF(k));
}



All times are GMT. The time now is 08:53 PM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.