I need to dump the certain things into a text file and same has needs to be displayed on screen. (I'm telling about a C program utiltiy)
The menu option looks like following,
1. display AA parameters
2. display BB parameters
3. display CC parameters
4. dump all
5. Exit
Select option >
If they select 1/2/3, it just needs to displayed on screen only or if they select option #4,it need to display all the parameters one by one and same needs to dumped in a .txt file.
I know, we can use the printf and fprintf functions to display on screen and write it to text file respectively. The thing is that I've display more that 20 parameters and each have at least 20 sub-parameters.
I'm currently implemented as below,
printf ( "Starting serial number [%ld]\n",
serial_info_p->start_int_idx);
fprintf(file_p, "Starting serial number [%ld]\n",
serial_info_p->start_int_idx)
printf ( "Current Serial number [%d]\n",
serial_info_p->current_int_idx);
fprintf(file_p, "Current Serial number [%d]\n",
serial_info_p->current_int_idx);
Is there an easiest way to implement this to cut down the number of lines of code?
Edit: the C++ tag seems misleading, can someone remove it please? thanks :)
I use variadic macros to customize printf and friends.
I would write something like this:
#define tee(fp,fmt, ...) \
{ \
printf (fmt, __VA_ARGS__); \
fprintf (fp, fmt, __VA_ARGS__); \
}
(the name comes from the tee(1) utility)
Something like this allows you to add any number of output streams, and allows changing them at runtime simply by modifying the PrintTarget linked list.
/** gcc -Wall -o print_target print_target.c && ./print_target */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct PrintTarget* PrintTargetp;
void* xmalloc (size_t size);
PrintTargetp pntCreate (PrintTargetp head, FILE* target);
void pntDestroy (PrintTargetp list);
typedef struct PrintTarget
{
FILE* target;
PrintTargetp next;
} PrintTarget;
void myPrintf (PrintTargetp streams, char* format, ...)
{
va_list args;
va_start(args, format);
while (streams)
{
vfprintf(streams->target, format, args);
streams = streams->next;
}
va_end(args);
}
int main(void)
{
PrintTargetp streams = pntCreate(NULL, stdout);
streams = pntCreate(streams, fopen("somefile.txt", "a+")); //XXX IO errors?
myPrintf(streams, "blah blah blah...\n");
pntDestroy(streams);
return 0;
}
Here's a definition of auxiliary functions:
PrintTargetp pntCreate (PrintTargetp head, FILE* target)
{
PrintTargetp node = xmalloc(sizeof(PrintTarget));
node->target = target;
node->next = head;
return node;
}
void pntDestroy (PrintTargetp list)
{
while (list)
{
PrintTargetp next = list->next;
free(list);
list = next;
//XXX cycles?
//XXX close files?
}
}
void* xmalloc (size_t size)
{
void* p = malloc(size);
if (p == NULL)
{
fputs("malloc error\n", stderr);
abort();
}
return p;
}
You could also just pipe the output of your prorgam to the tee(1) command.
If you're writing a console application, you should be able to output to the screen (standard output) using something like:
fprintf(stdout, "Hello World\n");
This should enable you to move the code that prints your data to its own function, and to pass in a FILE* for it to print to. Then the function can print to the screen if you pass "stdout", or to a file if you pass in a different FILE*, e.g.:
void print_my_stuff(FILE* file) {
fprintf( file,"Starting serial number [%ld]\n", serial_info_p->start_int_idx);
fprintf(file, "Current Serial number [%d]\n", serial_info_p->current_int_idx);
.
.
.
}
Edit: I didn't notice you needed a C solution. I'll leave this answer for reference, but it obviously requires C++.
You could create a new stream class that sends the output to two streams. I found an implementation of this at http://www.cs.technion.ac.il/~imaman/programs/teestream.html. I haven't tried it, but it should work.
Here's the code from the link:
#include <iostream>
#include <fstream>
template<typename Elem, typename Traits = std::char_traits<Elem> >
struct basic_TeeStream : std::basic_ostream<Elem,Traits>
{
typedef std::basic_ostream<Elem,Traits> SuperType;
basic_TeeStream(std::ostream& o1, std::ostream& o2)
: SuperType(o1.rdbuf()), o1_(o1), o2_(o2) { }
basic_TeeStream& operator<<(SuperType& (__cdecl *manip)(SuperType& ))
{
o1_ << manip;
o2_ << manip;
return *this;
}
template<typename T>
basic_TeeStream& operator<<(const T& t)
{
o1_ << t;
o2_ << t;
return *this;
}
private:
std::ostream& o1_;
std::ostream& o2_;
};
typedef basic_TeeStream<char> TeeStream;
You would use it like this:
ofstream f("stackoverflow.txt");
TeeStream ts(std::cout, f);
ts << "Jon Skeet" << std::endl; // "Jon Skeet" is sent to TWO streams
I'd go more radical than what people have suggested so far, but maybe it is too much for you. (The 'inline' keyword is C99; you can omit it without much consequence if you code to C89.)
/*
** These could be omitted - unless you get still more radical and create
** the format strings at run-time, so you can adapt the %-24s to the
** longest tag you actually have. Plus, with the strings all here, when
** you change the length from 24 to 30, you are less likely to overlook one!
*/
static const char fmt_int[] = "%-24s [%d]\n";
static const char fmt_long[] = "%-24s [%ld]\n";
static const char fmt_str[] = "%-24s [%s]\n"; /* Plausible extra ... */
static inline void print_long(FILE *fp, const char *tag, long value)
{
fprintf(fp, fmt_long, tag, value);
}
static inline void print_int(FILE *fp, const char *tag, int value)
{
fprintf(fp, fmt_int, tag, value);
}
static inline void print_str(FILE *fp, const char *tag, const char *value)
{
fprintf(fp, fmt_str, tag, value);
}
static void dump_data(FILE *fp, const serial_info_t *info)
{
dump_long("Starting serial number", info->start_int_idx);
dump_int( "Current Serial number", info->current_int_idx);
/* ... and similar ... */
}
Then the calling code would call dump_data() once (with argument stdout) for options 1, 2, 3 and twice (once with stdout, once with file pointer for output file) for option 4.
If the number of parameters got truly huge (into the multiple hundreds), I'd even go as far as to consider a data structure which encoded type and offset information (offsetof from <stddef.h>) and pointers to functions and such like, so that there would be just a loop in dump_data() iterating over a structure which encodes all the necessary information.
You could also simplify life by using the same basic integer type (long in your example) for all the integer members of the data structure.
Fred Brooks in "Mythical Man Month" - a book well worth reading if you've not already done so, but make sure you read the Twentieth Anniversary edition - says in Chapter 9:
Show me your flowcharts [code] and conceal your tables [data structures], and I shall continue to be mystified. Show me your tables, and I won't usually need your flowcharts; they'll be obvious.
A table-driven version of this code could end up saving space, as well as frustration when having to change a hundred related functions in the same way whereas a simple change in the tabular data could have fixed the whole lot.
#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0]))
FILE *f = fopen("somefile.txt", "a+");
FILE *fp[] = { stdout, f };
int i = 0;
for (i = 0; i < ARRAY_LEN(fp); i++) {
fprintf(fp[i], "Starting serial number [%ld]\n", serial_info_p->start_int_idx);
fprintf(fp[i], "Current serial number [%ld]\n", serial_info_p->start_int_idx);
}
fclose(f);
Related
EDIT: This question is to be edited, please stop reading. Don't waste your time! Thank you
I’m doing High School Turbo C++. I tried making a header file containing a function to search a binary file.
My Headerfile program is: alpha.h
#ifndef ALPHA_H
#define ALPHA_H
#if !defined __FSTREAM_H
#include<fstream.h>
#endif
#if !defined __PROCESS_H
#include<process.h>
#endif
void searchclass(char* & buf, int, char *);
#endif
According to some research that I did on the internet, I found out that the definitions will go in a separate program not in the main header file. So this is that program: ALPHA.CPP
#include<process.h>
#include<fstream.h>
#include"alpha.h"
//All the Definations of the alpha.h header file go here
void searchclass(char* & buf, int s_var, char * file)
{
ifstream fin;
fin.open(file, ios::binary);
if(!fin)
{
cout<<"Error 404: File not found";
exit(-1);
}
while(!fin.read((char*)buf, sizeof(buf)))
if(buf.getint()==s_var)
cout<<"\n\nRecord Found!";
buf.show();
fin.close();
}
Keep in mind that I'm trying to write a function that can help me search a random binary file storing records in form of classes for some specific int variable. So it should be able to take in an object of any class and perform a search in it.
This is the program I wrote to check my header file. A_TEST.CPP
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include"alpha.h"
#include<string.h>
class stu
{ int rn;
char name[20];
public:
void show() //Display Function
{
cout<<"\n\tStudent Details:";
cout<<"\nName: "<<name;
cout<<"\nRoll No.: "<<rn;
}
stu() //constructor
{
rn = 6;
strcpy(name,"Random Name");
}
int getint() //return function
{
return rn;
}
};
char* returnfile()
{ char file[10];
strcpy(file,"file.dat");
return file;
}
void main()
{
clrscr();
int search_var=6;
stu S1;
char file[10];
strcpy(file, "test.dat");
ofstream fout;
fout.open(file, ios::binary);
fout.write((char*)&S1, sizeof(S1));
fout.close();
searchclass((char*)& S1, search_var, file);
getch();
}
On compiling A_TEST.CPP (above program), I get the warning:
Warning A_TEST.CPP 45: Temporary used for parameter 'buf' in call to
'searchclass(char * &,int,char *)'
On linking, it gives me this error:
Linking A_TEST.EXE
Linker Error: Undefined symbol searchclass(char nearnear&,int,char
near) in module A_TEST.CPP
I don't think that the ALPHA.CPP file is getting linked with the alpha.h file, and if I compile ALPHA.CPP file it gives me the following errors:
Error ALPHA.CPP 17: Structure required on left side of . or .*
Error ALPHA.CPP 19: Structure required on left side of . or .*
Warning ALPHA.CPP 21: Parameter 's_var' is never used
In ALPHA.CPP 17 and 19, you can't write code like that, because int type hasn't getint() or show() methods. If you want to check int in the buffer, you should convert pointer into "int*" first, try below code:
int count = fin.read((char*)buf, sizeof(buf));
for (int i = 0; i<(count-4); ++i) {
if (*(int *)(buf + i) == s_var) {
cout << "\n\nRecord Found!";
break;
}
}
After I enter a string in c and store it in for example char s[100], how can I compare that string to all function names in a math.h? For example, I enter pow and the result will look like this in stored form.
s[0]='p'
s[1]='o'
s[2]='w'
s[3]='\0'
Since my string is the equivalent of pow(), I want my program to recognise that and then call pow() during execution of my program. I know it is not that hard to do string comparison within the code, but that would mean that I would have to do string comparison for every function name in the library. I don't want to do that. How is it possible to compare my string against all names in the library without hard coding every comparison?
Thank you :)
You can't, not without doing work yourself. There are no names of functions present at runtime in general, and certainly not of functions you haven't called.
C is not a dynamic language, names are only used when compiling/linking.
Regular expressions in C
Try parsing the header files using FILE and use aforementioned link as a guide to check whether the function exists or not.
I tried to make a little sample about what I assume the questioner is looking for (eval.c):
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <assert.h>
/* mapping function names to function pointers and number of parameters */
struct Entry {
const char *name; /* function name */
double (*pFunc)(); /* function pointer */
int nArgs; /* number of arguments */
} table[] = {
#define REGISTER(FUNC, N_ARGS) { #FUNC, &FUNC, N_ARGS }
REGISTER(atan2, 2),
REGISTER(pow, 2),
REGISTER(modf, 2),
REGISTER(sin, 1),
REGISTER(cos, 1)
#undef REGISTER
};
/* let compiler count the number of entries */
enum { sizeTable = sizeof table / sizeof *table };
void printUsage(const char *argv0)
{
int i;
printf(
"Usage:\n"
" %s FUNC\n"
" where FUNC must be one of:\n", argv0);
for (i = 0; i < sizeTable; ++i) printf(" - %s\n", table[i].name);
}
int main(int argc, char **argv)
{
int i;
char *func;
struct Entry *pEntry;
/* read command line argument */
if (argc <= 1) {
fprintf(stderr, "ERROR: Missing function argument!\n");
printUsage(argv[0]);
return -1;
}
func = argv[1];
/* find function by name */
for (i = 0; i < sizeTable && strcmp(func, table[i].name) != 0; ++i);
if (i >= sizeTable) {
fprintf(stderr, "ERROR! Unknown function '%s'!\n", func);
printUsage(argv[0]);
return -1;
}
/* perform found function on all (standard) input */
pEntry = table + i;
for (;;) { /* endless loop (bail out at EOF or error) */
switch (pEntry->nArgs) {
case 1: {
double arg1, result;
/* get one argument */
if (scanf("%lf", &arg1) != 1) {
int error;
if (error = !feof(stdin)) fprintf(stderr, "Input ERROR!\n");
return error; /* bail out at EOF or error */
}
/* compute */
result = (*pEntry->pFunc)(arg1);
/* output */
printf("%s(%f): %f\n", pEntry->name, arg1, result);
} break;
case 2: {
double arg1, arg2, result;
/* get two arguments */
if (scanf("%lf %lf", &arg1, &arg2) != 2) {
int error;
if (error = !feof(stdin)) fprintf(stderr, "Input ERROR!\n");
return error; /* bail out at EOF or error */
}
/* compute */
result = (*pEntry->pFunc)(arg1, arg2);
/* output */
printf("%s(%f, %f): %f\n", pEntry->name, arg1, arg2, result);
} break;
default: /* should never happen */
fprintf(stderr,
"ERROR! Functions with %d arguments not yet implemented!\n",
pEntry->nArgs);
assert(0);
return -1; /* bail out at error */
}
}
}
I compiled and tested this with gcc in cygwin on Windows (64 bit):
$ gcc -std=c11 -o eval eval.c
$ ./eval
ERROR: Missing function argument!
Usage:
./eval FUNC
where FUNC must be one of:
- atan2
- pow
- modf
- sin
- cos
$ echo "1 2 3 4 5 6 7 8 9 10" | ./eval pow
pow(1.000000, 2.000000): 1.000000
pow(3.000000, 4.000000): 81.000000
pow(5.000000, 6.000000): 15625.000000
pow(7.000000, 8.000000): 5764801.000000
pow(9.000000, 10.000000): 3486784401.000000
$ echo "1 2 3 4 5 6 7 8 9 10" | ./eval sin
sin(1.000000): 0.841471
sin(2.000000): 0.909297
sin(3.000000): 0.141120
sin(4.000000): -0.756802
sin(5.000000): -0.958924
sin(6.000000): -0.279415
sin(7.000000): 0.656987
sin(8.000000): 0.989358
sin(9.000000): 0.412118
sin(10.000000): -0.544021
The usage of this application: the name of the function to apply is provided as command line argument. The values (to apply function to) are provided via standard input. In the sample session, I used echo and a pipe (|) to redirect the output of echo to the input of eval. (If eval is called stand-alone the numbers may be typed in by keyboard.)
Notes:
The table does the actual mapping of strings to function pointers. To solve that issue about the number of parameters, I considered this in struct Entry also.
The REGISTER macro is a trick to use the identifier as string constant also. The #FUNC is a stringize macro-operation (a typical C trick to prevent errors due to typos).
The sizeTable is another trick to prevent redundant definitions. I let the compiler count the number of entries. Thus, new entries may be added and it still will work without any other editing.
The actual trick is to provide a function pointer where the arguments are "left out". When it is called, the correct number of arguments is used and it works. (assuming, of course, the table initialization has been implemented carefully.) However, it would be a pain to do this in C++ because the functions with distinct number of arguments would need an appropriate function pointer with matching signature - horrible casts would be necessary. (Try to compile this with g++ -std=c++11 -c eval.c to see what I mean.)
For a productive solution, I would sort the entries by names (lexicographically) and apply a binary search (or even use hashing to be faster and more sophisticated). For this sample, I wanted to keep it simple.
math.h provides a lot of functions in "float flavor" also. These may not be added to this sample without additional effort. To support other than double arguments
some type info had to been added to the table entries
the type info has to be considered somehow in the switch statement of evaluation.
...not to mention functions where argument types are distinct to each other (or return type). (I cannot remember whether math.h even provides such functions.)
Btw. this will work for non-math.h functions also...
I've a huge C project with a module reading and managing configuration data. If I have to add a new configuration parameter, I'll have to edit several functions, e.g. as pseudo-code:
void read_configuration(config *c) {
read_param("p1", c->p1);
read_param("p2", c->p2);
read_param("p3", c->p3);
/* ... */
}
void dump_configuration(config *c) {
dump_param("p1", c->p1);
dump_param("p2", c->p2);
dump_param("p3", c->p3);
/* ... */
}
Is there a way to ensure by macro at compile time, that each location has at least the same count of parameters? I thought of making dump_param some kind of macro counting the invocations and then add something like
#if nr_read != nr_dump
#error "You forgot something, idiot!"
#endif
at the end of the module. I can't find a method to make the macro count its invocations, though...
Since the list of parameters is the same in both functions, how about factoring that out and avoid any possible mismatch ?
Using X-macros
#define X_CONFIG_PARAMS(config) \
X("p1", (config).p1) \
X("p2", (config).p2) \
X("p3", (config).p3)
void read_configuration(config *c) {
#define X(name, param) read_param(name, ¶m);
X_CONFIG_PARAMS(*c)
#undef X
}
void dump_configuration(config *c) {
#define X(name, param) dump_param(name, ¶m);
X_CONFIG_PARAMS(*c)
#undef X
}
Using function pointers
void alter_config(config *c, void(*func)(char const *name, Param *param)) {
func("p1", &c->p1);
func("p2", &c->p2);
func("p3", &c->p3);
}
void read_configuration(config *c) {
alter_config(c, read_param);
}
void dump_configuration(config *c) {
alter_config(c, dump_param);
}
Using an array and offsetof
struct param_info {
char const *name;
size_t config_offs;
};
param_info allParams[] = {
{"p1", offsetof(config, p1)},
{"p2", offsetof(config, p2)},
{"p3", offsetof(config, p3)}
};
void read_configuration(config *c) {
size_t paramCount = sizeof allParams / sizeof *allParams;
for(size_t i = 0; i < paramCount; ++i) {
Param *p = (Param*)((char*)config + allParams[i].config_offs);
read_param(allParams[i].name, p);
}
}
void dump_configuration(config *c) {
size_t paramCount = sizeof allParams / sizeof *allParams;
for(size_t i = 0; i < paramCount; ++i) {
Param *p = (Param*)((char*)config + allParams[i].config_offs);
dump_param(allParams[i].name, p);
}
}
I would rather let the preprocessor write the code in the first place.
It could look something like this:
Define the list of parameters in a separate file, say parameters.inc:
PARAM (p1)
PARAM (p2)
...
Then in the source code locally define the macro PARAM as required and let the preprocessor include and expand the contents of parameters.inc:
void read_configuration(config *c) {
#define PARAM(NAME) read_param(#NAME, c->NAME);
#include "parameters.inc"
#undef PARAM
}
void dump_configuration(config *c) {
#define PARAM(NAME) dump_param(#NAME, c->NAME);
#include "parameters.inc"
#undef PARAM
}
I don't think you can do this at compile time without ugly hacks.
What you could do: add a test to your test suite which replaces the header that contains the read_param() and dump_param() macros so they generate code which only updates a counter. Then, in the main() function of that test, place an assertion that compares both counters and fails if they're not equal.
You do have a test suite and run it at compile time, right? ;-)
However, I do agree with the comment that it's probably better to do this differently. In an approach called "table-driven programming", you turn the macro definition and data definition on their head (that is, you have the #define in your .c file and the use of the macro in the header rather than the other way around), you don't have this problem. Poul-Henning Kamp, of FreeBSD fame, explains very well how to that here.
my problem with vsprintf is that I can not obtain input arguments directly, I have to first get inputs one by one and save them in void**, then pass this void** to vsprintf(), it is all fine for windows, but when I come to 64bit linux, gcc cannot compile because it is not allowed to convert from void** to va_list, Is there anyone that can give me some help how I should do this under linux?
Can I create va_list dynamically in GCC?
void getInputArgs(char* str, char* format, ...)
{
va_list args;
va_start(args, format);
vsprintf(str, format, args);
va_end(args);
}
void process(void)
{
char s[256];
double tempValue;
char * tempString = NULL;
void ** args_ptr = NULL;
ArgFormatType format; //defined in the lib I used in the code
int numOfArgs = GetNumInputArgs(); // library func used in my code
if(numOfArgs>1)
{
args_ptr = (void**) malloc(sizeof(char)*(numOfArgs-1));
for(i=2; i<numOfArgs; i++)
{
format = GetArgType(); //library funcs
switch(format)
{
case ArgType_double:
CopyInDoubleArg(i, TRUE, &tempValue); //lib func
args_ptr[i-2] = (void*) (int)tempValue;
break;
case ArgType_char:
args_ptr[i-2]=NULL;
AllocInCharArg(i, TRUE, &tempString); //lib func
args_ptr[i-2]= tempString;
break;
}
}
}
getInputArgs(s, formatString, (va_list) args_ptr); //Here
// is the location where gcc cannot compile,
// Can I and how if I can create a va_list myself?
}
There is a way you can do this, but it is specific to gcc on Linux. It does work on Linux (tested) for both 32 and 64 bit builds.
DISCLAIMER: I am not endorsing using this code. It is not portable, it is hackish, and is quite frankly a precariously balanced elephant on a proverbial tightrope. I am merely demonstrating that it is possible to dynamically create a va_list using gcc, which is what the original question was asking.
With that said, the following article details how va_list works with the amd64 ABI: Amd64 and Va_arg.
With knowledge of the internal structure of the va_list struct, we can trick the va_arg macro into reading from a va_list that we construct ourselves:
#if (defined( __linux__) && defined(__x86_64__))
// AMD64 byte-aligns elements to 8 bytes
#define VLIST_CHUNK_SIZE 8
#else
#define VLIST_CHUNK_SIZE 4
#define _va_list_ptr _va_list
#endif
typedef struct {
va_list _va_list;
#if (defined( __linux__) && defined(__x86_64__))
void* _va_list_ptr;
#endif
} my_va_list;
void my_va_start(my_va_list* args, void* arg_list)
{
#if (defined(__linux__) && defined(__x86_64__))
/* va_args will read from the overflow area if the gp_offset
is greater than or equal to 48 (6 gp registers * 8 bytes/register)
and the fp_offset is greater than or equal to 304 (gp_offset +
16 fp registers * 16 bytes/register) */
args->_va_list[0].gp_offset = 48;
args->_va_list[0].fp_offset = 304;
args->_va_list[0].reg_save_area = NULL;
args->_va_list[0].overflow_arg_area = arg_list;
#endif
args->_va_list_ptr = arg_list;
}
void my_va_end(my_va_list* args)
{
free(args->_va_list_ptr);
}
typedef struct {
ArgFormatType type; // OP defined this enum for format
union {
int i;
// OTHER TYPES HERE
void* p;
} data;
} va_data;
Now, we can generate the va_list pointer (which is the same for both 64 bit and 32 bit builds) using something like your process() method or the following:
void* create_arg_pointer(va_data* arguments, unsigned int num_args) {
int i, arg_list_size = 0;
void* arg_list = NULL;
for (i=0; i < num_args; ++i)
{
unsigned int native_data_size, padded_size;
void *native_data, *vdata;
switch(arguments[i].type)
{
case ArgType_int:
native_data = &(arguments[i].data.i);
native_data_size = sizeof(arguments[i]->data.i);
break;
// OTHER TYPES HERE
case ArgType_string:
native_data = &(arguments[i].data.p);
native_data_size = sizeof(arguments[i]->data.p);
break;
default:
// error handling
continue;
}
// if needed, pad the size we will use for the argument in the va_list
for (padded_size = native_data_size; 0 != padded_size % VLIST_CHUNK_SIZE; padded_size++);
// reallocate more memory for the additional argument
arg_list = (char*)realloc(arg_list, arg_list_size + padded_size);
// save a pointer to the beginning of the free space for this argument
vdata = &(((char *)(arg_list))[arg_list_size]);
// increment the amount of allocated space (to provide the correct offset and size for next time)
arg_list_size += padded_size;
// set full padded length to 0 and copy the actual data into the location
memset(vdata, 0, padded_size);
memcpy(vdata, native_data, native_data_size);
}
return arg_list;
}
And finally, we can use it:
va_data data_args[2];
data_args[0].type = ArgType_int;
data_args[0].data.i = 42;
data_args[1].type = ArgType_string;
data_args[1].data.p = "hello world";
my_va_list args;
my_va_start(&args, create_arg_pointer(data_args, 2));
vprintf("format string %d %s", args._va_list);
my_va_end(&args);
And there you have it. It works mostly the same as the normal va_start and va_end macros, but lets you pass your own dynamically generated, byte-aligned pointer to be used instead of relying on the calling convention to set up your stack frame.
I have tried using libffi as mentioned somewhere else and it works.
Here below is the link , hope it can help others with similar issues.
Thanks again for all help I got here!
Link:
http://www.atmark-techno.com/~yashi/libffi.html -- simple example given
http://www.swig.org/Doc1.3/Varargs.html -- printf() and other examples given
The type of va_list is not void ** or anything similar with 64-bit gcc (on Intel x86/64 machines). On both Mac OS X 10.7.4 and on RHEL 5, there is no header stdarg.h in /usr/include. Consider the following code:
#include <stdarg.h>
#include <stdio.h>
int main(void)
{
printf("sizeof(va_list) = %zu\n", sizeof(va_list));
return 0;
}
The output on both RHEL 5 and Mac OS X 10.7 with a 64-bit compilation is:
sizeof(va_list) = 24
With a 32-bit compilation, the output on each platform is:
sizeof(va_list) = 4
(You may take it that I was surprised to find this much discrepancy between the 32-bit and 64-bit versions. I was expecting a value between 12 and 24 for the 32-bit version.)
So, the type is opaque; you can't even find a header that tells you anything about; and it is much bigger than a single pointer on 64-bit machines.
Even if your code works on some machines, it is very, very far from guaranteed to work everywhere.
The GCC 4.7.1 manual does not mention any functions that allow you to build a va_list at runtime.
Following class works for me:
class VaList
{
va_list _arguments;
public:
explicit inline VaList(const void * pDummy, ...)
{
va_start(_arguments, pDummy);
}
inline operator va_list &()
{
return _arguments;
}
inline operator const va_list &() const
{
return _arguments;
}
inline ~VaList()
{
va_end(_arguments);
}
};
and it can be used like this:
void v(const char * format, const va_list & arguments)
{
vprintf(format, const_cast<va_list &>(arguments));
}
...
v("%d\n", VaList("", 1)); // Uses VaList::operator va_list &()
v("%d %d\n", VaList(nullptr, 2, 3)); // Uses VaList::operator va_list &()
vprintf("%s %s %s\n", VaList("", "Works", "here", "too!"));
const VaList args(NULL, 4, 5, "howdy", "there");
v("%d %d %s %s\n", args); // Uses VaList::operator const va_list &() const
The first dummy parameter can be any kind of pointer, it is only used to compute the address of the following arguments.
The same can of course be done in C too but not so niftily (use pointer instead of reference)!
Simple example of using VaList to construct a dynamic va_list:
static void VectorToVaList(const std::vector<int> & v, va_list & t)
{
switch (v.size())
{
case 1: va_copy(t, VaList("", v[0])); return;
case 2: va_copy(t, VaList("", v[0], v[1])); return;
case 3: va_copy(t, VaList("", v[0], v[1], v[2])); return;
case 4: va_copy(t, VaList("", v[0], v[1], v[2], v[3])); return;
// etc
}
throw std::out_of_range("Out of range vector size!");
}
and usage:
va_list t;
VectorToVaList(std::vector<int>{ 1, 2, 3, 4 }, t);
vprintf("%d %d %d %d\n", t);
If the problem you're trying to solve is inserting passing arbitrary types to a function in va_list style, then, consider using union:
#include <iostream>
#include <cstdarg>
union ARG
{
int d;
char* s;
double f;
};
int main()
{
printf("%d %s %f \n", 1, "two", 3.1415 );
// Output: 1 two 3.141500
char format[ 1024 ] = "%d %s %f\n";
ARG args[ 5 ] = { };
args[ 0 ].d = 1;
args[ 1 ].s = "two";
args[ 2 ].f = 3.1415;
printf( format, args[ 0 ], args[ 1 ], args[ 2 ], args[ 3 ], args[ 4 ] );
// Output: 1 two 3.141500
return 0;
}
Some things you'll note about my solution:
No attempt is made to produce the correct number of arguments. i.e. I oversupply the arguments, but, most functions will look at the first parameter to determine how to handle the rest (i.e. format)
I didn't bother dynamically create the format, but, it is a trivial exercise to build a routine that dynamically populates format and args.
Tested this on:
- Ubuntu, g++
- Android NDK
I did some more testing, and, confirmed #PeterCoordes comments about this answer not working for double precision.
I've noticed that at several places in our code base we use dynamically expanding arrays, i.e. a base array coupled with an element counter and a "max elements" value.
What I want to do is replace these with a common data structure and utility functions, for the usual object-oriented reasons.
The array elements can be either basic data types or structs, I need fast random access to the elements, and preferably a type-safe implementation.
So, basically, what I would like to use is an STL vector, but the code base is restricted to C89 so I have to come up with something else :-)
I gave it some thought and whipped up this initial draft, just to show what I'm aiming at:
/* Type-safe dynamic list in C89 */
#define list_declare(type) typedef struct _##type##_list_t { type * base_array; size_t elements; size_t max_size; } type##_list_t
#define list(type) type##_list_t
#define list_new(type, initial_size) { calloc(initial_size, sizeof(type)), 0, initial_size }
#define list_free(list) free(list.base_array)
#define list_set(list, place, element) if ( list.elements < list.max_size ) { list.base_array[place] = element; } else { /* Array index out of bounds */ }
#define list_add(list, element) if ( list.elements < list.max_size ) { list.base_array[list.elements++] = element; } else { /* Expand array then add */ }
#define list_get(list, n) list.base_array[n]
/* Sample usage: */
list_declare(int);
int main(void)
{
list(int) integers = list_new(int, 10);
printf("list[0] = %d\n", list_get(integers, 0));
list_add(integers, 4);
printf("list[0] = %d\n", list_get(integers, 0));
list_set(integers, 0, 3);
printf("list[0] = %d\n", list_get(integers, 0));
list_free(integers);
return EXIT_SUCCESS;
}
...however, there must be someone else who has done this before. I'm aware of the FreeBSD sys/queue.h implementation of a similar concept for some different queues, but I can't find anything like that for arrays.
Is anyone here any wiser?
glib provides an GArray type, which implements a dynamically growing array. If you can use external 3rd party libraries, glib is almost always a good choice as "standard" library for C. It provides types for all basic data structures, for unicode strings, for date and time values, and so on.
here a simple vector-replacement, its ONE function for all, its strictly C89 and threadsafe;
libs are too difficult for me, i use my own;
no performance, but easy to use
/* owner-structs too */
typedef struct {
char name[20],city[20];
int salary;
} My,*Myp;
typedef char Str80[80];
/* add here your type with its size */
typedef enum {SPTR,INT=sizeof(int),DOUBLE=sizeof(double),S80=sizeof(Str80),MY=sizeof(My)} TSizes;
typedef enum {ADD,LOOP,COUNT,FREE,GETAT,GET,REMOVEAT,REMOVE} Ops;
void *dynarray(char ***root,TSizes ts,Ops op,void *in,void *out)
{
size_t d=0,s=in?ts?ts:strlen((char*)in)+1:0;
char **r=*root;
while( r && *r++ ) ++d;
switch(op) {
case ADD: if( !*root ) *root=calloc(1,sizeof r);
*root=realloc(*root,(d+2)*sizeof r);
memmove((*root)+1,*root,(d+1)*sizeof r);
memcpy(**root=malloc(s),in,s);
break;
case LOOP: while( d-- ) ((void (*)(char*))in)((*root)[d]); break;
case COUNT: return *(int*)out=d,out;
case FREE: if(r) {
++d; while( d-- ) realloc((*root)[d],0);
free(*root);*root=0;
} break;
case GETAT: { size_t i=*(size_t*)in;
if(r && i<=--d)
return (*root)[d-i];
} break;
case GET: { int i=-1;
while( ++i,d-- )
if( !(ts?memcmp:strncmp)(in,(*root)[d],s) )
return *(int*)out=i,out;
return *(int*)out=-1,out;
}
case REMOVEAT: { size_t i=*(size_t*)in;
if(r && i<=--d) {
free((*root)[d-i]);
memmove(&(*root)[d-i],&(*root)[d-i+1],(d-i+1)*sizeof r);
return in;
}
} break;
case REMOVE: while( *(int*)dynarray(root,ts,GET,in,&d)>=0 )
dynarray(root,ts,REMOVEAT,&d,0);
}
return 0;
}
void outmy(Myp s)
{
printf("\n%s,%s,%d",s->name,s->city,s->salary);
}
main()
{
My z[]={{"Buffet","Omaha",INT_MAX},{"Jobs","Palo Alto",1},{"Madoff","NYC",INT_MIN}};
Str80 y[]={ "123","456","7890" };
char **ptr=0;
int x=1;
/* precondition for first use: ptr==NULL */
dynarray(&ptr,SPTR,ADD,"test1.txt",0);
dynarray(&ptr,SPTR,ADD,"test2.txt",0);
dynarray(&ptr,SPTR,ADD,"t3.txt",0);
dynarray(&ptr,SPTR,REMOVEAT,&x,0); /* remove at index/key ==1 */
dynarray(&ptr,SPTR,REMOVE,"test1.txt",0);
dynarray(&ptr,SPTR,GET,"t3.txt",&x);
dynarray(&ptr,SPTR,LOOP,puts,0);
/* another option for enumerating */
dynarray(&ptr,SPTR,COUNT,0,&x);
while( x-- )
puts(ptr[x]);
dynarray(&ptr,SPTR,FREE,0,0); /* frees all mallocs and set ptr to NULL */
/* start for another (user)type */
dynarray(&ptr,S80,ADD,y[0],0);
dynarray(&ptr,S80,ADD,y[1],0);
dynarray(&ptr,S80,ADD,y[2],0);
dynarray(&ptr,S80,ADD,y[0],0);
dynarray(&ptr,S80,LOOP,puts,0);
dynarray(&ptr,S80,FREE,0,0); /* frees all mallocs and set ptr to NULL */
/* start for another (user)struct-type */
dynarray(&ptr,MY,ADD,&z[0],0);
dynarray(&ptr,MY,ADD,&z[1],0);
dynarray(&ptr,MY,ADD,&z[2],0);
dynarray(&ptr,MY,ADD,&z[0],0);
dynarray(&ptr,MY,LOOP,outmy,0);
dynarray(&ptr,MY,FREE,0,0);
return 0;
}
There is sglib, which implements various lists,hashmaps and rbtrees in a generic fashion (i.e. by specializing over a type). There is also a fast sorting function for arrays:
http://sglib.sourceforge.net/
qLibc implements a vector in pure C. The data structure allows it to store any type of object like (void *object) and it provides convenient wrappers for string, formatted string and integer types.
Here's a sample code for your idea.
qvector_t *vector = qvector(QVECTOR_OPT_THREADSAFE);
vector->addstr(vector, "Hello");
vector->addstrf(vector, "World %d", 123);
char *finalstring = vector->tostring(vector);
printf("%s", finalstring);
free(finalstring)
vector->free(vector);
for object type:
int a = 1, b = 2;
qvector_t *vector = qvector(QVECTOR_OPT_THREADSAFE);
vector->add(vector, (void *)&a, sizeof(int));
vector->add(vector, (void *)&b, sizeof(int));
int *finalarray = vector->toarray(vector);
printf("a = %d, b = %d", finalarray[0], finalarray[1]);
free(finalarray)
vector->free(vector);
Note) I made this sample code just for your reference, copying from its example code.
it might have typo errors.
You can check out the Full API reference at http://wolkykim.github.io/qlibc/
I'm using the following macro implementation without problems so far. It isn't a complete implementation but grows the array automatically :
#define DECLARE_DYN_ARRAY(T) \
typedef struct \
{ \
T *buf; \
size_t n; \
size_t reserved; \
} T ## Array;
#define DYN_ARRAY(T) T ## Array
#define DYN_ADD(array, value, errorLabel) DYN_ADD_REALLOC(array, value, errorLabel, realloc)
#define DYN_ADD_REALLOC(array, value, errorLabel, realloc) \
{ \
if ((array).n >= (array).reserved) \
{ \
if (!(array).reserved) (array).reserved = 10; \
(array).reserved *= 2; \
void *ptr = realloc((array).buf, sizeof(*(array).buf)*(array).reserved); \
if (!ptr) goto errorLabel; \
(array).buf = ptr; \
} \
(array).buf[(array).n++] = value; \
}
To use you first write: DECLARE_DYN_ARRAY(YourType)
To declare variables you write DYN_ARRAY(YourType) array = {0}.
You add elements with DYN_ADD(array, element, errorLabel).
You access elements with array.buf[i].
You get the number of elements with array.n.
When done you free it with free(array.buf) (or whatever function you used to allocate it.)
I usually roll my own code for purposes such as this, like you did. It's not particularly difficult, but having type safety etc. is not easily achievable without a whole OO framework.
As mentioned before, glib offers what you need - if glib2 is too big for you, you could still go with glib1.2. It's quite old, but doesn't have external dependencies (except for pthread if you need thread support). The code can also be integrated into larger projects, if necessary. It's LGPL licensed.
Personally, I prefer "Gena" library. It closely resembles stl::vector in pure C89.
It is comfortable to use because you can:
Access vector elements just like plain C arrays: vec[k][j];
Have multi-dimentional arrays;
Copy vectors;
Instantiate necessary vector types once in a separate module, instead of doing this every time you needed a vector;
You can choose how to pass values into a vector and how to return them from it: by value or by pointer.
You can check it out here:
https://github.com/cher-nov/Gena