假设我有一个可变函数foo(int tmp, ...),当调用foo函数时,我需要知道有多少个参数.我知道有两种方法可以找出有多少参数:
在调用foo时使用最后一个参数,比如-1,所以你的函数调用将是这样的:foo(tmp, 1, 2, 9, -1)当你在foo内部并且va_arg调用返回-1时你知道你已经读取了所有的函数参数
在foo中再添加一个参数,程序员将拥有参数总数,因此你可以像这样调用foo:foo(tmp, 5, 1, 2, 3, 4, 5)或者foo(tmp, 2, 7, 8)
我曾经遵循第一种方式,曾经有过以下错误.随着代码:
expr_of_type(expr, boolexpr_e, newtable_e, nil_e, -1)
Run Code Online (Sandbox Code Playgroud)
其中expr_of_type是一个可变参数函数,并检查expr(第一个参数)是否是以下类型之一(boolexpr_e或new_table_e或nil_e具有所有类型的枚举类型).我一个人意外地写道:
expr_of_type(expr, boolexpr_e, newtable_e, nil_e -1)
Run Code Online (Sandbox Code Playgroud)
我忘记了nil_e和-1之间的逗号,因为nil_e有一个枚举类型,nil_e - 1是一个有效的表达式,因为nil_e不是0,当试图获取expr_of_type参数时,给定的变量函数没有找到-1作为最后一个参数继续搜索创建一个花了我一些时间才发现的bug.
我也没有找到第二种方式,因为当从可变参数函数中添加或删除一个参数时,您需要更改包含总参数数量的参数.
在寻找更好的方法来使用/创建可变参数函数时,我找到了可变的宏,它可以解决我在使用第一种方式时遇到的错误.但是可变参数宏可用于C99标准.我一直在寻找一种在C89中使用/创建可变参数函数的更好方法.有任何想法吗?
我学会了使用库stdarg.h来获取具有未知数量参数的函数.这是一个简单的函数如何使用:
void print(int args,...){
va_list ap;
va_start(ap, args);
int i = 0;
for(i=0; i<args; i++){
printf("%d\n",va_arg(ap, int));
}
va_end(ap);
}
Run Code Online (Sandbox Code Playgroud)
基于上面的代码,有两个主要的约束,我不知道如何printf 克服:
1)固定数量参数:意思是,在几乎vardiac函数中,你需要包含args的数量.但是当我写作时printf,我不必包括这个数字.我以为在printf真正使用参数之前,它已经计算了之前的参数数量(通过计算第一个字符串中的数字%).但同样,我认为这个解决方案有点效率不高.它必须通过三个pharses:计算参数数量,并将这些参数放入堆栈,最后将所有参数放入屏幕.
2)所有参数必须具有相同的类型: 如下所示:printf("%d\n",va_arg(ap, int));.因此,列表中的每个参数都必须具有相同的类型.而且正如我们所知,这不是printf中必须的.您可以使用整数或字符串打印double.如果我们将所有这些视为一个字符串,那么这一行应该是错误的,因为错误的语法:
printf("%d",4); //4 cannot treat by string
printf("%d",'4'); // :)) I think this line is better
Run Code Online (Sandbox Code Playgroud)
请帮我解释一下上面两个问题.
我有一个非常简单的代码.此代码适用于Linux机器.但是当我使用交叉编译构建并在Embbedded Hardware参数上运行时,可变参数函数的值是错误的.它是关于编译(交叉编译)?所有应用程序运行良好但可变功能不起作用.
我的示例代码如下.foo和formatString函数都工作错误.
void foo(char *fmt, ...)
{
va_list ap;
int d;
char c, *s;
va_start(ap, fmt);
while (*fmt)
{
switch (*fmt++)
{
case 's' :
s = va_arg(ap, char *);
printf("string %s\n", s);
break;
case 'd' :
d = va_arg(ap, int);
printf("int %d\n", d);
break;
case 'c':
c = (char) va_arg(ap, int);
printf("char %c\n", c);
break;
}
va_end(ap);
}
void formatString(char* format, ...)
{
va_list args;
char buffer[100];
va_start(args, format);
sprintf(buffer, format, args);
va_end(args);
printf((char*)buffer);
}
int main(int argc, …Run Code Online (Sandbox Code Playgroud) 我对目标c变量参数函数一无所知.我想编写一个将采用nlsog类型参数的函数,但有时我会在该函数中使用NSLog.我怎样才能做到这一点?
-(void) printStatus:(NSString*)status, ...
{
// I want use use NSLog with all these parameter here.
// some gui logging also happens here
}
Run Code Online (Sandbox Code Playgroud)
电话会是这样的,
[self printStatus:@"status"];
Run Code Online (Sandbox Code Playgroud)
要么
[self printStatus:@"Staus: %@", someObject];
Run Code Online (Sandbox Code Playgroud)
而不是使用NSLog,我想使用printStatus.当我需要将控制台日志切换到GUI日志记录时,我只能更改为printStatus函数,而不是更改代码中的所有位置.
或者在我这里使用DLog,
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
# define DLog(...) /* */
#endif
Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一个类似于此的函数:
#define printf_copy(s, ...) printf(s, ##__VA_ARGS__) // acceptable!
Run Code Online (Sandbox Code Playgroud)
但这是一个预处理器,我需要一个运行时,如下所示:
+ (NSString *)format:(NSString *)first, ...
{
return [NSString stringWithFormat:first, __VA_ARGS__]; // unacceptable!
}
Run Code Online (Sandbox Code Playgroud)
但!!编译器这是不可接受的!
我想弄清楚(...)的局部变量是什么?(是的那3个点)
不幸的是,我得到了"太多的输入参数".执行此调用时出错:
[varargout{1:nargout}]=pca(varargin{1},'Algorithm','svd','Economy',fEconomy);
Run Code Online (Sandbox Code Playgroud)
关于具有签名的功能如下:
function [coeff, score, latent, tsquared, explained, mu] = pca(x,varargin)
Run Code Online (Sandbox Code Playgroud)
我用这种方式调用princomp:
[pc,score,latent,tsquare] = princomp(data);
Run Code Online (Sandbox Code Playgroud)
知道可能是什么原因的任何想法?(该错误出现在stats包的princomp.m中)
有谁知道我们如何以自动方式从任何Seq转换为_*?每次我们有Seq时强制类型并且方法使用类型为vararg的参数非常麻烦.
def mean[T: Numeric](elems: T*): Double
...
elems = Seq(1.0, 2.0, 3.0)
mean(elems) // this doesn't compiles
mean(elems: _*) // this compiles but it is cumbersome
Run Code Online (Sandbox Code Playgroud) 我有一个类模板管道:
template <typename A, typename B> class Pipeline;
Run Code Online (Sandbox Code Playgroud)
我想创建一个可变参数函数模板,接受任意数量的任意Pipelines,我想以一种棘手的方式约束它们.非可变代码看起来像:
Pipeline<A, C> compose(Pipeline<A, B> p1, Pipeline<B, C> p2);
Pipeline<A, D> compose(Pipeline<A, B> p1, Pipeline<B, C> p2, Pipeline<C, D> p3);
// ...and so on
Run Code Online (Sandbox Code Playgroud)
现在是否有可能以可变方式端到端地约束它们?
// I would like to write something like:
Pipeline<Args[0], Args[len(Args)-1]> compose(Pipeline<Args[i], Args[i+1]> ps...);
Run Code Online (Sandbox Code Playgroud) 我知道现代C++中的可变参数模板是什么,但是我无法绕过它以便能够编写如下代码:
#include <iostream>
#include <sstream>
using namespace std;
template <typename... Args, typename Combinator>
auto combine(Args... args, Combinator combinator)
{
auto current_value = combinator(args...);
return current_value;
}
int main() {
auto comb = combine(1, "asdf"s, 14.2,
[](const auto& a, const auto& b, const auto& c) {
stringstream ss;
ss << a << "\n";
ss << b << "\n";
ss << c << "\n";
return ss.str();
});
return 0;
}
Run Code Online (Sandbox Code Playgroud)
换句话说,我想给函数提供一个未知数量的不同类型的参数,但最后一个参数是lambda或用于以某种方式组合参数的任何可调用对象.这个例子看起来纯粹是学术性的,但在这个例子的基础上,我想构建更多时髦的代码,但首先我需要这个来编译.希望你能帮忙!
我无法编译.我不知道我错过了什么.
以下是GCC吐口水:
In function 'int main()':
21:6: error: no matching function …Run Code Online (Sandbox Code Playgroud) 在Java中,可以执行以下操作:void function(Url... urls).它可以使用1..n网址.问题是,是否有可能与Kotlin做同样的事情.