C++ & C arg_list函数
C++ & the C arg_list functions
我需要模拟一个库类型,该类型允许将其同时视为char*&std::字符串。例如,这应该是允许的:
char c[16];
MyString ms;
...
strcpy(c, ms);
strcpy(c, ms.c_str());
我只控制库,但不幸的是无法更改此库的使用。我无法更改printf调用,只能更改发送给它的类型!
例如,我可以通过实现来做到这一点
class MyString : public string {
public:
operator const char*();
};
问题在于:
sprintf(c, "%s", ms);
C"arg_list"函数将不使用char*强制转换。
有什么建议吗?
谢谢。
您只能向...
传递一般可复制的POD。
你可以做
struct wrapper { const char * it; };
wrapper it{"hello"};
printf("%s", it);
但问题是,你无法管理内存。一旦您尝试添加构造函数和析构函数来分配/释放内存,就会遇到错误。
错误:无法通过"…"传递非普通可复制类型"class mystr"的对象
你可以帮助自己:
const char * c_str(const char * it) { return it; }
const char * c_str(const std::string& it) { return it.c_str(); }
const char * cstr = "hello";
std::string cppstr = "world";
printf("%s %s!", c_str(cstr), c_str(cppstr));
或者使用boost::format
(或类似的ostream
)。您应该为C++使用ostream/format(类型安全)。
你说:
问题在于:
sprintf(c,"%s",ms);
C"arg_list"函数将不使用char*铸造。
这里没有石膏。sprintf(..., "%s")
不会将ms
强制转换为任何值,因此它永远不会调用您的转换运算符。演员阵容为:sprintf(c, "%s", (const char *)ms)
。与strcpy不同,va_list不会导致强制,因为没有参数类型。
您可以将对象传递给va_list函数,但需要显式强制转换参数以调用正确的类型转换,或者使用.c_str()
如果printf()可以根据其格式说明符隐式处理C++对象,那么它肯定已经在该语言中了,因为它可能是最需要的库函数之一,而不是从C.映射过来的
如果你打算使用printf()和family,只需写下:
printf("%s", foo.c_str());
或者试试这样的东西(正如@firda在评论中所建议的):
const char * c_str(const std:string &s) { return s.c_str(); }
const char * c_str(const char * s) { return s; }
然后你一直写:
printf("%s%s", c_str(foo), c_str(bar));
普通C++变量函数不能与对象实例一起工作,因为值必须是位可复制的(被调用的函数不知道编译时传递的对象的类型)。
然而,使用C++11,您可以编写一个可变模板,该模板负责使用调用站点类型知识来解包参数:
#include <string>
#include <stdio.h>
#include <string.h>
int mysprintf(char *buf, const char *fmt) {
return sprintf(buf, "%s", fmt);
}
template<typename T, typename... Args>
int mysprintf(char *buf, const char *fmt, const T& x, Args... args) {
const char *sp = strchr(fmt, '%');
if (sp) {
while (fmt < sp) *buf++ = *fmt++;
std::string fmt1(fmt, fmt+2);
int sz = sprintf(buf, fmt1.c_str(), x);
return sz + mysprintf(buf+sz, fmt+2, args...);
} else {
fputs("Invalid format stringn", stderr);
std::abort();
return 0;
}
}
template<typename... Args>
int mysprintf(char *buf, const char *fmt, const std::string& x, Args... args) {
const char *sp = strchr(fmt, '%');
if (sp) {
if (sp[1] != 's') {
fputs("Invalid format string (%s expected)n", stderr);
std::abort();
}
while (fmt < sp) *buf++ = *fmt++;
std::string fmt1(fmt, fmt+2);
int sz = sprintf(buf, fmt1.c_str(), x.c_str());
return sz + mysprintf(buf+sz, fmt+2, args...);
} else {
fputs("Invalid format stringn", stderr);
std::abort();
return 0;
}
}
int main() {
char buf[200];
std::string foo = "foo";
const char *bar = "bar";
int x = 42;
mysprintf(buf, "foo='%s', bar='%s', x=%i", foo, bar, x);
printf("buf = "%s"n", buf);
return 0;
}
注意:为了简单起见,此代码不处理任何格式化选项或%
转义,但允许对裸char *
和std::string
使用%s
。
注2:我并不是说这是个好主意。。。这是可能的
- 如何将 std::list of 派生类而不是 std::list of parent class 传递给函数
- std::list 模板是否需要其实例类型中的复制构造函数(或等效项)?
- constexpr constructor initialiser list 中的 constexpr 函数
- 将 std::list<std::unique_ptr> 移动到向量中会尝试引用已删除的函数
- 如何从 JNI 传递 std::list 参数来调用本机 C++ 函数
- Rcpp 中"List"的操作函数 - 类似于 R 中的"Reduce function"
- 为什么 std::list::splice 不是一个免费函数?
- 返回在函数中创建的 std::list 的第一个节点
- 按值将 std::list 从一个函数传递到另一个函数
- 将数组传递给在 arg-list 中接受双指针的函数
- 错误:没有用于初始化'List<double>::node'的匹配构造函数
- 'list::list'命名构造函数,而不是类型
- 我正在收到错误的“ list :: ShowList”:功能风格的初始化器似乎是我的CPP文件中的函数定义'
- C++ STL (std::unordered_set) 中没有用于 std::list 的哈希函数
- 没有匹配函数调用 std::list::remove_if( function()::p redicate )
- 为什么C++ std::list::clear() 不调用析构函数
- 将 std::list<boost::any> 作为函数的参数传递
- 通过 BaseClass List 调用派生类对象的析构函数
- 如何使用list::sort()对STL列表对象进行排序,同时将自定义排序函数作为参数传递给list::排序
- std::list.remove 正在调用析构函数,但不删除它