0

How can I convert a char field to a string if I have the '\ 0' character stored in some position. For example, if I have "ab \ 0bb", the a.lenght () command will show me that I have only two characters stored

string getString(char *str, int len)
{
    str[len] = '\0';
    string strBuffer = string(str);
    cout << strBuffer.length() << endl;
    return strBuffer;
}
Aaron7
  • 277
  • 2
  • 10
  • 1
    `std::string(str, len);` – Yksisarvinen Apr 27 '22 at 13:14
  • 1
    Isn't `str[len] = '\0';` **undefined behavior**? Because of going out of bounds. – Jason Apr 27 '22 at 13:16
  • @Anya No, it's a bit confusing here, but within the context of the program it's OK. – Aaron7 Apr 27 '22 at 13:16
  • 3
    If you buffer contains '\0' maybe `std::string` is not the best container. What abount `std::vector` ? – wohlstad Apr 27 '22 at 13:17
  • Uh, can't find a good duplicate. Related: [convert a char* to std::string](https://stackoverflow.com/questions/1195675/convert-a-char-to-stdstring) (in particular [this answer](https://stackoverflow.com/a/1195705/797680)) and [null character inside string](https://stackoverflow.com/questions/17906455/null-character-inside-string) – Yksisarvinen Apr 27 '22 at 13:19
  • Note that string isn't null-terminated. It stores length separately – Swift - Friday Pie Apr 27 '22 at 13:22
  • @wohlstad Not necessarily, `std::string` works well with `\0` inside. You just need to remember that C-style strings usually doesn't, so you need proper initialization. And don't do things like `printf("%s", str.c_str());`, but that wouldn't work with `std::vector` either. – Yksisarvinen Apr 27 '22 at 13:25
  • @Aaron7 Ok, can you tell why exactly? I mean, accessing one past the last element(with index `len`) is usually UB? – Jason Apr 27 '22 at 13:26
  • @Yksisarvinen I agree it's possible, just mentioned another option. The question does not give enough context to say which is more suitable. – wohlstad Apr 27 '22 at 13:29
  • @Aaron7 -- If your string contains embedded nulls, it isn't a good idea to do `str[len] = '\0';`. It makes no sense to artificially stick nulls inside a string that has embedded nulls already. – PaulMcKenzie Apr 27 '22 at 13:31
  • @Anya A C string with length `n` is backed by an array of at least `n+1` characters. For example the string literal `"Hello"` has a string length of 5, and type `const char [6]`. It is common for string manipulation functions inherited from C to work with string lengths and not array lengths like `strcmp` and `strcpy`. – François Andrieux Apr 27 '22 at 13:38
  • @FrançoisAndrieux Ok, i know that `"Hello"` is actually a `const char[6]` but i think your reasoning is wrong. The string literal `"Hello"` has a length of `6` and not `5`. This can be confirmed by using `std::size`. For example `std::cout< – Jason Apr 27 '22 at 13:46
  • @Anya The terminology "string length" for C strings means the length of the string, not the size of the storage. Storage size is associated with `sizeof` and string length with the standard function `std::strlen` (which stands for STRing LENgth). A single array can even contain multiple C strings, for example `"Hello\0World"` is an array of 12 characters, it contains two C strings of length 5 each. The length of the C string `"Hello"` is still 5 in that case, it is not 12. Edit : `std::size` doesn't care about the content of the data, while string length is defined by the data. – François Andrieux Apr 27 '22 at 13:53
  • 1
    @Yksisarvinen _std::string works well with \0 inside_ well, it _works_, but I would say it violates the principle of least surprise. – Paul Sanders Apr 27 '22 at 14:24

1 Answers1

5

As mentioned in the comments, std::string (which I will assume string and the question is referring to) has a constructor taking the length and allowing null characters:

string getString(char *str, int len)
{
    return {str, len};
}

or if you want to be explicit (to avoid confusion with an initializer list constructor)

string getString(char *str, int len)
{
    return string(str, len);
}

The str parameter should probably also have type const char*, not char*, and the type of len should probably be std::size_t. And probably string should be qualified as std::string as well instead of using using namespace std; or using std::string; (depends on context).

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • I didn't get why `str[len] = '\0';` is not UB. Usually, if we have an array of size say `4` then we're allowed to access only elements with index `0`, `1`, `2` and `3`. But here, OP has used `str[len]` instead of `str[len-1]`. – Jason Apr 27 '22 at 13:28
  • @Anya There is no `str[len] = '\0';` in the code I am showing and it doesn't require the range to be null-terminated either. If you are referring to the code in the question, it may be that OP calls this function only on pointers pointing to arrays that are larger than `len`. Of course that is not a generally safe assumption to make. – user17732522 Apr 27 '22 at 13:31
  • @Anya You don't know if `len` is actual length of the array or not. OP could have `char arr[10]{}; getString(arr, 5);` for example. As I understand their comment, they know the danger. – Yksisarvinen Apr 27 '22 at 13:31