-5

Okay, after two days of searching the web and MSDN, I didn't found any real solution to this problem, so I'm gonna ask here in hope I've overlooked something.

I have open dialog window, and after I get location from selected file, it gives the string in following way C:\file.exe. For next part of mine program I need C:\\file.exe. Is there any Microsoft function that can solve this problem, or some workaround?

ofn.lpstrFile = fileName;
char fileNameStr[sizeof(fileName)+1] = "";
    if (GetOpenFileName(&ofn))
        strcpy(fileNameStr, fileName);
    DeleteFile(fileName); // doesn't works, invalid path 

I've posted only this part of code, because everything else works fine and isn't relevant to this problem. Any assistence is greatly appreciated, as I'm going mad in last two days.

user3576682
  • 13
  • 1
  • 2
  • 3
    I usually avoid using \\ and instead use / on windows as the path separator. – drescherjm Oct 29 '14 at 22:06
  • Use the method described in [this](http://stackoverflow.com/questions/2896600/how-to-replace-all-occurrences-of-a-character-in-string) question – Lander Oct 29 '14 at 22:17
  • 3
    You are drastically on the wrong track with this. Always pay attention to the return value of winapi functions and call GetLastError() when the function failed. With the expectation that you'll get error 5 if you try to delete a file in the c:\ directory. – Hans Passant Oct 29 '14 at 22:20
  • 3
    Why would you want the file name to be `C:\\file.exe`? That is not a valid Win32 path. – Carey Gregory Oct 29 '14 at 22:48
  • @HansPassant If I manually enter paramater as "C:\\file.exe", it deletes it, without any error 5, if I leave it like above, it returns error 123, PATH_NOT_FOUND. – user3576682 Oct 29 '14 at 23:16
  • @CareyGregory How much I've seen, DeleteFile() only works with that path, in every other way I gets error 123. – user3576682 Oct 29 '14 at 23:18
  • ***If I manually enter paramater as "C:\\file.exe"*** Are you talking about entering that as a literal string in your c++ code or are you using cin / scanf ...? – drescherjm Oct 29 '14 at 23:32
  • @drescherjm As a literal string ofc. – user3576682 Oct 29 '14 at 23:40
  • 3
    ***Literal strings*** and ***only*** literal strings need the backslash doubled up. The actual string only has a single backslash (which is all it needs). If you write a literal string as "C:\file.txt" the actual string doesn't contain either a backslash or an f, they are converted to a control character, 0x0F. – Harry Johnston Oct 30 '14 at 00:13
  • 2
    What @HarryJohnston said. You're mixing up the C++ requirement to escape backslashes in literals with the actual file name Windows sees. You should not attempt to change single backslashes in file names to double backslashes. Doing so will make almost all file names invalid. – Carey Gregory Oct 30 '14 at 00:25
  • 4
    `char fileNameStr[sizeof(fileName)+1] = "";` Is this your contribution to a How-many-errors-can-you-fit-in-a-single-line-contest? – IInspectable Oct 30 '14 at 09:08

3 Answers3

6

You are confusing the requirement in C and C++ to escape backslash characters in string literals with what Windows requires.

Windows allows double backslashes in paths in only two circumstances:

  • Paths that begin with "\\?\"
  • Paths that refer to share names such as "\\myserver\foo"

Therefore, "C:\\file.exe" is never a valid path.

The problem here is that Microsoft made the (disastrous) decision decades ago to use backslashes as path separators rather than forward slashes like UNIX uses. That decision has been haunting Windows programmers since the early 1980s because C and C++ use the backslash as an escape character in string literals (and only in literals).

So in C or C++ if you type something like DeleteFile("c:\file.exe") what DeleteFile will see is "c:ile.exe" with an unprintable 0xf inserted between the colon and "ile.exe". That's because the compiler sees the backslash and interprets it to mean the next character isn't what it appears to be. In this case, the next character is an f, which is a valid hex digit. Therefore, the compiler converts "\f" into the character 0xf, which isn't valid in a file name.

So how do you create the path "c:\file.exe" in a C/C++ program? You have two choices:

  • "c:/file.exe"
  • "c:\\file.exe"

The first choice works because in the Win32 API (and only the API, not the command line), forward slashes in paths are accepted as path separators. The second choice works because the first backslash tells the compiler to treat the next character specially. If the next character is a hex digit, that's what you will get. If the next character is another backslash, it will be interpreted as exactly that and your string will be correct.

Carey Gregory
  • 6,836
  • 2
  • 26
  • 47
  • 4
    I recommend avoiding the forward-slash, because while it works in most Win32 API functions it is not supported by the kernel. This means, for example, that you can't use it with long file paths. – Harry Johnston Oct 30 '14 at 02:35
0

The library Boost.Filesystem "provides portable facilities to query and manipulate paths, files, and directories".

In short, you should not use strings as file or path names. Use boost::filesystem::path instead. You can still init it from a string or char* and you can convert it back to std::string, but all manipulations and decorations will be done correctly by the class.

Michael Simbirsky
  • 3,045
  • 1
  • 12
  • 24
-4

Im guessing you mean convert "C:\file.exe" to "C:\\file.exe"

  std::string output_string;
  for (auto character : input_string)
  {
    if (character == '\\')
    {
      output_string.push_back(character);
    }
    output_string.push_back(character);
  }

Please note it is actually looking for a single backslash to replace, the double backslash used in the code is to escape the first one.

robby987
  • 827
  • 1
  • 9
  • 25