如何从具有嵌入空值的字符数组中提取std :: string

时间:2014-06-11 22:40:55

标签: c++

我有一个已知长度的字符数组,带有嵌入的空值;没有结束null。

const char * raw = "text1\0\0text2\0\0\0text3\0more text";

这样做

std::string clean(raw);

只给我第一个字符串("text1")但是,我想要整个原始字符串。

我想要多个字符串。在这种特殊情况下,raw.

内有4个字符串

6 个答案:

答案 0 :(得分:4)

如果您可以将raw的类型从const char *更改为const char[],那么您可以使用一对迭代器构造字符串

const char raw[] = "text1\0\0text2\0\0\0text3\0more text";
std::string clean(std::begin(raw), std::end(raw));

否则,您需要向std::string构造函数提供字符串文字的长度。

std::string clean(raw, length);

要回答有关如何从字符串文字中提取4个空字符分隔字符串的已编辑问题,这里有一个循环,可以完成这项工作

std::vector<std::string> tokens;
std::string::size_type pos, lastPos = 0;
while(pos < clean.length())
{
    // find next delimiter
    pos = clean.find_first_of('\0', lastPos);
    if(pos == std::string::npos) {
        // we've reached the end of the string, so get remaining
        pos = clean.length();
    }

    // if not empty add it to the vector
    if(pos != lastPos) tokens.push_back(clean.substr(lastPos, pos - lastPos));
    // increment to next character
    lastPos = pos + 1;
}

Live demo

答案 1 :(得分:4)

在不知道字符串文字的实际大小的情况下,您将无法完成任务。 如果你知道大小,那么你可以使用构造函数

basic_string(const charT* s, size_type n, const Allocator& a = Allocator());

或相应的方法assign

这里第二个参数指定将在字符串中复制的s的字符数。

如果知道长度,那么你可以简单地写

std::string clean( raw, n );

std::string clean;
clean.assign( raw, n );
编辑:当您更改原始邮件时,我会附上我的帖子。您可以通过以下方式拆分文字

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

int main()
{
    const char * s = "text1\0\0text2\0\0\0text3\0more text";
    size_t n = 30;
    std::istringstream is( std::string( s, 30 ) );

    std::vector<std::string> v;
    std::string word;
    while ( std::getline( is, word, '\0' ) ) if ( !word.empty() ) v.push_back( word );

    for ( const std::string &s : v ) std::cout << s << std::endl;
}

输出

text1
text2
text3
more text

如果你有四个不同的字符串,你可以写

#include <iostream>
#include <sstream>
#include <string>

int main()
{
    const char * s = "text1\0\0text2\0\0\0text3\0more text";
    size_t n = 30;
    std::istringstream is( std::string( s, 30 ) );

    std::string word1, word2, word3, word4;
    while ( std::getline( is, word1, '\0' ) && word1.empty() );
    while ( std::getline( is, word2, '\0' ) && word2.empty() );
    while ( std::getline( is, word3, '\0' ) && word3.empty() );
    while ( std::getline( is, word4, '\0' ) && word4.empty() );

    for ( const std::string &s : { word1, word2, word3, word4 } ) std::cout << s << std::endl;
}

答案 2 :(得分:2)

std::string有一个constructor,需要const char *和一个计数。您必须确定要复制的字符串中有多少个字符,因为您不能使用通常的空终止符约定。

答案 3 :(得分:1)

因为没有结尾null,你必须以其他方式知道大小。

根据已知尺寸,只需使用the string constructor that takes a pointer to first char, and a size

std::string可以包含空值。

答案 4 :(得分:1)

你可以去:

std::string(clean, clean + 30);

如果将字符串存储在数组(或#define)中会更好,然后您可以通过编程方式检查其长度,例如

char const raw[] = "text1\0\0text2\0\0\0text3\0more text";
std::string(raw, raw + sizeof raw - 1);

答案 5 :(得分:0)

这是预期的行为。 &#34; \ 0&#34;被理解为字符串的结尾。如果你试图使用&#34;%s&#34;来修改原始变量。格式你会得到相同的输出 - &#34; text1&#34;。如果你想要整个字符串,这就是你应该做的:

const char * raw = "text1\\0\\0text2\\0\\0\\0text3\\0more text";

因此,在将它传递给std :: string构造函数之前,您可以编写另一个附加额外&#39; \&#39;。

的例程。