Solved

parameters...

Posted on 2002-06-06
12
239 Views
Last Modified: 2010-04-02
Hi!
i want to create a function which will use an undefined number of parameters (like printf, execlp...)
but i have no idea about how to do this.
thanks, Ralph
0
Comment
Question by:ralph78
12 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 7058913
If you have VC++, check out the CString implementation as an example.

void FormatV(const TCHAR * lpszFormat, va_list argList)
{
}

void Format(const TCHAR * lpszFormat, ...)
{
     va_list argList;
     va_start(argList, lpszFormat);
     FormatV(lpszFormat, argList);
     va_end(argList);
}
0
 
LVL 86

Expert Comment

by:jkr
ID: 7059065
Or this examle from the VC++ docs:

Example

/* VA.C: The program below illustrates passing a variable
 * number of arguments using the following macros:
 *      va_start            va_arg              va_end
 *      va_list             va_dcl (UNIX only)
 */

#include <stdio.h>
#define ANSI            /* Comment out for UNIX version     */
#ifdef ANSI             /* ANSI compatible version          */
#include <stdarg.h>
int average( int first, ... );
#else                   /* UNIX compatible version          */
#include <varargs.h>
int average( va_list );
#endif

void main( void )
{
   /* Call with 3 integers (-1 is used as terminator). */
   printf( "Average is: %d\n", average( 2, 3, 4, -1 ) );

   /* Call with 4 integers. */
   printf( "Average is: %d\n", average( 5, 7, 9, 11, -1 ) );

   /* Call with just -1 terminator. */
   printf( "Average is: %d\n", average( -1 ) );
}

/* Returns the average of a variable list of integers. */
#ifdef ANSI             /* ANSI compatible version    */
int average( int first, ... )
{
   int count = 0, sum = 0, i = first;
   va_list marker;

   va_start( marker, first );     /* Initialize variable arguments. */
   while( i != -1 )
   {
      sum += i;
      count++;
      i = va_arg( marker, int);
   }
   va_end( marker );              /* Reset variable arguments.      */
   return( sum ? (sum / count) : 0 );
}
#else       /* UNIX compatible version must use old-style definition.  */
int average( va_alist )
va_dcl
{
   int i, count, sum;
   va_list marker;

   va_start( marker );            /* Initialize variable arguments. */
   for( sum = count = 0; (i = va_arg( marker, int)) != -1; count++ )
      sum += i;
   va_end( marker );              /* Reset variable arguments.      */
   return( sum ? (sum / count) : 0 );
}
#endif


0
 
LVL 22

Expert Comment

by:nietod
ID: 7059438
You might want to reconsider this.

variable argument (VA) functions are widely considered to be the leading cause of bugs in C programs.  (This has been measured empirically.)   Because VA function do not perform type check on their parameters it is easy to pass invalid data to a VA function and the compiler will not catch it.

C++ provides many great alternatives to VA functions.   Its likely that an alternative will work just as well for you.

What is it that you are hoping to achieve?
0
 
LVL 4

Expert Comment

by:IainHere
ID: 7059465
ralph78, it might well be the case that this is the best way to do what you're attempting, but consider that C++ offers stringstreams as an alternative to printf for a reason.

The types of the final parameter[s] passed are only checked at run time, and can lead to Hard To Find errors.

printf("%d", "oops");
cout << "no oops";

Maybe you can implement a different interface?
0
 
LVL 4

Expert Comment

by:IainHere
ID: 7059467
ARGH! Followed nietod here, but you hadn't posted when I started - apologies.
0
 
LVL 22

Expert Comment

by:nietod
ID: 7059474
No problem.

Note that its very likely that this does not concern outputting the information.   I think ralph78 only used printf() asn an example of a function that takes an unspecified number of parameters, not necessarily one that performs the desired operation.   However, the C++ stream objects are an example of one alternative solution to VA functions.
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 

Author Comment

by:ralph78
ID: 7061524
ok, thank u all!
i'll search for an alternative
(i'm writing a VECTOR class (i can't use STL), and it's about vectors of undefined dimensions.
i need a "Set" method, which will set the attributes of a VECTOR.
for instance:

VECTOR v(4);    //4d vector
v.Set(4,1,2,3,4); //1st param is the number of parameters
0
 
LVL 4

Expert Comment

by:IainHere
ID: 7061540
This is an excellent description of your options:

http://www.cuj.com/articles/2000/0012/0012c/0012c.htm
0
 
LVL 22

Accepted Solution

by:
nietod earned 50 total points
ID: 7061668
>> i'll search for an alternative
Well the VA procedures suggested by Axter and others will certainly work.  You woudl have something like

