Concatenation in C - c

I have a program which does concatenation.
its like char *testConc(int a,..)
Where a indicates number of arguments are being passed for concatenation.
As legth keeps on changing is there is anything like constructor overloading in C
or any simple syntax which implements the functionality

Yes, there are varadic functions
#include <stdio.h>
#include <stdarg.h>
/* print all non-negative args one at a time;
all args are assumed to be of int type */
void printargs(int arg1, ...)
{
va_list ap;
int i;
va_start(ap, arg1);
for (i = arg1; i >= 0; i = va_arg(ap, int))
printf("%d ", i);
va_end(ap);
putchar('\n');
}
int main(void)
{
printargs(5, 2, 14, 84, 97, 15, 24, 48, -1);
printargs(84, 51, -1);
printargs(-1);
printargs(1, -1);
return 0;
}

C does not have function overloading capabilities. The syntax you have is called a variadic function, which can be used to perform what you asked.
The textConc function would look something like this:
char *textConc(int argc, ...)
{
va_list args;
char *str = NULL;
size_t len = 0;
va_start(args, argc);
while (argc--)
{
/* next string */
const char *temp = va_arg(args, const char *);
size_t size = strlen(temp);
/* make room and copy over */
str = realloc(str, len+size+1);
memcpy(str+len, temp, size+1);
/* new length */
len += size;
}
va_end(args);
return str;
}
int main(int argc, char **argv)
{
char *example = textConc(4, "Hello", "All", "good", "morning");
puts(example);
free(example);
return 0;
}
If you use GCC, we can fake overloading completely, using a little help of macros.
Rename textConc to textConcN and use the following macros:
#define ARGCOUNT(...) (sizeof((const char *[]){__VA_ARGS__})/sizeof(const char *))
#define textConc(...) textConcN(ARGCOUNT(__VA_ARGS__), __VA_ARGS__)
int main(int argc, char **argv)
{
/* notice, no more need for the number of arguments */
char *example = textConc("Hello", "All", "good", "morning");
puts(example);
free(example);
return 0;
}

Functions can't be overloaded in C.
You could rewrite your function as char *testConc(const char *s, ...), where you mark the end of the list with NULL:
testConc("foo", "bar", "baz", "quux", (char *)0);
This makes adding changing the number of actual arguments easier. If you have a C99 compiler, you can even write a wrapping macro that adds the NULL for you:
#define TESTCONC(...) testConc(__VA_ARGS__, (char *)0)

Related

Is it possible to pass 2 functions which have different signature as an argument to another function?

