-2
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?

A M
  • 14,694
  • 5
  • 19
  • 44
user3600124
  • 829
  • 1
  • 7
  • 19
  • 6
    You might not like the syntax, but it's the syntax we've got. Welcome to C++. – chris Jul 07 '22 at 06:04
  • 1
    If you're insane enough you can have PHP generate the code for you by using php as a preprocessor to c ` in the middle of a C file with .php extension... then dump the ouput and compile it as `.c` file. – Dmytro Jul 07 '22 at 06:07
  • 1
    How about forward slashes? They should work too. – HolyBlackCat Jul 07 '22 at 06:08
  • @HolyBlackCat yes, I was thinking about it. The problem is when working with registry, forward slashes are valid key-name characters. They rarely (if ever) appear in a key-name though – user3600124 Jul 07 '22 at 06:10
  • User defined string literal? That way you get to choose your own suffix, and you can do something like convert `/` into a backslash. – john Jul 07 '22 at 06:11
  • @john Not gonna work, they will automatically interpret escape sequences. – HolyBlackCat Jul 07 '22 at 06:12
  • 1
    @HolyBlackCat But you could put some code behind them to convert forward to backward slashes – john Jul 07 '22 at 06:13
  • 4
    Out of curiosity ...... While I realise that neither `char raw_string[] = "C:\\Windows\\system32";` nor `char raw_string[] = R"(C:\Windows\system32)";` is your ideal, why do you consider that `char str[] = "C:\Windows\system32"; auto raw_string = convert_to_raw(str);` (if it was even possible, which it isn't) would be preferable? – Peter Jul 07 '22 at 06:39
  • @Peter Consider function call `get_location("C:\Windows\system32")`. In this case `convert_to_raw()` (or any equivalent operation) is performed inside a function and hidden away from the caller. Looks neat, much simpler – user3600124 Jul 07 '22 at 06:46
  • @user3600124 Yeah, well. As long as you want to type string literals into source code, what you want aint possible. The escaping (additional `\\`) or raw strings are THE ways to avoid that - and the standard doesn't provide a third way (to turn a string containing special characters back) because it is ambiguous in general. – Peter Jul 07 '22 at 07:22

2 Answers2

4

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.

Enlico
  • 23,259
  • 6
  • 48
  • 102
1

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.

Peter
  • 35,646
  • 4
  • 32
  • 74