class Vector
{
    public:
       Vector(int Dimensions, ... )
};

However, I still don't recommend it very hardily.   There is nothing to prevent you from doing

Vector V1(3,10); // Error, missing a dimension, may crash.
Vector V2(2,10,20,30); // Error there is a extra dimension, it will probably be missed, but
                                // maybe you wan't it to be a 3D vector.
Vector V2(10);  // Error, forgot to specify the number of dimensions (1) before the size.
Vector V2(1,"I have no clue"); // Error, who knows what size this will be.

None of these errors--and others will be detected by the compiler.  

Now there are alternatives.  If you don't mind breaking this up into multiple operations, you can have one function set the number of dimensions and another function set the size of each dimension.  Like

Vector V;

V.SetNoDimensions(2); // Set to 2 dimesnsions.
V.SetSize(1,20); // Set size of 1st dimension.
V.SetSize(2,30); // Set size of 2nd dimension.
V.SetSize(3.40); // Error.  But at least it has predictable behavior and you can catch it.  (not as nice as a compile-time error though.

Another option is to place the sizing information into a seperate class.   This is an extremely powerful type of solution.   It allows you to delegate properties used during constructio--or other times in the class to sub-classes.  These classes may be written later on or by other programmers.  A very powerful technique.   Just oen example Might be

// The base class.  Defines the 2 interface rfunctiosn the other classes need to provide.
class DimensionConstructorBase
{
public:
    virtual ~DimensionConstructorBase() {} = 0;
    virtual int GetNoDimensions() const = 0;
    virtual int GetDimensionSize(int Dim) const = 0;
};

// Class for a 1D array.
class Dimension1 : public DimensionConstructorBase
{
   int S[1];
public:
     // Constructor specifies the size of dimension.
     Dimension1(int S1) { S[0] = S1; };

     // indicates there is only 1 dimension.
     virtual int GetNoDimensions() const { return 1; }

    // Indicates the size of dimession 1;
    virtual int GetDimensionSize(int Dim) const  { assert(Dim <= 1;  return S[Dim - 1]; }
};


// Class for a 2D array.
class Dimension2 : public DimensionConstructorBase
{
   int S[2];
public:
     // Constructor specifies the size of dimension.
     Dimension2(int S1, int S2) { S[0] = S1; S[1] = S2; };

     // indicates there is only 1 dimension.
     virtual int GetNoDimensions() const { return 1; }

    // Indicates the size of dimession 1;
    virtual int GetDimensionSize(int Dim) const  { assert(Dim <= 1;  return S[Dim  - 1]; }
};

// and so on up to the number of dimesions you expect to support.
// (more dimensions can be added later and templates can be used to help with this.

You could then use it like

Vector V1(Dimension2(10,20));  // Constructor a 2 D array.
Vector V1(Dimension3(10,20,30));  // Constructor a 3 D array.
Vector V1(Dimension2(10,20,30));  // Error is this 2D or 3D?  Cought at compile time.

continues
0
 
LVL 22

Expert Comment

by:nietod
ID: 7061680
You could also do this with a single dimension class (unlike the version above that uses 1 class for each number of dimesions you want to support).  To do this the class would record the number of dimesions on a dynamic array.  Like

class Dimesion
{
    vector<int> S;
public:
     // Constructor takes first dimension.
     Dimension(int S1) { S.push_back(S1); };
     // Add an additional dimension.
     // Returns a reference to itself for "chaining"--look at how it is used.
     // A shorter name is probably better.
     Dimension & AddDimension(int Sn) { S.push_back(Sn);   return *this;  };
     // Get the number of dimesions.
     int GetNoDimensions() { return S.size(); };
      // Get the size of a particular dimension.
     int GetDimension(int i) {  return S[i]; };
}


You would use this like

Vector V( Dimension(10)); // Create a 1D vector. (10)
Vector V( Dimension(10).AddDimension(20) );  // Create a 2D vector.  (10 X 20).
Vector V( Dimension(10).AddDimension(20).AddDimension(30 );  // Create a 3D vector.  (10 X 20 X 30).

You could also give the class  a few different constructors, so the common dimesions (1, 2, and 3) could all be handled without chaining to AddDimension.().
0
 

Expert Comment

by:GregToombs
ID: 7061810
I'd suggest writing a linked list class describing the dimensions of the vector. For something like your Set function, then, all you'd have to do is pass a reference to the class.

-Greg
0
 
LVL 22

Expert Comment

by:nietod
ID: 7061938
I wish I had thought of that.
0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Suggested Solutions

This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now