Currently, I have the following 2 functions:
void write_to_file(FILE *fp)
{
fprintf(fp, "stuff here: %d", 10);
/* 1000s of similar lines below */
}
and
void write_to_string(char *str)
{
sprintf(str, "stuff here: %d", 10);
/* 1000s of similar lines below */
}
I'd like to poly morph it into a single function.
I'd thought about something like:
void write_somewhere(void *ptr, int to_file)
{
if (to_file) {
typedef fprintf myprintf;
} else {
typedef sprintf myprintf;
}
myprintf(ptr, "stuff here: %d", 10);
}
This doesn't work and looks ugly.
Since the signature of fprintf and sprintf are different and as follows,
int fprintf(FILE *stream, const char *format, …);
int sprintf(char *buffer, const char *format, …);
Is it possible to do something like,
void write_somewhere(void *ptr, void *func)
{
func(ptr, "stuff here: %d", 10);
}
EDIT:
Based on Alter's answer below, this is what I have but it doesn't quite work as expected and prints out garbage value when trying to print out values in write_somewhere() function:
#include <stdio.h>
#include <stdarg.h>
typedef int (*myprintf_t) (void *, const char *, ...);
int myfprintf(void *ptr, const char *format, ...)
{
va_list args;
int ret;
va_start(args, format);
ret = vfprintf(ptr, format, args);
va_end(args);
return ret;
}
int mysprintf(void *ptr, const char *format, ...)
{
va_list args;
int ret;
va_start(args, format);
ret = vsprintf(ptr, format, args);
va_end(args);
return ret;
}
void write_somewhere(void *ptr, myprintf_t myprintf, const char *format, ...)
{
va_list args;
int ret;
va_start(args, format);
ret = myprintf(ptr, format, args);
va_end(args);
return ret;
}
int main(void)
{
char s[100];
int i = 100;
/* This works */
write_somewhere(stdout, myprintf, "Hello world");
/* This prints out garbage */
write_somewhere(stdout, myprintf, "Hello world, I am %d", i);
write_somewhere(s, mysprintf);
return 0;
}
Jen‘s answer is the correct one, but in this case you can redirect ptr to v*printf using a pointer to function:
#include <stdio.h>
#include <stdarg.h>
int myfprintf(void *ptr, const char *format, ...)
{
va_list args;
int ret;
va_start(args, format);
ret = vfprintf(ptr, format, args);
va_end(args);
return ret;
}
int mysprintf(void *ptr, const char *format, ...)
{
va_list args;
int ret;
va_start(args, format);
ret = vsprintf(ptr, format, args);
va_end(args);
return ret;
}
void write_somewhere(void *ptr, int (*myprintf)(void *, const char *, ...))
{
myprintf(ptr, "stuff here");
}
int main(void)
{
char s[100];
write_somewhere(stdout, myfprintf);
write_somewhere(s, mysprintf);
return 0;
}
For your last edit:
It seems that you want to pass some extras parameters to write_somewhere, in this case I suggest:
#include <stdio.h>
#include <stdarg.h>
#define TO_FILE 0
#define TO_STRING 1
void write_somewhere(int where, void *ptr, const char *format, ...)
{
#define myprintf(ptr, ...) \
(where == TO_FILE ? vfprintf(ptr, __VA_ARGS__) : vsprintf(ptr, __VA_ARGS__))
va_list args;
va_start(args, format);
myprintf(ptr, format, args);
/* more stuff */
va_end(args);
#undef myprintf
}
int main(void)
{
char s[100];
write_somewhere(TO_FILE, stdout, "%u\n", 10);
write_somewhere(TO_STRING, s, "Hello");
printf("%s\n", s);
return 0;
}
The C language guarantees that all function pointers have the same representation. Your polymorphic functions simply needs to be prototyped as accepting any function pointer, say, a void (*funcptr)(void). Note that a ptr-to-void is not a function pointer (it's an object pointer) and may not be able to hold a function pointer.
Of course you can only call the function if you know which of the several types it is. So you need some way to discriminate, much like printf does by looking at the format. If you call a function with arguments not matching its prototype, the behavior is undefined.
Not an answer to your exact question, but instead of writing write_something() as you have, you could change the structure slightly:
void write_somewhere(void *ptr, int to_file)
{
if (to_file) {
fprintf( (FILE*) ptr, "stuff here");
} else {
sprintf( (char*) ptr, "stuff here");
}
}
However, for a strict answer to your question...
As you've found, the typedef line that you've attempted doesn't work. typedef is a compile time operation, not a runtime operation.
What you could do, though, is to define a type for a function pointer that matches both the fprintf() and sprintf() functions:
typedef int (*someprintf_ptr)(FILE *stream, const char *format, …);
The write_somewhere() would then look like:
void write_somewhere(void *ptr, someprintf_ptr func)
{
func(ptr, "stuff here");
}
/* with calls looking like... */
write_somewhere( (void *)a_file_ptr, (someprintf_ptr)(fprintf));
Your write_something function would have to be something like:
void write_something(void (*function)(), int to_file)
{
....
}
Try making myprintf a function
void write_somewhere(void *ptr, int to_file)
{
myprintf(to_file, ptr, "stuff here");
// do stuff
/* 1000s of similar lines below */
}
void myprintf( int to_file, void *ptr, char *output )
{
if (to_file)
fprintf( ptr, output );
else
sprintf( ptr, output );
}
Let me try:
struct target {
int (*tgtfunction)();
void* ptr;
}
struct target mktarget_file(FILE * fp) {
struct target tgt = { .tgtfuntion = vfprintf, .ptr = fp };
return tgt;
}
struct target mktarget_string(char * str) {
struct target tgt = { .tgtfuntion = vsprintf; .ptr = str };
return tgt;
}
void tgtprintf(struct target * target, char * fmt, ...) {
va_list ap;
va_start(ap, target);
int ret = target.tgtfunction(target.ptr, fmt, ap);
va_end(ap);
return ret;
}
void write_stuff(struct target * target)
{
tgtprintf(target, "stuff here");
/* 1000s of similar lines below */
}
should do what you want: create a struct target for your wanted target, and just call write_stuff to write your stuff there.
Be aware that the sprintf stuff might need to be refined, as each string is written to the same place instead of appended, and there is no check for free space. But the general concept could start like this.

How to print contents of va_list in ansi c

I am trying to print the contents of a va_list,
I want to pass an array to it
I am getting gibrish in return
int printVA(int num_args,...);
int main(int argc, const char * argv[])
{
int numArgs = 3;
int arr [3];
arr[0]=183;
arr[1]=184;
arr[2]=15;
printVA(numArgs,arr);
return 0;
}
int printVA(int num_args,...){
va_list arg_list;
int my_arg;
va_start(arg_list, num_args);
for(int i = 0; i<num_args;i++){
my_arg = va_arg(arg_list, int);
printf("%d\n", my_arg);
}
va_end(arg_list);
return 1;
}
this is what i get
1606416584
15
1606416584
You are calling it incorrectly, pass the arguments themselves, not an array of them:
printVA(numArgs, arr[0], arr[1], arr[2]);
or simply:
printVA(numArgs, 183, 184, 15);
On the other hand, if you really want to pass the array, va_list is not the right solution.

What is the best way to generate a path in C?

I need to generate three different types of paths on runtime:
/sys/class/gpio/gpio%d
/sys/class/gpio/gpio%d/value
/sys/class/gpio/gpio%d/direction
Currently I generate these by doing the following:
#define GPIO_PATH_BASE "/sys/class/gpio/gpio"
#define GPIO_PATH_DIRECTION "/direction"
#define GPIO_PATH_VALUE "/value"
int open_gpio(const char * port) {
char * base_path = (char *) malloc(sizeof(GPIO_PATH_BASE) + sizeof(port));
strcpy(base_path, GPIO_PATH_BASE);
strcat(base_path, port);
char * value_path = (char *) malloc(sizeof(base_path) + sizeof(GPIO_PATH_VALUE));
strcpy(value_path, (const char *) base_path);
strcat(value_path, GPIO_PATH_VALUE);
char * dir_path = (char *) malloc(sizeof(base_path) + sizeof(GPIO_PATH_DIRECTION));
strcpy(dir_path, (const char *) base_path);
strcat(dir_path, GPIO_PATH_DIRECTION);
}
I am actually quite unhappy with this approach. Is there a possibility to let a macro this stuff for me or should I create a helper function?
Bodo
You can make a function that takes two parts, allocates the space, and concatenates them. This should reduce the code duplication, while keeping your code readable:
static char *concat(const char* prefix, const char* suffix) {
size_t len = strlen(prefix) + strlen(suffix) + 1;
char *res = malloc(len);
strcpy(res, prefix);
strcat(res, suffix);
return res;
}
Now you can use this function as follows:
char * base_path = concat(GPIO_PATH_BASE, port);
char * value_path = concat(base_path, GPIO_PATH_VALUE);
char * dir_path = concat(base_path, GPIO_PATH_DIRECTION);
I find sprintf (or snprintf as mentionned by #larsmans) more suitable for string manipulations, especially if you want to add decimal values in your string.
I would use PATH_MAX (defined in limits.h) to have a statically allocated buffer like:
#include <limits.h>
#include <stdio.h>
unsigned char path[PATH_MAX];
#define GPIO_PATH_BASE "/sys/class/gpio/gpio"
#define GPIO_PATH_VALUE "/value"
int main(void)
{
snprintf(path, PATH_MAX, "%s/%d%s", GPIO_PATH_BASE, 42, GPIO_PATH_VALUE);
puts(path);
return 0;
}
$ make main
cc main.c -o main
$ ./main
/sys/class/gpio/gpio/42/value
$
If your system supports it, then asprintf() is the easiest mechanism:
#define GPIO_PATH_BASE "/sys/class/gpio/gpio"
#define GPIO_PATH_DIRECTION "/direction"
#define GPIO_PATH_VALUE "/value"
int open_gpio(const char * port)
{
char *base_path = asprintf("%s%s", GPIO_PATH_BASE, port);
char *value_path = asprintf("%s%s", base_path, GPIO_PATH_VALUE);
char *dir_path = asprintf("%s%s", base_path, GPIO_PATH_DIRECTION);
//...do some work with these...or return them...
//...should check for failed allocations, too...
}
If your system doesn't support asprintf(), you can 'fake' it with:
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
/* Should be in a header */
#ifndef HAVE_ASPRINTF
extern int asprintf(char **ret, const char *format, ...);
extern int vasprintf(char **ret, const char *format, va_list args);
#endif
#ifndef HAVE_ASPRINTF
int vasprintf(char **ret, const char *format, va_list args)
{
va_list copy;
va_copy(copy, args);
/* Make sure return pointer is determinate */
*ret = 0;
int count = vsnprintf(NULL, 0, format, args);
if (count >= 0)
{
char* buffer = malloc(count + 1);
if (buffer != NULL)
{
count = vsnprintf(buffer, count + 1, format, copy);
if (count < 0)
{
free(buffer);
buffer = 0;
}
*ret = buffer;
}
}
va_end(copy);
return count;
}
int asprintf(char **ret, const char *format, ...)
{
va_list args;
va_start(args, format);
int count = vasprintf(ret, format, args);
va_end(args);
return(count);
}
#endif /* HAVE_ASPRINTF */
I quite like to use sprintf to generate strings like this. But that assumes that you have a reasonable maximum size that you know won't be exceeded.
Of course, that's at least a little better than sizeof(base_path), which is completely wrong.
Using malloc also seems like a bad idea for variables that aren't being visible outside the module.
If we assume that port is the correct string, something like this:
char base_path[100];
sprintf(base_path, "%s/%s", GPIO_PATH_BASE, port);

Printing function with variable number of arguments

I have this function:
void print(THashEntry *entry, ...)
{
va_list parameters;
va_start(parameters, entry);
while (true)
{
THashEntry *currentEntry = va_arg(parameters, THashEntry *);
if (!currentEntry)
{
break;
}
printf("%s\n", currentEntry->value);
}
va_end(parameters);
}
I pass adresses of these entries into the function and then I want to access their member "value" and print it.
However when I try to obtain a parameter via va_arg, it returns me not the first, but the second parameter right from the start and when another loop of cycle goes in, it's segmentation fault.
As John Kugelman states in his answer, here are some of the good practices to pass variable number of arguments to printf/sprintf:-
void Error(const char* format, ...)
{
va_list argptr;
va_start(argptr, format);
vfprintf(stderr, format, argptr);
va_end(argptr);
}
I apologize for butting into your design but this might be an alternative to use
struct abc {
int a;
char b[10];
};
void f(int size, abc* a) {
for (int i = 0; i < size; i++) {
abc x = a[i];
}
}
int _tmain(int argc, _TCHAR* argv[])
{
abc *arrAbc = new abc[10];
for (int i = 0; i < 10; i++) {
arrAbc[i].a = 0;
}
f(10, arrAbc);
}
va_arg won't return NULL when you reach the end of argument list. As man va_arg says:
random erros will occur
So to get around it you either need to pass number of arguments to your print function, or end terminator.
To automatically calculate number of arguments at compile time, you can use macro
#define NUMARGS(...) (sizeof((int[]){__VA_ARGS__})/sizeof(int))
See more details in this answer
Seems like there are quite a few answers, but personally I've never found a great way to get around dynamically counting the number of args in a va_list.
That said, there are several ways around it:
Use the NUMARGS(...) macro as noted by qrdl
Pass the number of args into the function like as main does void print(int numArgs, MyEntry *entry, ...)
Use a NULL terminated list
The latter happens to be my personal preference, since it tends to go with my (and it looks like yours too) instinct to how to catch the end of the list. See below:
#import <stdarg.h>
typedef struct MyEntry {
int a;
int b;
} MyEntry;
void print(int numArgs, MyEntry *entry, ...) {
va_list parameters;
va_start(parameters, entry);
MyEntry *m;
for ( m = entry; m != NULL; m = va_arg(parameters, MyEntry *)) {
printf("%d\n", (int)m->a);
}
va_end(parameters);
}
int main(int argc, char *argv[]) {
MyEntry entry = { 10, 20 };
MyEntry entry2 = { 30, 40 };
MyEntry entry3 = { 50, 60 };
MyEntry entry4 = { 70, 80 };
MyEntry entry5 = { 90, 100 };
print(2, &entry, &entry2, &entry3, &entry4, &entry5, NULL);
return 1;
}
Happy coding!

In pure C how can I pass a variable number of parameters into a function?

How can i pass (and access) using C, not c++, variable parameters into a function?
void foo(char* mandatory_param, char* optional_param, char* optional_param2...)
thanks
/fmsf
Use stdarg.h
You need to use va_list and then use the macros va_start, va_arg, and va_end.
For more information, see http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.10.html
It sounds like you are looking for varargs.
#include <stdarg.h>
void foo(const char *fmt, ...)
{
va_list argp;
va_start(argp, fmt);
int i = va_arg(argp, int);
// Do stuff...
va_end(argp);
}
Read about Variable Arguments in C
#include <stdarg.h>
void do_sth (int foo, ...)
{
int baz = 7; /* "baz" argument */
const char *xyz = "xyz"; /* "xyz" argument */
/* Parse named parameters */
va_list ap;
va_start (ap, foo);
for (;;) {
const char *key = va_arg (ap, char *);
if (key == NULL) {
/* Terminator */
break;
} else if (strcmp (key, "baz") == 0) {
baz = va_arg (ap, int);
} else if (strcmp (key, "xyz") == 0) {
xyz = va_arg (ap, char *);
} else {
/* Handle error */
}
}
va_end (ap);
/* do something useful */
}
do_sth (1, NULL); // no named parameters
do_sth (2, "baz", 12, NULL); // baz = 12
do_sth (3, "xyz", "foobaz", NULL); // xyz = "foobaz"
do_sth (4, "baz", 12, "xyz", "foobaz", NULL); // baz = 12, xyz = "foobaz"
Variadic functions and arguments assignment in C/C++
In a language that does not support optional parameters directly, there are a few ways to achieve a similar effect. I will list them in order from the least versatile to the most:
Create multiple overloads of the same function. As I recall, you cannot do this in C.
Use variadic functions. Just Google this: http://www.google.com/search?q=variadic+function+c
I recommend this: Create a "params" or "args" class (or struct in C), like this:
)
// untested C code
struct FooArgs {
char * mandatory_param;
char * optional_param;
char * optional_param2;
// add other params here;
};
and then make your method call take in a single argument:
// untested
void foo(struct fooArgs * args)
This way, as needs change, you can add parameters to fooArgs without breaking anything.
I have a solution that does not use VA_LIST in pure C. However, it works at 32bits only. Here, what happens is that each parameter of the call stack occupies as many bytes according to its type. It is possible to create a structure with a size larger than 4 or 8 bytes, so just align all the parameters in this structure.
int printf(void*,...);
typedef struct{
char p[1024];
}P_CALL;
int soma(int a,int b){
return a+b;
}
void main(){
P_CALL
call;
char
*pcall=(void*)&call;
int
(*f)()=soma,
res;
*(int*)pcall=1;
pcall+=sizeof(void*);
*(int*)pcall=2;
pcall+=sizeof(void*);
res=f(call);
printf("%d\n",res);//3
}

Resources