Can You Pass a Vector to a Vararg: Vector to Sprintf

how to print a variable number of arguments in r?

The doc is right. In first case, do.call(sprintf, c(list("%s %s"), vec)) is equal to:

sprintf("%s %s", "a","b","c","d")

The fmt string "%s %s" requires two vectors while you provided four and the last two ("c", "d") were not used for printing.

The second case is similar. do.call(sprintf, c(fmt = base_string, as.list(v1))) is equal to:

sprintf(fmt = "%s, %s, %s", "foo", "bar", "baz","foo", "bar", "baz")

Three variables were to be printed based on fmt but you provided six.


Then, what does "recycled" in the doc mean?

and I guess you might misunderstand it. It means when the formating string and vectors are of different lengths, the short er ones will be recycled to the longest one. An example:

> sprintf(c('%s %s', '%s, %s'), c('a', 'b', 'c'), 1:6)
[1] "a 1" "b, 2" "c 3" "a, 4" "b 5" "c, 6"

How to print variable number of arguments: You can try paste:

> sprintf(paste0(vec, collapse = ' '))
[1] "a b c d"
> sprintf(paste0(v1, collapse = ', '))
[1] "foo, bar, baz, foo, bar, baz"

how to wrap a function that only takes individual elements to make it take a list

You are looking for do.call:

f <- function(x,y,z)x+y+z
do.call(f,list(1,2,3))
[1] 6

Replace the argument with a list in R

You are looking for do.call.

do.call(f, argv)

Here are some examples

> args <- list(n = 10, mean = 3, sd = .5)
> do.call(rnorm, args)
[1] 3.589416 3.393031 2.928506 2.503925 3.316584 2.581787 2.686507 3.178877
[9] 3.083885 2.821506
> do.call(rnorm, list(10, 3, .5))
[1] 3.964526 2.838760 2.436684 3.068581 1.842332 3.739046 4.050525 3.097042
[9] 3.665041 3.535947
> f <- function(a, b) a + b
> argv <- list(a=1, b=2)
> do.call(f, argv)
[1] 3
> f <- function(a, b, ...){print(a);print(b);print(sum(...))}
> argv <- list(a=1,b=2, 3, 4, 5)
> do.call(f, argv)
[1] 1
[1] 2
[1] 12

How do i make a function with a variable number of parameters?

First of all Variadic arguments from C are considered a bad practice in C++ and should be avoided.

There are plenty of better C++ solutions which are able to replace this C feature.

Old fashioned std::vector:

std::vector<int> filterPrimes(std::vector<int> a) {
auto end = std::remove_if(a.begin(), a.end(), [](auto x) {
return !isPrime(x)
};
a.remove(end, a.end());
return a;
}

Or std::initializer_list

std::vector<int> filterPrimes(std::initializer_list<int> l) {
std::vector<int> r;
std::copy_if(l.begin(), l.end(), std::back_inserter(r), isPrime);
return r;
}

Or Variadic templates, or template with iterator ranges, or ... .

C++ varargs wrapper for a vsnprintf function unitended behaviour

Since you cannot reuse a va_list, you should recreate it in order to repeat the print:

void sprintf(char *format, ...)
{
while(true)
{
va_list args;
va_start (args, format);

int c = vsnprintf(&data[pos],size-pos,format,args);

va_end (args);

// this value is different on windows and linux (or msvc and gcc)
if((c == -1) || (c > (size-pos)))
{
this->size *= 2;
data = (char*)realloc(data,this->size);
continue;
}
else
{
pos += c;
data[pos] = 0;
}
return;
}
}


Related Topics



Leave a reply



Submit