我有一个char*,它具有固定(已知)的宽度,但没有以空字符结尾。
我想将其传递给LOG4CPLUS_ERROR("Bad string " << char_pointer);
,但由于它没有以空字符结尾,它会打印全部内容。
有什么轻量级方法可以获取"(char[length])*char_pointer"
而不进行复制吗?
我有一个char*,它具有固定(已知)的宽度,但没有以空字符结尾。
我想将其传递给LOG4CPLUS_ERROR("Bad string " << char_pointer);
,但由于它没有以空字符结尾,它会打印全部内容。
有什么轻量级方法可以获取"(char[length])*char_pointer"
而不进行复制吗?
const char *
和size_t
构建一个std::string
,除非您可以访问底层流对象。 - Nim如果你的目标是打印这样的字符串,你可以:
把所有这些包装在一个函数中。
struct foo
{
char a1[10];
char a2[10];
char a3[10];
char a4[10];
};
// free function to stream the above structure properly..
std::ostream operator<<(std::ostream& str, foo const& st)
{
str << "foo::a1[";
std::copy(st.a1, st.a1 + sizeof(st.a1), std::ostream_iterator<char>(str));
str << "]\n";
str << "foo::a2[";
std::copy(st.a2, st.a2 + sizeof(st.a2), std::ostream_iterator<char>(str));
str << "]\n";
:
return str;
}
foo
的实例,不必担心空终止字符串等!ostream.write(char*,streamsize)
? - Ken Bloomstd :: ostream
派生的对象形式? - Nimiostream
当你写入真正的 iostream 时,你可以直接使用 ostream.write()
,它需要一个 char*
和一个要写入多少个字节的大小--不需要空终止符。(事实上,字符串中的任何空字符都将被写入到 ostream 中,并且不会用于确定大小。)
在一些日志库中,你写入的流并不是真正的 iostream。这在 Log4CPP 中就是这种情况。
然而,在 Log4CPlus 中,这是 matt 所使用的对象,它是一个 std::basic_ostringstream<tchar>
(请参阅 loggingmacros.h
和 streams.h
的定义,因为从文档中无法明确了解)。只有一个问题:在宏 LOG4CPLUS_ERROR
中,第一个 <<
已经内置到宏中,所以他将无法调用 LOG4CPLUS_ERROR(.write(char_pointer,length))
或类似的东西。不幸的是,我没有看到任何简单的方法来避免这种情况,除非解构 LOG4CPLUS_ERROR
错误宏并进入 Log4CPlus 的内部。
我不确定为什么你在这个时候尝试避免复制字符串,因为你可以看到日志库内部有很多复制操作。任何试图避免这种额外的字符串复制的尝试可能都是不必要的优化。
我假设这是代码清洁度的问题,也许是确保复制发生在 LOG4CPLUS_ERROR
宏内部,而不是外部的问题。在这种情况下,只需使用:
LOG4CPLUS_ERROR("Bad string " << std::string(char_pointer, length));
我在我的工具箱中保留了一个字符串引用类,专门用于这些类型的情况。下面是该类的大大简化版本。我已经删除了与此特定问题无关的任何内容:
#include <iostream>
class stringref {
public:
stringref(const char* ptr, unsigned len) : ptr(ptr), len(len) {}
unsigned length() { return len; }
const char* data() { return ptr; }
private:
const char* ptr;
unsigned len;
};
std::ostream& operator<< (std::ostream& os, stringref sr) {
const char* data = sr.data();
for (unsigned len = sr.length(); len--; )
os << *data++;
return os;
}
using namespace std;
int main (int argc, const char * argv[])
{
cout << "string: " << stringref("test", 4) << endl;
}
或者,在你的情况下:
LOG4CPLUS_ERROR("Bad string " << stringref(char_pointer, length));
应该可以工作。
字符串引用类的想法是保留有关字符串的足够信息(大小和指针),以引用表示字符串的任何内存块。它依赖于您确保在字符串引用对象的整个生命周期内基础字符串数据有效。这样,您可以传递和处理字符串信息,而最小化开销。
ostream.write(char*,streamsize)
? - Ken Bloomoperator<<
。我更仔细地查看了matt正在使用的Log4Cplus,从文档中无法确定它是否使用iostreams,但代码示例让我认为它实际上确实使用了。 - Ken Bloom不,你必须复制它。语言中没有适当的转换可以用来获取数组类型。
你想这样做似乎非常奇怪,或者你一开始就有一个非终止的C风格字符串。
为什么不使用std::string
?
std::copy
)。最好的方法是构造一个std::string()
,使用带有const char*
和size_t
参数的变量,并将其流式传输... - Nimstd::string
来复制它。 - Lightness Races in Orbit
'\0'
字符。 - Šimon Tóthsizeof()
,数组和指针在实际上是无法区分的。 - Šimon Tóthint x[];
和float x[];
是兼容的一样。但是float **x;
与float *x[];
兼容,并且float x[a][b];
与float (*x)[a];
兼容。(c) 数组可以隐式转换为第一个元素的指针,这不仅适用于函数调用。 - Šimon Tóthwrite(char*,streamsize)
函数。 - Ken Bloom