Search code examples
c++filewinapieditboxlptstr

Concatenating LPTSTR with const char* (Win32 C++)


I wish to be able to open a file in my Win32 application. The method I am using is retrieving the root path from an edit box e.g. "C:\MyFolder" (this is assigned to strPathToSource). Then I want to append another string e.g. "\source\Utilities\File.h" and store the concatenated path in a new variable strPathToFile.

So strPathToFile should contain "C:\MyFolder\source\Utilities\File.h", which can then be opened using infile.open(strPathToFile).

The relevant code is shown below:

ifstream infile;

int bufSize = 1024;
LPTSTR strPathToSource = new TCHAR[bufSize];
GetDlgItemText(hWnd, IDC_MAIN_EDIT_FILEPATH, strPathToSource, bufSize); // Get text from edit box and assign to strPathToSource

const char* strPathToFile = char(strPathToSource) + PATH_TO_FILE;
infile.open(strPathToFile);
if(!infile)
{
    log(hWnd, "File.h not found.");
    return false;
}

Where PATH_TO_FILE is defined as:

const char* PATH_TO_FILE = "\\source\\Utilities\\File.h";

My issue is that it is always logging out "File.h not found". I believe the issue lies with the concatenation e.g.

const char* strPathToFile = char(strPathToSource) + PATH_TO_FILE;

Stepping through I can see the values of strPathToSource and PATH_TO_FILE are as they should be, but the concatenated result in strPathToFile is a NULL value I believe.


Solution

  • Adding two character pointers does not concatenate the strings, it just adds the two pointer values (as "numbers"). So you end up with an invalid pointer.

    Also, typecasting from LPTSTR to char* is not a good idea, as TCHAR can be wide character as well, depending on the current build settings. (in the fact, you are casting a LPTSTR to char, not to pointer, which is even more wrong)

    I think the easiest would be to convert both strings to std::string (or wstring), there you can use the '+' operator to do the concatenation.

    One possibility to do that:

    const std::wstring strPathToFile = cvt2wstring(strPathToSource) + cvt2wstring(PATH_TO_FILE);
    

    cvt2wstring defined as:

    #include <codecvt>
    #include <string>
    
    std::wstring cvt2wstring(const char * str)
    {
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
        return converter.from_bytes(str);
    }
    
    std::wstring cvt2wstring(const wchar_t * str)
    {
        return str;
    }
    

    Depending on the actual type, it should choose the appropriate overload.

    For the opposite conversion to std::string (so that you can use the regular std::ifstream) you can switch the direction:

    std::string cvt2string(const char * str)
    {
        return str;
    }
    
    std::string cvt2string(const wchar_t * str)
    {
        std::wstring_convert<std::codecvt_utf8_utf16<wchar_t> > converter;
        return converter.to_bytes(str);
    }
    

    For me, the ifstream::open() seems to work with wstring (but it might be MSVC extension as the C++ standard does not provide that - anyway if you use TCHAR & comp. you probably target Windows and MSVC).