Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

avoiding the first newline in a C++11 raw string literal?

Tags:

c++

c++11

The raw string literals in C++11 are very nice, except that the obvious way to format them leads to a redundant newline \n as the first character.

Consider this example:

    some_code();     std::string text = R"( This is the first line. This is the second line. This is the third line. )";     more_code(); 

The obvious workaround seems so ugly:

    some_code();     std::string text = R"(This is the first line. This is the second line. This is the third line. )";     more_code(); 

Has anyone found an elegant solution to this?

like image 865
Hugues Avatar asked Jul 22 '14 05:07

Hugues


People also ask

What is a raw string literal?

Raw String Literal in C++ A Literal is a constant variable whose value does not change during the lifetime of the program. Whereas, a raw string literal is a string in which the escape characters like ' \n, \t, or \” ' of C++ are not processed. Hence, a raw string literal that starts with R”( and ends in )”.

What is a character literal in C++?

A character literal is a type of literal in programming for the representation of a single character's value within the source code of a computer program. In C++, A character literal is composed of a constant character. It is represented by the character surrounded by single quotation marks.

How does compiler process string literals?

The compiler scans the source code file, looks for, and stores all occurrences of string literals. It can use a mechanism such as a lookup table to do this. It then runs through the list and assigns the same address to all identical string literals.


2 Answers

You can get a pointer to the 2nd character - skipping the leading newline - by adding 1 to the const char* to which the string literal is automatically converted:

    some_code();     std::string text = 1 + R"( This is the first line. This is the second line. This is the third line. )";     more_code(); 

IMHO, the above is flawed in breaking with the indentation of the surrounding code. Some languages provide a built-in or library function that does something like:

  • removes an empty leading line, and
  • looks at the indentation of the second line and removes the same amount of indentation from all further lines

That allows usage like:

some_code(); std::string text = unindent(R"(     This is the first line.     This is the second line.     This is the third line.     )"); more_code(); 

Writing such a function is relatively simple...

std::string unindent(const char* p) {     std::string result;     if (*p == '\n') ++p;     const char* p_leading = p;     while (std::isspace(*p) && *p != '\n')         ++p;     size_t leading_len = p - p_leading;     while (*p)     {         result += *p;         if (*p++ == '\n')         {             for (size_t i = 0; i < leading_len; ++i)                 if (p[i] != p_leading[i])                     goto dont_skip_leading;             p += leading_len;         }       dont_skip_leading: ;     }     return result; } 

(The slightly weird p_leading[i] approach is intended to make life for people who use tabs and spaces no harder than they make it for themselves ;-P, as long as the lines start with the same sequence.)

like image 77
Tony Delroy Avatar answered Sep 22 '22 12:09

Tony Delroy


This is probably not what you want, but just in case, you should be aware of automatic string literal concatenation:

    std::string text = "This is the first line.\n" "This is the second line.\n" "This is the third line.\n"; 
like image 36
Brian Bi Avatar answered Sep 23 '22 12:09

Brian Bi