Why does my colon character disappear when I go from char [] to string?

In an old Windows application, I am working on the fact that I need to get the path from the environment variable and then add to it to create the path to the file. Therefore, the code looks something like this:

static std::string PathRoot; // Private variable stored in class' header file char EnvVarValue[1024]; if (! GetEnvironmentVariable(L"ENV_ROOT", (LPWSTR) EnvVarValue, 1024)) { cout << "Could not retrieve the ROOT env variable" << endl; return; } else { PathRoot = EnvVarValue; } // Added just for testing purposes - Returning -1 int foundAt = PathRoot.find_first_of(':'); std::string FullFilePath = PathRoot; FullFilePath.append("\\data\\Config.xml"); 

The environment value for ENV_ROOT is set to "c: \ RootDir" in the Windows System Control Panel. But when I run the program, I end the line in FullFilePath, which skips the colon colon and everything that follows in the root folder. It looks like this: " c \ data \ Config.xml ".

Using the Visual Studio debugger, I looked at EnvVarValue after passing the GetEnvironmentVariable string and showed me an array that seems to have all the characters I would expect, including a colon. But after it gets assigned to PathRoot, mousing over PathRoot shows only C, and drilling down says bad ptr. As I noticed, calling find_first_of () does not find the colon colon. And when the application is added, it only saves the initial C and leaves the rest of the RootDir value.

So there seems to be something about the nature of the colon that confuses the string constructor. Yes, there are several ways I could get around this by leaving the colon in the env variable and adding it later in the code. But I would prefer to find a way to read and use it correctly from the environment variable as it is.

+6
source share
3 answers

You cannot just pass char* to wchar_t* (by clicking on LPWSTR ) and expect everything to work. These two are fundamentally different types, and in Windows they mean different encodings.

Obviously, the WinAPI defines many such that GetEnvironmentVariable allowed by GetEnvironmentVariableW , which uses UTF-16 to encode the string. In practice, this means that byte 0 follows each ASCII character in memory.

Then you create std::string from it, so it takes the first 0 bytes (in char index 1) as a line terminator, so you only get "c" .

You have several options:

  • Use std::wstring and wchar_t EnvVarValue[1024];

  • Call GetEnvironmentVariableA() (which uses char and ASCII)

  • Use wchar_t EnvVarValue[1024]; and convert the return value to std::string using something like wcstombs .

+4
source

It seems you are building with widescreen features (as indicated by your cast on LPWSTR ). This means that the string in EnvVarValue is a wide character string, and you should use wchar_t and std::wstring instead.

I would suggest that the contents of the array after calling GetEnvironmentVariable actually ASCII values 0x43 0x00 0x3a 0x00 0x5c 0x00 , etc. (that is, the widescreen representation of char "C:\" ). The first zero acts as a line terminator for a narrow-character string, so the narrow-character PathRoot string contains only 'C' .

+3
source

The problem may be that EnvVarValue is not a wchar. Try using wchar_t and std :: wstrรฎng.

0
source

All Articles