Home > database >  Convert string to raw string
Convert string to raw string

Time:07-08

char str[] = "C:\Windows\system32"

auto raw_string = convert_to_raw(str);

std::cout << raw_string;

Desired output:

C:\Windows\system32

Is it possible? I am not a big fan of cluttering my path strings with extra backslash. Nor do I like an explicit R"()" notation.

Any other work-around of reading a backslash in a string literally?

CodePudding user response:

That's not possible, \ has special meaning inside a non-raw string literal, and raw string literals exist precisely to give you a chance to avoid having to escape stuff. Give up, what you need is R"(...)".

Indeed, when you write something like

char const * str{"a\nb"};

you can verify yourself that strlen(str) is 3, not 4, which means that once you compile that line, in the binary/object file there's only one single character, the newline character, corresponding to \n; there's no \ nor n anywere in it, so there's no way you can retrieve them.


As a personal taste, I find raw string literals great! You can even put real Enter in there. Often just for the price of 3 characters - R, (, and ) - in addtion to those you would write anyway. Well, you would have to write more characters to escape anything needs escaping.

Look at

std::string s{R"(Hello
world!
This
is
Me!)"};

That's 28 keystrokes from R to last " included, and you can see in a glimpse it's 6 lines.

The equivalent non-raw string

std::string s{"Hello\nworld!\nThis\nis\nMe!"};

is 30 keystrokes from R to last " included, and you have to parse it carefully to count the lines.

A pretty short string, and you already see the advantage.

CodePudding user response:

To answer the question, as asked, no it is not possible.

As an example of the impossibility, assume we have a path specified as "C:\a\b";

Now, str is actually represented in memory (in your program when running) using a statically allocated array of five characters with values {'C', ':', '\007', '\010', '\000'} where '\xyz' represents an OCTAL representation (so '\010' is a char equal to numerically to 8 in decimal).

The problem is that there is more than one way to produce that array of five characters using a string literal.

char str[] = "C:\a\b";
char str1[] = "C:\007\010";
char str2[] = "C:\a\010";
char str3[] = "C:\007\b";
char str4[] = "C:\x07\x08";    // \xmn uses hex coding

In the above, str1, str2, str3, and str4 are all initialised using equivalent arrays of five char.

That means convert_to_raw("C:\a\b") could quite legitimately assume it is passed ANY of the strings above AND

std::cout << convert_to_raw("C:\a\b") << '\n';

could quite legitimately produce output of

C:\007\010

(or any one of a number of other strings).

The practical problem with this, if you are working with windows paths, is that c:\a\b, C:\007\010, C:\a\010, C:\007\b, and C:\x07\x08 are all valid filenames under windows - that (unless they are hard links or junctions) name DIFFERENT files.

In the end, if you want to have string literals in your code representing filenames or paths, then use \\ or a raw string literal when you need a single backslash. Alternatively, write your paths as string literals in your code using all forward slashes (e.g. "C:/a/b") since windows API functions accept those too.

  • Related