0

I am trying to get ride of trailing newlines on a std::stringstream object after flushing some stuff into it. For now I would try something like this:

const char* inputvalue = "My line\n";
std::stringstream stream;

stream << std::string{inputvalue};
stream.seekp( -1, std::ios_base::end );

if( stream.peek() == '\n' ) {
    stream << " ";
} else {
    stream.seekp( 0, std::ios_base::end );
}

Is this the most efficient way to do so i.e., fewer CPU instructions and time?

As a side note, can I completely remove the last newline other than putting a space character to get rid of the new line without sacrificing performance?

Evandro Coan
  • 8,560
  • 11
  • 83
  • 144
  • How performance sensitive is this code? – tadman Jun 06 '19 at 22:41
  • I am reading a file by lines, and I am casting way the new line characters coming with the line itself. I am using [`PyUnicode_AsUTF8AndSize`](https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_AsUTF8AndSize) to get the line. The other problem is that [`PyUnicode_AsUTF8AndSize`](https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_AsUTF8AndSize) returns a `const char*`. You can find a minimal code here on [my other](https://stackoverflow.com/questions/56482802) question. See the line `while( ( readline = PyObject_CallObject( fileiterator, NULL ) ) != NULL ) {` – Evandro Coan Jun 06 '19 at 22:46
  • Could you manipulate the raw `char*` data instead? – tadman Jun 06 '19 at 22:49
  • Maybe I can convert the `const char* pointer` to `char * pointer` and set `pointer[size-1] = '\0';`? – Evandro Coan Jun 06 '19 at 22:51
  • The first problem seems to be the unnecessary `std::string{inputvalue};`. Having said that, `stringstream` is not particularly fast. The `iostream` methods are good for human-readable formatting, and humans just aren't fast. So speed was not really a design goal. – MSalters Jun 06 '19 at 22:54
  • I am building a big string and when I tried `stringstream << const char*` it raised an exception, then, I added the `std::string{const char*}`. Is there a better wat to build a big string other than using `stringstream`? – Evandro Coan Jun 06 '19 at 22:57
  • You could dupe the string, yeah, and then work with it. – tadman Jun 06 '19 at 23:08
  • std::string has some pretty useful functions for finding last characters which you could then erase. If you had a char array you could use a while loop and remove the characters yourself. Also, don't set the character to a space set it to nul. – Bayleef Jun 06 '19 at 23:34

1 Answers1

0

Before adding the thing on the stringstream I am taking the const char* and checking whether it has the new line \n on it. If so, I am casting it to char* and ending the string with \0 on size-1.

Py_ssize_t linesize;
std::stringstream stream;

char* nonconstcharline;
const char* constcharline;

for( PyObject* linepy : linecache ) {
    constcharline = PyUnicode_AsUTF8AndSize( linepy, &linesize );

    if( constcharline[linesize-1] == '\n' ) {
        nonconstcharline = const_cast<char *>( constcharline );
        nonconstcharline[linesize-1] = '\0';
        stream << std::string{nonconstcharline};
    }
    else {
        stream << std::string{constcharline};
    }
}

I read on this other question How to use const_cast? I should not do const char* to char* and change it as I do not seem to own the const char* thing, but so far no problems.

Evandro Coan
  • 8,560
  • 11
  • 83
  • 144