I have to classes, an Executer with these methods:
Executer()
struct Execute(string s)
Lookup(string name, int module, int num, ...)
and a Parser:
Parser()
struct Parse(string s)
The Exectuers Execute method calls the Parsers Parse method. The Parser then chucks the string into smaller bits (it explodes the string on the ;-sign) and returns a struct to the Execute method. This struct it uses to call the Lookup method.
The struct that the Parse returns holds some standard information:
An command name
A senderId (a username, a mac address and a password)
A variable number of arguments
And that is my problem. The Lookup method take variable arguments, but how do I handle the the hand over of these variable arguments by the struct? Im not an expert in C and C++. Should I mass the two classes togheter? So the Parser method could call the Execute method, sparing the struct away.
Or maybe there is a way of parsing an unknown variable of arguments at runtime? By some sort of array?
EDIT
I cant use the STL library from C++. I only use the C++ class and virtual feature. Im writing to an compiler where Im restricted to use almost all of the C libraries + the magic skills of C++ (virtual and class). SOory for not telling that right away.
EDIT 2
Im writing code to an embedded system and thereby using avr-gcc to compile my code. Thats why I cant use STL. The avr-gcc doesnt support this.
Use std::vector<> or a simular container that can hold an arbitrary number of entries.
struct {
std::string commandName;
sender_t senderId;
std::vector<arg_t> arguments;
};
Edit: oh, you can't use std::vector. In that case: use an array and store the length:
struct {
const char* commandName;
sender_t senderId;
int argumentCount;
int maxArgumentCount; // you might not need this
arg_t* arguments; // pointer to array of (at least) argumentCount elements.
};
Use malloc() or new() to create the array for the arguments.
I would suggest to wrap the argumentCount, maxArgumentCount and arguments in a separate class, which can handle the malloc/new and free/delete as well. This will make it easier to prevent memory leaks.
In the end, you'll have written your own vector_of_arg_t class, so maybe have a look at some basic vector implementation. There must be tutorials on that on the web.
You could declare your Lookup method as follows:
void Lookup(string name, int module, int num, std::vector<std::string> &args);
By storing the variable arguments in an args array, you can have as many as you want.
See
Q: How can I write a function which takes a variable number of arguments and passes them to some other function (which takes a variable number of arguments)?
A: In general, you cannot. Ideally, you should provide a version of that other function which accepts a va_list pointer.
Suppose you want to write a faterror function which will print a fatal error message, then exit. You might like to write it in terms of the error function of question 15.5:
void faterror(const char *fmt, ...)
{
error(fmt, what goes here? );
exit(EXIT_FAILURE);
}
but it's not obvious how to hand faterror's arguments off to error.
<snip>
Read on at
http://c-faq.com/varargs/handoff.html
Related
I'm learning to code c++ and I've come to this problem:
I have this struct:
struct storeData
{
string name;
string username;
string fav_food;
string fav_color;
}data[30];
And I need to check if two usernames are equal so I made this statement:
for(i=0;i<c;i++){
if(data[c].username.compare(data[i].username)==0){
cout<<"Username already taken"<<endl;
}
}
And it works well, the problem that I have is that I'm required to make a function let's call it: isTaken that returns the error message, so I can use it whenever I need to for example delete a username so I don't have to copy/paste the code again.
So I began looking for an answer for that, many forums present a way to send the whole struct like this:
void isTaken(struct storeData *data)
which I understand but because I'm using string is not working, so I guess it's because string is an object? I'm using the library <string> I'm sorry if I'm not being that clear at the moment, I'm looking for a way to use isTaken(data[c].user); but I don't know how to declare the function, I think is also because string is not the same as C string but I'm not really sure I've been looking for a solution and could not find it.
I tried: void isTaken(struct storeData *data) but I got an error saying that I can't convert std::string to basic_string which makes sense if I'm correct about string I tried converting string into c string but could not get anywhere. I'm open to suggestions/corrections because I want to improve my code, also I could not find the answer here, so If someone's got a link to a problem like this please let me know.
Thank you so much for you time, have a good day.
Do you mean an array of structs instead of a struct of arrays?
In the example you are giving I see only an array of structs each of which has multiple string objects in it. You see, a string is a class coming from std and I wouldn't call it an array. If you want to know how to pass an array to a function, you should read about it (I'm sure you can find such a question in SO). If you want to have an array within your struct, then the struct will take care of the memory of the array, but you should definitely read about constructors.
You got an error because you are passing an string argument to a function which requires struct pointer
void isTaken(struct storeData *data);
...
isTaken(data[c].user);
but what you actually need is to have a function which takes an array of your users, its size and username you want to check
bool IsUsernameTaken(struct storeData data[], int dataSize, const string &username){
for(int i = 0; i<dataSize; i++){
if(username == data[i].username)
return true;
}
return false;
}
A C string looks like this
data
A C++ string usually looks like this
size
capacity
ptr
|
v
data
or if using short string optimization and the string is short enough
size
data
data
all are zero terminated.
Making a shallow copy a C string only cost the copy of the pointer to it. Where a copy of a might cost just copying the 3 members and possible an allocation of data, which is not ideal, therefor most C++ functions use a reference to a string making the cost equivalent to the C string.
All code is untested.
bool Find(const std::string& target);
Making a deep copy of a C string would also cost an allocation.
In C++ you have many options to do a search, for your struct it could look like this. In case your member variables are private you must use an access function
auto found = std::find(std::begin(data), std::begin(data)+c, [&target](const storeData& auser) { return auser.GetName() == target });
return (found != std::begin(data)+c);
The first two parameters are the range that is search, not including the 2nd. A lambda is used to check the name, a free function with the right declaration would also do.
std::string& GetName() { return name; }
The higher C++ protection schemes would advice adding 2 consts to that in case you don't need to change name.
const std::string& GetName() const { return name; }
Meaning the returned string cant be changed and the 2nd says it wont change anything in your class. This const version would be required as I used a const storeData& auser in the lambda to satisfy the constness of the struct.
I'm using VxWorks 6.9 and am trying to use some spyLib.h functions but I'm having issues finding what signature to expect given that the type is variadic.
in vxTypesOld.h I find my type: typedef int (*FUNCPTR) (...);
and in spyLib.h i have my function call : extern void spyReportCommon (FUNCPTR printRtn);
But what function parameters are expected for printRtn ? I guess a c-style string is one but I don't know if each line of the table is a string or if its an array of strings, or even one large string.
I can't start writing the function to parse data from the outputted data until I know in what form that data is passed into the function.
All I know for certain is that it returns an int (e.g. int parsePrint( ???? );)
Here is my attempt at reporting:
#include <vxworks.h>
#include <spyLib.h>
#include <usrLib.h>
int ParseSpy(const char * spyOutput); // this is a guess
void Startup()
{
//startup logic
// the compiler said and int param is expected but the .h had void
spyLibInit(1);
spyCommon(1,50, (FUNCPTR) &ParseSpy);
}
int ParseSpy(const char * spyOutput){} // this is a guess
I'm getting an unexpected compiler error: 'spyCommon' was not declared in scope
but as you can see spyLib.h was included so I'm a bit confused by this.
That looks like a bad design. The print function cannot print if it does not know what the parameters are. At least one parameter is needed to specify what the rest of the parameters are.
Looking at the source and searching for "printRtn" I see that all calls to the print function are expecting a printf like function where the first parameter is a format string. Your function should better be written as
int ParseSpy(const char * spyOutput, ...);
Regarding the missing spyCommon you could try to let VxWorks write the preprocessor output to a file to check what the compiler sees. Maybe you are getting the wrong spylib.h file or something it that file is hidden by #if.
So I am using execlp in my c++ program. execlp is of the form " int execlp(const char *file, const char *arg0,...,const char *argn)" meaning that it can take arbitrary amount of arguments. I just want to know that is there a way I can put arguments inside this function at run time? Since the arguments are provided by the user, there is no way for me to know the exact number of arguments. Of course I can pick a ridiculously large number from the start but that won't be very efficient.I need a more efficient way that would allow me to put arguments at run time.
If you are not required to use execlp, execv or execvp are better functions for your requirement.
From http://linux.die.net/man/3/execlp
The execv(), execvp(), and execvpe() functions provide an array of pointers to null-terminated strings that represent the argument list available to the new program. The first argument, by convention, should point to the filename associated with the file being executed. The array of pointers must be terminated by a NULL pointer.
I guess that you are using Linux or some other POSIX system.
You obviously need, as R.Sahu answered, to use functions like execv(3), which takes an array of arguments to execve(2) syscall. You could allocate that array in C dynamic memory with malloc(3) or friends (calloc). If coding in C++, you would use new.
For a useless example, here is a chunk of code executing /bin/echo on an array of arguments 1, 2, .... nargs where int nargs; is strictly positive.
Variant in C99
assert(nargs>0);
char** myargs = malloc ((nargs+2)*sizeof(char*));
if (!myargs) { perror("malloc myargs"); exit(EXIT_FAILURE); };
myargs[0] = "echo";
for (int ix=0; ix<nargs; ix++)
{ char buf[32];
snprintf(buf,sizeof(buf),"%d",ix);
myargs[ix+1] = strdup(buf);
if (!myargs[ix+1]) { perror("strdup"); exit(EXIT_FAILURE); };
}
myargs[nargs+1] = NULL;
execv("/bin/echo", myargs);
perror("exec echo failed");
exit(EXIT_FAILURE);
In C++ you would e.g. code char**myargs = new char*[nargs+2];
In general, you need to later free (in C++, use delete) heap allocated memory. Here it is not really needed, since execv does not return. However, in other occasions (e.g. if using fork before execv, so the parent process is continuing and would later waitpid), you need a loop to free each individual element (result of strdup), then you need to free the entire myargs array.
Regarding the general question of calling an arbitrary (runtime-known) function of arbitrary signature, this is not possible in plain standard C99, but you could use some libraries (with a few assembler or machine specific code inside them) like libffi
In genuine C++11 you still need the array argument to execv to be an array of char*. You might consider using (as an intermediate step) some std::vector<std::string> but you'll need at least to transform it into a std::vector<char*> then pass the data to execve. Read about std::string (and its c_str member function) and std::vector (and its data member function). You could try something like:
assert (nargs>0);
std::vector<std::string> vecstr;
vecstr.resize(nargs+2);
vecstr[0] = "echo";
for (int ix=0; ix<nargs; ix++) vecstr[ix+1] = std::to_string(ix+1);
std::vector<const char*> vecargs;
vecargs.resize(nargs+2,nullptr);
std::transform(vecstr.begin(), vecargs.begin(),
[](const std::string&s) { return s.c_str(); });
vecargs[nargs+1] = nullptr;
execv("/bin/echo", vecargs.data());
throw std::runtime_error(std::string{"exec failure:"}+strerror(errno));
Notice that execv can fail, in particular when the array of arguments is too big; usually the limit is a few hundred thousands elements, but it can be much smaller.
I mean strings like "(%d%%%d) some text %s , %d%% %x %o %#x %#o \n". The printf family of functions somehow know how many args they would need from this string so separate argument for it is not needed. Is this functionality provided in c/c++ in terms of a separate function so I could write my own printf-like functions ? (yes I put these percents intentionally to accent how complicated it could get, so it is not simple counting of percent characters)
The problem with printf family is that it is not safe, and it doesn't really know or care how many format elements are there in string or in argument list.
printf family uses something called "variadic functions"; only one parameter is named (format string) and others are taken from the stack, without respecting their type or size - their type is deduced from format string, which makes it type-unsafe, and finds how many arguments to use by iterating over the string and finding all formatting specifiers, which makes it argument-number-unsafe. You can write variadic functions; syntax is
void foo(...);
and later you can use those macros and types, although if you are using C++, you should use C++11's variadic templates instead of C variadic functions, as variadic templates are type safe - you don't loose type information anywhere, and with universal references (but not quite thanks them) they are more powerful than variadic functions.
No, there is no standard library function for parsing printf-style format strings. If you want to write your own string formatting function, then I strongly recommend against following the printf example. It's inherently unsafe for the reasons mentioned in the others answers. It also has problems with localization since word order changes in some languages. Personally, I would write a type-safe function using templates and copying the .NET style of format strings. (Actually, I did do that--it's a lot of work but also fun.)
the printf family of functions only knows about one parameter, the first one...
It basically scans the string and each time it encounters a format specifier that it understands it pulls then next argument of that size from the argument list... this is an easily corruptible behavior.
imagine:
printf("%i",someInt); // fine
printf("%i",someLong); // depending on endianness and sized
// of those types could be the high or low 32 bits(probably)
printf("%i %i",someInt); // depending on abi could crash, read a int sized chunk
// of stack, or a register that would correspond to that
// parameter.
so inherently not safe..
you should pay attention to warnings and when writing portable code do things like:
size_t t = 5; //can be 32 or 64 bit depending on arch.
printf("%ull",(unsigned long long)t);
Edit. I guess I only half answered the question...
you can define your own variadic functions, the following adds count number of params and returns the result.
int sumList(int count, ...);
int main(int argc, const char * argv[])
{
printf("the answer is: %i",sumList(4,1,2,3,4));
return 0;
}
int sumList(int count, ...)
{
va_list args;
va_start(args, count);
int sum = 0;
for (int i = 0; i<count; i++) {
sum += va_arg(args, int);
}
va_end(args);
return sum;
}
I have a function with following signature
char requestApiCall(int num, const wchar_t* pParams = 0, ...)
{
...
}
Now I want to to get all pParams in an array (or to be able to iterate over it). I know this is possible with some macros, but I have no idea how to do it.
Any help would be appreciated.
P.S. I'm using MinGW if it matters.
UPDATE
my question caused confusion. I will try to clarify (sorry for my grammar). Both Object Pascal and C# has the ability to pass unlimited amount of parameters to a method. In C# we achieve this with params keyword:
void Foo(params string[] strs)
{
...
}
Foo("first", "second", "another one", "etc");
I want to achieve same result in C++ without using any object/class. In my case, type safety is not a concern, but if there is a type safe way to achieve that goal, I will gladly hear your comments :)
Thanks
You need to look at the functions and macros declared in stdarg.h. Here is a tutorial that explains it.
http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html
I'm not sure what your function parameters are supposed to represent but I think you'll find that it needs to change.
By the way, I find that for C++ I can usually avoid variadic functions. This has the advantage of preserving type safety. Are you sure you really need a variadic function?
Using variadic function arguments is a dangerous and tricky business, and almost surely there is a better way - for example, you might pass an std::vector<std::wstring>& to your function!
OK, that said, here's how to use variadic arguments. The key point is that it is your responsibility to know the number and types of the arguments!
#include <cstdarg>
char requestApiCall(int num, const wchar_t* pParams, ...)
{
va_list ap; // the argument pointer
va_start(ap, pParams); // initialize it with the right-most named parameter
/** Perform magic -- YOU have to know how many arguments you are getting! **/
int a = va_arg(ap, int); // extract one int
double d = va_arg(ap, double) // one double
char * s = va_arg(ap, char*) // one char*
/* ... and so forth ... */
va_end(ap); // all done, clean up
}
Just for completeness, I would redefine the function as this:
char requestApiCall(std::vector<std::wstring> & params)
{
for (std::vector<std::wstring>::const_iterator it = params.begin(), end = params.end(); it != end; ++it)
{
// do something with *it
}
/* ... */
}
A good example of what you are trying to accomplish is the exec family of functions. exec() takes an variable list of arguments all of which are expected to be const char*. The last item is a NULL ((char*)0). The last item is the indicator for when the list of items is complete.
You can use the variadic macros in stdargs.h as others have described.