char * to char []

时间:2011-04-05 12:34:15

标签: c++

我有char *,它具有固定(已知)宽度,但不会以空值终止。

我想将它传递给LOG4CPLUS_ERROR("Bad string " << char_pointer);,但由于它不是空终止,它会打印出来。

在不执行复制的情况下获得"(char[length])*char_pointer"的轻量级方法的任何建议?

7 个答案:

答案 0 :(得分:7)

不,你必须进行深层复制并将其终止。该代码需要以空字符结尾的字符串,它表示以空终止符结尾的连续字符块。

答案 1 :(得分:5)

如果你的目标是打印这样一个字符串,你可以:

  1. 存储最后一个字节。
  2. 将其替换为\ 0。
  3. 打印字符串。
  4. 打印存储的字节。
  5. 将存储的字节放回字符串的最后位置。
  6. 将所有这些包裹在一个函数中。

答案 2 :(得分:2)

我们对char*char[]之间转换的语义感到困惑。退后一步,你想做什么?如果这是一个错误条件的简单情况,将结构的内容流式传输到流,为什么不正确地执行?

e.g。

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的实例,而不必担心空终止字符串等。!

答案 3 :(得分:2)

真实iostream s

当你写一个真实的iostream时,你可以使用ostream.write(),它需要char*和一个大小来写入多少字节 - 不需要空终止。 (实际上,字符串中的任何空字符都将写入ostream,并且不会用于确定大小。)

记录库

在某些日志记录库中,您写入的流不是真正的iostream。 Log4CPP就是这种情况。

但是,在Log4CPlus这就是亚特正在使用的内容中,您要写的对象是std::basic_ostringstream<tchar>(请参阅loggingmacros.hstreams.h定义,因为文档中没有一个是明显的)。只有一个问题:在宏LOG4CPLUS_ERROR中,第一个<<已内置到宏中,因此他无法调用LOG4CPLUS_ERROR(.write(char_pointer,length))或类似的内容。不幸的是,在没有解构LOG4CPLUS_ERROR错误宏并进入Log4CPlus内部

的情况下,我没有看到一个简单的方法。

解决方案

我不确定你为什么要避免在此时复制字符串,因为你可以看到日志库里面有很多复制。任何避免额外字符串副本的尝试都可能是无根据的优化。

我将假设它是代码清洁的问题,也许是确保副本发生在LOG4CPLUS_ERROR宏内部而不是外部的问题。在这种情况下,只需使用:

LOG4CPLUS_ERROR("Bad string " << std::string(char_pointer, length));

答案 4 :(得分:1)

我在我的工具包中保留了一个字符串引用类,仅用于这些类型的情况。这是该类的大大缩写版本。我删除了与此特定问题无关的任何内容:

#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));

应该有用。

字符串引用类的想法是保留有关字符串(大小和指针)的足够信息,以引用代表字符串的任何内存块。它依赖于您确保底层字符串数据在stringref对象的整个生命周期内都有效。这样,您可以以最小的开销传递并处理字符串信息。

答案 5 :(得分:0)

当你知道它是固定长度时:为什么不简单地再添加一个charakter到数组的大小?然后你可以用\ 0终止字符轻松地填充这个最后一个字符,一切都很好

答案 6 :(得分:0)

不,你必须复制它。语言中没有适当的转换可用于从中获取数组类型。

你想要做到这一点似乎很奇怪,或者你首先有一个没有终止的C风格的字符串。

为什么不使用std::string