Click to See Complete Forum and Search --> : C, variable arguements, and string structure fields
BrianDrozd
06-07-2001, 01:30 PM
Okay, here's the situation.
I have a variable arguement function that uses the va_list, va_start, etc. macros. I am trying to pass into this function a string field of a structure. The exact function call is: f(where, format, tabular_data[i].l1, tabular_data[i].d1, tabular_data[i].s1) where 'where' and 'format' are strings, and tabular_data is an array of a structure consisting of a long value (l1), a double value (d1), and a string field (s1).
The problem is that when I try extracting the string from the va_list with va_arg, I get back something that isn't a valid string and the program crashes when I then try to print the string to the screen.
Does anyone have any suggestions on what I might be doing wrong?
TheLinuxDuck
06-07-2001, 03:09 PM
Firstly, let me say that I know very little about the va_ usage, so I can't really offer anything valuable in regards to that.
Might I suggest an alternate method?
Instead of passing in each item like that as a variable list, why not simply pass in a pointer to the array, and do the fancy stuff inside the function?
Or, if you're formatting the data into a string 'where', just use sprintf, since it is already in place and works well.
BrianDrozd
06-07-2001, 03:44 PM
Originally posted by TheLinuxDuck:
<STRONG>Firstly, let me say that I know very little about the va_ usage, so I can't really offer anything valuable in regards to that.
Might I suggest an alternate method?
Instead of passing in each item like that as a variable list, why not simply pass in a pointer to the array, and do the fancy stuff inside the function?
Or, if you're formatting the data into a string 'where', just use sprintf, since it is already in place and works well.</STRONG>
Unfortunately there are no viable alternate methods. This function is supposed to decode the variable arguements and arrange them into a message to be sent across a socket. The cost of converting numbers to ascii and back again is unacceptable for this project, so I can't use sprintf. I really need the variable arguements here.
And, I can't simply pass in the entire array. This function is to be part of an API, and so doesn't have access to the structure information for the local program I'm using to test it.
TheLinuxDuck
06-07-2001, 04:06 PM
Here is the link (http://www.codeexamples.org/cgi-bin/c2h/c2h.cgi?type=HTMLdetail&filename=varargs.c) to an example on the ccae website that uses the variable argument list. I don't know if it will help you or not, but it can't hurt to take a look.
pinoy
06-07-2001, 05:50 PM
if your code's not too long, can you post it.
TheLinuxDuck
06-07-2001, 05:52 PM
^^^^ this is the good fellow who posted the va_ example at ccae.. (^=
BrianDrozd
06-08-2001, 08:09 AM
Okay. I can't post the entire code; beyond the fact that it would be far too long, it'd also probably be a breach of confidentiality. Nevertheless here are bits of the code.
typedef struct {
long l1;
double d1;
char s1[10];
} tabular_record;
static tabular_record tabular_data[50]; /* for tabular data */
void init_tabular_data ()
{
int i;
double d = 1.0145;
char buf[10];
for (i=0; i<50; i++)
{
tabular_data[i].l1 = i+1;
tabular_data[i].d1 = d * (i+1);
sprintf(tabular_data[i].s1,"Record %2d",i);
tabular_data[i].s1[9] = 0;
}
}
void main (int argc, char **argv)
{
int i;
init_tabular_data ();
// Extra code goes here
for (i=0; i<50; i++)
sendData (("tablejunk", "lfc", tabular_data[i].l1, tabular_data[i].d1, tabular_data[i].s1);
// and here
}
void sendData (String_t key, String_t format, ...)
{
va_list vl;
int i, j, len;
va_start (vl, format);
i = 0; j = 0;
len = strlen (format);
arraylength = 0;
array = NULL;
ln = '\n';
while (i < len)
{
switch (format[i])
{
case 'c':
fprintf (stdout, "\t%s%c", va_arg(vl, char*),ln);
break;
case 'd':
fprintf (stdout, "\t%15.6E%c", va_arg(vl, double),ln);
break;
case 'l':
fprintf (stdout, "\t%08X%c", va_arg(vl, long),ln);
break;
default:
break;
}
i++;
}
fflush (stdout);
va_end (vl);
}
The code outputs the integer value and double value but then crashes while trying to output the string.
Though right now I am only echoing the sent data to the screen, I will eventually need to package the data so it can be sent across a socket, so as I mentioned v*printf functions will not work for me here.
-- Fixed up the code sample.
[ 08 June 2001: Message edited by: BrianDrozd ]
TheLinuxDuck
06-08-2001, 08:51 AM
Brian:
Just upon first glance, there are a few things that don't make sense. One is that the variable 'len' never appears to be assigned anything. That would cause the while loop to do undeterminmed things, since there is no way to determine when the variable 'i' will be greater than 'len'. Secondly, variable 'ln' in the fprintf doesn't seem to be given any data anywhere, either..
It looks as though some vital parts of the code aren't there.. (^=
BrianDrozd
06-08-2001, 04:00 PM
Originally posted by TheLinuxDuck:
<STRONG>Brian:
Just upon first glance, there are a few things that don't make sense. One is that the variable 'len' never appears to be assigned anything. That would cause the while loop to do undeterminmed things, since there is no way to determine when the variable 'i' will be greater than 'len'. Secondly, variable 'ln' in the fprintf doesn't seem to be given any data anywhere, either..
It looks as though some vital parts of the code aren't there.. (^=</STRONG>
Sorry about that. I started to re-write the code to make it cleaner, but haven't finished yet, so I had to try restoring it from memory. It should be corrected now.
pinoy
06-08-2001, 07:51 PM
I can't see anything obvious that's wrong. Looks fine to me. Unfortunately I don't have a compiler at home so I can't test it.
Anyway try this version (remember I don't have a compiler to verify this, but it should work).
typedef char * String_t;
void sendData(String_t key, String_t format, ...)
{
va_list vl;
va_start(vl, format);
printf("Key %s\n", key);
while (*format) {
switch (*format) {
case 'c':
fprintf(stdout, "\t%s\n", va_arg(vl, char*));
break;
case 'd':
fprintf(stdout, "\t%15.6E\n", va_arg(vl, double));
break;
case 'l':
fprintf(stdout, "\t%08X\n", va_arg(vl, long));
break;
}
format++;
}
fflush(stdout);
va_end(vl);
}