Thread: return values from function with variable number of arguments

  1. #1
    Registered User
    Join Date
    Sep 2005
    Posts
    6

    return values from function with variable number of arguments

    Hi all,

    In C/C++ it is possible to create a function that takes a variable number of arguments using the va_list type found in stdarg.h. These arguments can be used as input for the function.

    Does anybody know if it is possible to create a function where a variable number of arguments can be used as output. So that each of the arguments gets a new value assigned. I would like to create something like this:

    Code:
    void   CopyResult(int numberArgs, ...) { 
       va_list   argp; 
       va_start(argp, numberArgs); 
       for(int i = 1; i < numberArgs; i++)  { 
          //assign argument 'i' here 
          ..... 
          va_arg(argp, int);  } 
       va_end(argp); 
       } 
    }
    Using an array is not possible for me. Since I plan to extend the function to not only take a variable number of arguments but also variable types.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    You mean the same way that scanf() type functions can store many answers?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2005
    Posts
    6
    Exactly

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    Sure, you do what you're doing now, except your va_arg needs to extract pointers (which you then dereference and store a value there).
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Sep 2005
    Posts
    6
    Hi Salem,

    I figured out the part about passing only pointer type arguments.

    It is the the dereferencing that is baffling me. Just using a cast doesn't seem to do the trick.

    Code:
    char* TempChar;
    
    TempChar = (char*)argp;
    strcpy(TempChar , thevalue);

    PS. 8000+ posts WOW !!!

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    It's all done with va_arg and the 2nd parameter

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <stdarg.h>
    
    void foo ( int num, ... ) {
      char *p;
      va_list   argp;
      va_start(argp, num);
      p = va_arg(argp,char*);
      strcpy(p,"hello");
      p = va_arg(argp,char*);
      strcpy(p,"world");
      va_end(argp);
    }
    
    int main(void)
    {
      char s1[10], s2[10];
      foo ( 2, s1, s2 );
      printf( "%s %s\n", s1, s2 );
      return 0;
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    There is no way, with stdarg, to get the number of arguments unless YOU provide that information. You have to pass information to the function that specifies how many arguments there are. That is essentially what scanf() does, albeit indirectly: the format string specifies exactly what arguments follow it, and what type they are. And, if you have a mismatch between what's in the format string and the arguments that follow .... the result is often problematical

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    In C++ you can try some combination of a vector and boost::any.

  9. #9
    Registered User
    Join Date
    Sep 2005
    Posts
    6
    I have made some progress. This is the current state of my function:

    Code:
    bool	SQL_ResultWithValues(SQL_Output *SQL_Statement, const char *Typelist, ...) 
    {
    	int     cType, Column;
    	char   *TString = 0;
    	int    *TInt    = 0;
    	double *TDouble = 0;
    	va_list	argp;
    	
    	va_start(argp, Typelist);
    	for (int i = 1; i < strlen(Typelist); i += 2)
    	{
    		Column = (int)((i-1)/2);
    		if (!strncmp(Typelist + i - 1, "%", 1 ) )
    		{
    			cType = (int)Typelist[i];
    			switch (cType)
    			{
    			case 115 : case 83	: 	// s or S
    				TString = va_arg(argp, char*);
    				strcpy(TString, getResultAsString(SQL_Statement, Column) );
    			break;
    			case 100 : case 68	: 	// d or D
    				TInt	= va_arg(argp, int*);
    				// getResultAsInt returns an int
    				TInt	= (int*)getResultAsInt(SQL_Statement, Column);
    			break;
    			case 102 : case 70	: 	// f or F
    				TDouble = va_arg(argp, double*);									
    				// next statement gives compiler error 'cannot convert double* to double'
    				// getResultAsDouble returns a double
    				TDouble = (double*)getResultAsDouble(SQL_Statement, Column);
    			break;
    			default				:
    				printf("Unknown Type in Typelist: %s at position %d Token=%s\n",
    				Typelist, i, Typelist[i]);
    				va_end(argp);
    				return false;
    			break;
    			}
    		}
    		else
    		{	printf("Error parsing Typelist: %s at position %d\n", Typelist, i);
    			return false;
    		}
    	}
    	va_end(argp);
    	return true;
    }
    I am calling this function for example with:

    Code:
    int    ID;
    double Value;
    char   Remark[100];
    		
    DB->SQL_ResultWithValues(&SQLOut, "%d%f%s", &ID, &Value, &Remark);
    
    printf("%d,%f,%s\n", ID, Value, Remark );
    The Typelist parameter gives the number of arguments and it's type. (and yes the % characters aren't really necessary). I
    agree with grumpy that there is a risk of mismatches between Typelist and actual types.
    I am not familiar (yet) with 'boost::any'


    For string type values everything works perfect.
    For integers no values are returned.
    For doubles I get an compiler error.

    So I think i'm on the right track, but the code needs some tweeking.

    I am using DevC with gcc 3.4.2
    Last edited by evo_x; 09-26-2005 at 02:50 PM.

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    > case 115 : case 83
    Write this for readability
    case 's' : case 'S' :

    > TInt = (int*)getResultAsInt(SQL_Statement, Column);
    Dereference, don't cast
    *TInt = getResultAsInt(SQL_Statement, Column);
    Ditto for your double result.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Registered User
    Join Date
    Sep 2005
    Posts
    6

    return values from function with variable number of arguments [SOLVED]

    Hi,

    Tried it. And it works brilliantly. Looks so simple, so why couldn't I figure it myself.

    I also used 's' etcetera instead of the ascii value. My presumption was incorrect that this is impossible when the 'switched' variable is an integer.

    Thanks for all the help.

    [SOLVED]

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Undefined Reference Compiling Error
    By AlakaAlaki in forum C++ Programming
    Replies: 1
    Last Post: 06-27-2008, 11:45 AM
  3. Troubleshooting Input Function
    By SiliconHobo in forum C Programming
    Replies: 14
    Last Post: 12-05-2007, 07:18 AM
  4. returning char arrays!!!!
    By bobthebullet990 in forum C Programming
    Replies: 2
    Last Post: 03-30-2006, 07:05 AM
  5. help with a source code..
    By venom424 in forum C++ Programming
    Replies: 8
    Last Post: 05-21-2004, 12:42 PM