-1

I have a character array of known length with embedded nulls; there is no ending null.

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

Doing this

std::string clean(raw);

Gives me just the first string ("text1") however, I want the entire raw string.

I want multiple strings. In this particular case there are 4 string inside raw.

yizzlez
  • 8,757
  • 4
  • 29
  • 44
user841550
  • 1,067
  • 3
  • 16
  • 25
  • Don't just tack on more and more corrections to the question - *rewrite* it so that it becomes a single, concise, clear question. – Kerrek SB Jun 11 '14 at 23:02
  • @Kerrek SB I thought std::string (s) in the title would be clear but I guess not. But I also said my attempt give me one string, I want them all. – user841550 Jun 11 '14 at 23:12

6 Answers6

4

If you can change the type of raw from const char * to const char[] then you can construct the string using a pair of iterators

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

Otherwise you'll need to provide the length of the string literal to the std::string constructor.

std::string clean(raw, length);

To answer the edited question about how to extract the 4 null character delimited strings from the string literal, here's a loop that'll do the job

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

Praetorian
  • 106,671
  • 19
  • 240
  • 328
4

Without knowing the actual size of the string literal you will not do the task. If you know the size then you can use constructor

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

or the corresponding method assign

Here the second parameter specifies the number of characters of s that will be copied in the string.

If the length is know then you can write simply

std::string clean( raw, n );

or

std::string clean;
clean.assign( raw, n );

EDIT: As you changed your original message then I will append my post. You can split the literal the following way

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

The output is

text1
text2
text3
more text

If you have four different strings you can write

#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;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

std::string has a constructor that takes a const char * and a count. You must determine how many characters are in the string you want to copy, since you can't use the usual convention of a null terminator.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
1

since there is no ending null you must know the size in some other way.

Given the known size, just use the string constructor that takes a pointer to first char, and a size.

A std::string can contain null values.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
1

You can go:

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

It would be better if you store the string in an array (or a #define), then you can check its length programmatically, e.g.

char const raw[] = "text1\0\0text2\0\0\0text3\0more text";
std::string(raw, raw + sizeof raw - 1);
M.M
  • 138,810
  • 21
  • 208
  • 365
0

This is the expected behavior. The "\0" is being understood as end of string. If you try to pritnf you raw variable with "%s" format you will get the same output - "text1". If you want the whole string this is what you should do:

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

So, before passing it to an std::string constructor you can write another routine which appends an extra '\'.

santahopar
  • 2,933
  • 2
  • 29
  • 50