9

In C/C++, strings are NULL terminated.

Could I use stringstream as a memory stream like MemoryStream in C#?

Data of memory streams may have \0 values in the middle of data, but C++ strings are NULL terminated.

Amir Saniyan
  • 13,014
  • 20
  • 92
  • 137
  • you can treat the set of continues character as a memory stream,but other wise is not possible. – Amir Naghizadeh Nov 24 '12 at 15:13
  • 4
    C++ strings are not null-terminated (and can contain null bytes). C doesn't have strings, so what they ise null-terminated arrays instead – jalf Nov 24 '12 at 15:34
  • 2
    There is no such thing as C/C++. A string in C and a string in C++ are two completely different things. Strings in C++ are not null-terminated. – netcoder Nov 24 '12 at 15:35
  • 1
    You have a misconception: C++ std::string is not '\0' terminated and can have internal '\0' characters: See: http://stackoverflow.com/a/164274/14065 Thus it is perfectly valid to use std::string with '\0' anywhere in them. All the methods work as expected. – Martin York Nov 24 '12 at 17:32

3 Answers3

8

When storing character sequences in a std::string you can have included null characters. Correspondingly, a std::stringstream can deal with embedded null characters as well. However, the various formatted operations on streams won't pass through the null characters. Also, when using a built-in string to assign values to a std::string the null characters will matter, i.e., you'd need to use the various overloads taking the size of the character sequence as argument.

What exactly are you trying to achieve? There may be an easier approach than traveling in string streams. For example, if you want to read the stream interface to interact with a memory buffer, a custom stream buffer is really easy to write and setup:

struct membuf
    : std::streambuf 
{
        membuf(char* base, std::size_t size) {
        this->setp(base, base + size);
        this->setg(base, base, base + size);
    }
    std::size_t written() const { return this->pptr() - this->pbase(); }
    std::size_t read() const    { return this->gptr() - this->eback(); }
};

int main() {
    // obtain a buffer starting at base with size size
    membuf       sbuf(base, size);
    std::ostream out(&sbuf);
    out.write("1\08\09\0", 6); // write three digits and three null chars
}
participant
  • 2,923
  • 2
  • 23
  • 40
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
  • What is `base/size` in `membuf sbuf(base, size);`? Is this `char base[size];`? What if somebody writes more than `size` to `out`? – PiotrNycz Nov 24 '12 at 17:07
  • Yes, `base` is the base address of the memory you want to write to or read from. `size` is the number of available `char`s. When attempting to read or write past the end the stream will indicate a failure in the normal way. – Dietmar Kühl Nov 24 '12 at 17:47
  • 1) Is your `membuf` copyable? 2) What is this "normal way" of indicating a failure: I have to check `out.fail()/out.good()` or there is some way to trigger an exception (if yes, then what exception)? I am asking because `membuf` seems to be solution to some my own task (+1)... – PiotrNycz Nov 24 '12 at 18:57
  • Stream buffers are generally not copyable and this one isn't copyable either. If you need a copyable versin of this stream buffer I'd think it would be possible to create the relevant members but multiple instances would uncontrolled write to the same memory area. The error indication of the formatted oprations is setting `std::ios_base::failbit` etc. I don't recall off-hand if the unformatted operations also set the flags or just return suitable results. If you want to use exceptions you can set a corresponding exception mask. – Dietmar Kühl Nov 24 '12 at 19:04
  • Not copyable, not usable for me. At least, I learnt something, thanks. – PiotrNycz Nov 24 '12 at 19:08
  • Another idea: What if I'd added `char base[size];` to your `membuf` as member - and made the `membuf` constructed from own data, not from external one. Is there a way to force this modified `membuf` to be copyable? – PiotrNycz Nov 24 '12 at 19:11
  • The issue with copying isn't so much with the `membuf` part but rather with the base class: It doesn't expose a copy constructor (or copy assignment) because it generally doesn't make sense to copy a stream. You can, however, define a copy constructor and copy assignment for your special stram and arrange to setup the base members suitably using `setg()` and `setp()`. The main issue is whether you want the copy and the original to write to or read from a common destination (i.e., share a position). Maybe you can ask about what you actually want to do and I'll see what I can propose...? – Dietmar Kühl Nov 24 '12 at 19:15
  • http://stackoverflow.com/questions/13544762/i-need-copyable-buffer-as-light-as-possible-e-g-not-zero-initialized – PiotrNycz Nov 24 '12 at 19:29
5

In C/C++, strings are NULL terminated.

  • Two completely different languages (that have some commonality in syntax). But C is about as close to C++ as Jave is to C# (in that they are different).

Each language has their own string features.

  • C uses a sequence of bytes that by convention is terminated by a '\0' byte.
    • Commonly referred to as a C-String.
    • There is nothing special about this area of memory it is just a sequence of bytes.
    • There is no enforcement of convention and no standard way to build.
    • It is a huge area of bugs in C programs.
  • C++ uses a class (with methods) std::string.

Could I use stringstream as a memory stream like MemoryStream in C#?

Sure. The Memory stream is a stream that is backed by memory (rather than a file). This is exactly what std::stringstream is. There are some differences in the interface but these are minor and use of the documentation should easily resolve any confusion.

Data of memory streams may have \0 values in the middle of data, but C++ strings are NULL terminated.

This is totally incorrect.

  • C-String are '\0' terminated.
  • C++ std::string are not null terminated and can contain any character
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • I disagree with your comparison between C/C++ and Java/C++. C++ is a super-set of C. Most things that will compile with C will compile with C++ (aside from a few type-safety things), just not vice-versa. To be extra explicit, neither C nor C++ have strings at all. Their standard libraries have ways of operating on chars to give that functionality. C++ can use both the C and C++ standard libraries. Java cannot. – Jamie Jun 21 '16 at 23:01
  • @Jamie: That was all true 20 years ago. Not so anymore. Writing C and compiling it with a C++ compiler **may** work (may not). But that does not make it C++ code (its just C compiled with a C++ compiler). The style used by the two languages has diverged so completely that they are no longer look anything like each other. Yes there are crappy C programmers that have converted to using a C++ compiler but they are not writting C++ they are writting C. – Martin York Jun 21 '16 at 23:15
  • `std::string` is as much a part of the language of C++ as `Java.util.String` is a part of the Java language. If you are using C-Strings in C++ you are not writing C++ you are writting C and just happen to compile with a C++ compiler. "C with classes" is not C++ it is a bastardized form of C and the worst of both worlds. – Martin York Jun 21 '16 at 23:18
1

C and C++ are two different languages, in C sequence of continues character means string, and you can treat it as a memory part which can set/get its values, using memcpy(),memset(),memcmp().

In C++ strings means a class of information which used to get correct data as string. So you can't treat it as a sequence of memory location with char type.

Flexo
  • 87,323
  • 22
  • 191
  • 272
Amir Naghizadeh
  • 383
  • 3
  • 14