【问题标题】:Copy a string to char array将字符串复制到 char 数组
【发布时间】:2012-03-02 12:14:56
【问题描述】:

我正在尝试将中间可能包含空字符的字符串复制到 char 数组。 我构造了以下函数。

 void SaveStringToChar(string &mystring,const char * &ArrChar)
 {//begin function

   std::string str;
   char * writable = new char[str.size() + 1];
   std::copy(str.begin(), str.end(), writable);
   writable[str.size()] = '\0';
   ArrChar = writable;

 }//end function

我的问题是这种方法保证我不会丢失空元素后的字符。 我的另一个问题是我收到了这个链接器错误,我不知道它是什么意思。

/tmp/ccUpCRaz.o:在函数“Parser::RuleParser(char const*)”中: Parser.cpp:(.text+0x3f6): 未定义对 Parser::SaveStringToChar(std::basic_string, std::allocator >&, char const*&)' 的引用 collect2: ld 返回 1 个退出状态

请告诉我。

这是我传递东西比较的函数。

  void Search( size_t TextLength, const char *Text, const vector<const char *> &patterns );

【问题讨论】:

  • 出于好奇,你为什么不用std::string::c_str()
  • 我碰巧使用了它们,但我的字符串中间可能包含 null ,我怀疑它们在我将它们推送到 const char * 类型的向量时丢失了,因为我在之后重新检查了向量中的数据我发现他们迷路了
  • 我不确定 c_str() 函数的结果是否保证包含第一个 \0 之后的所有字符。即使您使用一种编译器对其进行测试,它在另一种编译器上的行为方式也可能不同。
  • 我怀疑他们真的迷路了。但是,由于c_str() 返回一个以空字符结尾的字符串,因此在显示它时您确实无法判断是否真的到达了字符串的末尾。现在一个重要的问题是:如果您确定它们可以包含空字符,为什么还要处理以空字符结尾的字符串?坚持使用std::string 似乎风险要小得多。
  • @MrLister:我现在没有标准的副本可供使用,但我相当有信心保证c_str() 返回字符串的所有字符,在结果数组中是否为 null。有人可以确认/确认吗?

标签: c++ string char type-conversion


【解决方案1】:

您需要将函数定义为Parser:: 的成员。目前定义为:

void SaveStringToChar(string &mystring,const char * &ArrChar)

改为:

void Parser::SaveStringToChar(string &mystring,const char * &ArrChar)

std::copy() 将复制所有字符。然而,调用者将不知道ArrChar 实际指向多少个字符,因为像strlen() 这样的函数将在第一个空字符处停止计数。您可以更改SaveStringToChar() 的签名以接受另一个参数size_t&amp; ArrCharLen,该参数将填充ArrChar 中的字符数。当然,mystring 的长度是ArrChar,所以也许您在调用SaveStringToChar() 之前已经存储了它。

编辑(在vector&lt;const char*&gt; 评论之后):

一旦将const char* 添加到vector,就会丢失真实的字节数。为什么不使用vector&lt;std::string&gt;,您可以通过std::string::length() 知道std::string 中实际存储了多少个字符。

EDIT2(比较函数 .c_str() 与 text.length() 后:

不用传递.c_str().length()vector&lt;const char*&gt; 中的元素进行比较,只需将std::string 传递给比较函数并与vector&lt;std::string&gt; 的元素进行比较:std::string::operator==() 将正确比较字符串将嵌入空字符。然后您可以使用std::find()vector&lt;std::string&gt; 中搜索从文件中读取的std::string

【讨论】:

  • 你有意见吗,但这不仅仅是简单的比较,搜索功能实际上是一种基于这些参数的算法,所以我不能像那样改变我的参数(告诉你事实上,我试图将其更改为字符串,但它给了我一堆我无法修复的错误)。
  • 您使用什么来比较TextTextLengthvector 中的条目?您需要在某处存储vector 元素的长度:更改为vector&lt;std::string&gt; 似乎是最简单的方法。
  • 如果需要,您仍然可以使用std::string[] 访问每个单独的字符。
【解决方案2】:

您的字符串副本看起来不错,但如果您这样做是为了将 char* 传递给函数,则有更好的方法,请参阅:

std::string str;
//...
my_func(str.c_str());

hmjd 有你的链接错误。

【讨论】:

    【解决方案3】:

    我的问题是这种方法保证我不会丢失空元素后的字符

    整个字符串将被复制到缓冲区中,即使它确实包含空字符。 std::copy 不会以任何方式解释它复制的数据,它只是复制您告诉它的元素数量。

    但是,如果字符串确实包含空字符,那么您不能将它用于任何处理以空字符结尾的字符串的函数(例如&lt;cstring&gt; 中的函数);他们会将第一个空字符解释为字符串的结尾。

    另外,至少在您发布的代码中,您将指针返回为const char *,这意味着您不会修改副本。在这种情况下,您是否真的需要字符串数据的副本,或者返回 str.c_str() 就足够了?

    我的另一个问题是我收到此链接器错误

    您似乎缺少Parser::SaveStringToChar 的定义。我猜您发布的代码来自源文件,而不是在 Parser 类中内联定义的函数。如果是这种情况,那么您忘记指定它是一个成员函数,而是定义了一个非成员函数;改成

    void Parser::SaveStringToChar(string &mystring,const char * &ArrChar)
         ^^^^^^^^
    

    【讨论】:

      【解决方案4】:

      查看 hmjd 对链接错误的回答。

      对于复制的字符,您实际上不会丢失任何字符,因为它们都被安全地复制到了输出缓冲区。但是,如果字符串中间确实有 \0 字符,则 C 风格的字符串函数(如 printf)都不会在其上正常工作。
      而且调用例程也不知道字符串的长度是多少,因此缓冲区的新分配大小是多少。您也应该返回字符串长度(作为返回值,或在另一个引用参数中)。

      【讨论】:

      • 好的,但是作为一个数组,如果我像 A A null B C null null 那样遍历它,它们就会在那里
      • 因为我不使用它来打印输出我使用它来进行比较
      • 如果你知道确切的长度是多少,好的。否则,C 风格的比较函数也不会正常工作。顺便说一句,std::strings 之间可以进行比较;无需先将它们复制到字符数组中。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-02-05
      • 2016-03-03
      • 1970-01-01
      • 1970-01-01
      • 2014-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多