所以我有2个函数都有相似的参数
void example(int a, int b, ...);
void exampleB(int b, ...);
Run Code Online (Sandbox Code Playgroud)
现在example调用exampleB,但是如何在不修改的情况下传递变量参数列表中的变量exampleB(因为这已经在别处使用过了).
我有大约30个可变函数.每个人都接受一个路径作为最终参数,例如:
bool do_foo(struct *f, int q, const char *fmt, ...)
Run Code Online (Sandbox Code Playgroud)
在每个函数中,我必须检查扩展格式是否小于或等于特定大小.所以,我发现自己复制/粘贴相同的代码块来检查vsnprintf()没有打印多少个字符,相应地设置并保留errno写入.
我想要做的是编写一个函数来执行此操作,这将返回一个已知为安全大小的静态分配(扩展)字符串,或者在失败时新初始化的字符串,可以针对NULL进行检查.检查还必须确定字符串是绝对路径还是相对路径,这会影响字符串的安全大小.这是很多重复的代码,它开始闻起来.
有没有办法可以将elipsis的内容从我的函数的条目传递给另一个函数?或者我必须先调用va_start(),然后传递va_list给辅助函数?
编辑:
我完全不反对把它传递va_list给帮助者,我只是想确保没有别的东西存在.在我看来,编译器理解可变参数的开始位置,所以我只是好奇我是否可以告诉它传递它们.
我的目标是在OSX环境中的QT项目中使用C++解析大型csv文件.(当我说csv我的意思是tsv和其他变种1GB~5GB).
这似乎是一项简单的任务,但是当文件大小变大时,事情会变得复杂.我不想编写自己的解析器,因为许多边缘情况与解析csv文件有关.
我已经找到了各种csv处理库来处理这个工作,但解析1GB文件在我的机器上大约需要90~120秒,这是不可接受的.我现在没有对数据做任何事情,我只是为了测试目的而处理和丢弃数据.
cccsvparser是我尝试过的库之一.但唯一足够快的库是fast-cpp-csv-parser,它给出了可接受的结果:我的机器上15秒,但只有在知道文件结构时它才有效.
使用示例:fast-cpp-csv-parser
#include "csv.h"
int main(){
io::CSVReader<3> in("ram.csv");
in.read_header(io::ignore_extra_column, "vendor", "size", "speed");
std::string vendor; int size; double speed;
while(in.read_row(vendor, size, speed)){
// do stuff with the data
}
}
Run Code Online (Sandbox Code Playgroud)
如你所见,我无法加载任意文件,我必须专门定义变量以匹配我的文件结构.我不知道任何允许我在运行时动态创建这些变量的方法.
我尝试过的另一种方法是逐行读取csv文件,使用fast-cpp-csv-parser, LineReader类非常快(读取整个文件大约需要7秒),然后使用可以处理字符串的cccsvparser lib 解析每一行.但这需要大约40秒才能完成,与第一次尝试相比这是一个改进,但仍然是不可接受的.
我已经看到了与csv文件解析相关的各种stackoverflow问题,它们都没有将大文件处理到帐户中.
此外,我花了很多时间谷歌搜索找到这个问题的解决方案,我真的很想念包裹经理喜欢npm或pip在搜索开箱即用的解决方案时提供的自由.
我将不胜感激任何有关如何处理此问题的建议.
编辑:
当使用@fbucek的方法时,处理时间减少到25秒,这是一个很大的改进.
我们可以进一步优化这个吗?
在我的应用程序中,我有很多日志.我确实在一个叫做的地方累积了所有日志中的所有错误errorsLogger.我用这种方式实现了它:
static Logger errorsLogger;
....
void Logger::Error(std::string format, ...) {
va_list arglist;
va_start(arglist, format);
if (this != &errorsLogger) {
errorsLogger.Error(format, arglist); // how to forward parameters?
}
vfprintf(logFile, , format.c_str(), arglist);
fprintf(logFile, "\n");
fflush(logFile);
va_end( arglist );
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码没有按预期工作errorsLogger包含一些奇怪的字符串 - 似乎变量参数没有传递.如何修复我的代码有效?
我有两个可变函数作为foo(format, ...)和bar(format, ...).我想实现函数,foo以便它可以bar使用相同的参数列表调用它.那是,
foo(format...)
{
...
bar(format, ...);
}
Run Code Online (Sandbox Code Playgroud)
例如,调用foo("(ii)", 1, 2)将bar使用相同的参数调用bar("(ii)", 1, 2).该foo功能应该如何实施?
PS:函数bar来自遗留库,我无法更改其界面.
与其说是一个知识共享问题.
根据GoogleMock 常见问题解答,无法模拟可变参数函数,因为不知道将为函数提供多少参数.
这是事实,但在大多数情况下,人们知道从被测系统调用可变参数函数有多少变量,或者如何将可变参数转换为1个非变量参数.
我的一位同事(不知道他是否在Stackoverflow上活动)想出了一个工作解决方案,如下面的例子所示(使用模拟器进行C型接口):
class MockInterface
{
public:
MockInterface() {}
~MockInterface() {}
MOCK_METHOD4( variadicfunction, void( const std:: string name, AN_ENUM mode,
const std::string func_name, const std::string message ) );
};
boost::shard_ptr<MockInterface> mock_interface;
extern "C"
{
void variadicfunction( const char *name, AN_ENUM mode,
const char *func_name, const char *format, ... )
{
std::string non_variadic("");
if (format != NULL )
{
va_list args;
va_start( args, format );
// Get length of format including arguments
int nr = vsnprintf( NULL, 0, …Run Code Online (Sandbox Code Playgroud) 考虑可变参数函数参数:
func foo(bar:Int...) -> () { }
Run Code Online (Sandbox Code Playgroud)
这里foo可以接受多个参数,例如foo(5,4).我很好奇Int...它的类型和支持的操作.例如,为什么这个无效?
func foo2(bar2:Int...) -> () {
foo(bar2);
}
Run Code Online (Sandbox Code Playgroud)
给出错误:
无法找到接受所提供参数的'_conversion'的重载
为什么转发可变参数无效?
什么是编译器抱怨的"转换"?
我试图在系统函数上创建一个钩子open().我按照以下几点做了这个.
我创建了一个包装库,其中包含以下内容:
extern int mocked_open(const char* fn, int flags, va_list args);
int open(const char* fn, int flags, ...)
{
int r = -1;
va_list args;
va_start(args, flags);
r = mocked_open(fn, flags, args);
va_end(args);
return r;
}
Run Code Online (Sandbox Code Playgroud)
我将其编译为libwrapper.so,我使用LD_PRELOAD加载.
执行mocked_open()如下(我使用CPPUtest框架):
int mocked_open(const char* fn, int flags, va_list args)
{
if (strncmp(fn, test_device_id, 11) == 0)
{
return mock().actualCall("open").returnValue().getIntValue();
}
else
{
int r = -1;
int (*my_open)(const char*, int, ...);
void* fptr = dlsym(RTLD_NEXT, "open");
memcpy(&my_open, &fptr, sizeof(my_open)); …Run Code Online (Sandbox Code Playgroud) 似乎GLIBC 2.28(于2018年8月发布)对fcntl进行了相当激进的更改。定义已更改<fcntl.h>为不再是外部函数,而是#define更改为fcntl64。
其结果是,如果你的系统上使用此glibc的编译代码-如果它使用的fcntl()在所有从2018年八月前--the生成的二进制文件将不能在系统上执行这会影响到相当多的各种应用.. .fcntl()的手册页显示,这是一小部分子功能的入口:
https://linux.die.net/man/2/fcntl
如果您可以告诉链接器所需的GLIBC函数的特定版本,那就太好了。但是我发现最接近的是在另一篇文章的答案中描述的这个技巧:
这有点复杂。 fcntl是不vffcntl带va_list的可变参数。在这种情况下,您无法转发可变参数函数的调用。:-(
当一个程序具有稳定的代码且具有较低的依赖关系时,就很难在当前的Ubuntu上构建它了……然后让可执行文件拒绝在仅一年前(近日)发布的另一个Ubuntu上运行。一个人有什么追索权?
有一个功能:
void some_function(int id,...);
Run Code Online (Sandbox Code Playgroud)
问题:有没有办法包装这个功能?这意味着得到这样的东西:
void wrapped_some_function(int id,...)
{
//do smth
some_function(id,...);
}
Run Code Online (Sandbox Code Playgroud)