Я хочу иметь возможность открыть файл в моем приложении Win32.
Метод, который я использую, — это получение корневого пути из поля редактирования, например, «C: \ MyFolder» (это назначено strPathToSource
). Затем я хочу добавить еще одну строку, например «\ source \ Utilities \ File.h» и сохраните объединенный путь в новой переменной strPathToFile
,
Так strPathToFile
должен содержать «C: \ MyFolder \ source \ Utilities \ File.h», который затем можно открыть с помощью infile.open(strPathToFile)
,
Соответствующий код показан ниже:
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;
}
куда PATH_TO_FILE
определяется как:
const char* PATH_TO_FILE = "\\source\\Utilities\\File.h";
Моя проблема заключается в том, что он всегда выходит из системы «File.h not found». Я считаю, что проблема заключается в конкатенации, например,
const char* strPathToFile = char(strPathToSource) + PATH_TO_FILE;
Проходя через, я вижу значения strPathToSource
а также PATH_TO_FILE
как и должно быть, но объединенный результат в strPathToFile
Я считаю, что это значение NULL.
Добавление двухсимвольных указателей не объединяет строки, а просто добавляет два значения указателя (как «числа»). Таким образом, вы получите неверный указатель.
Кроме того, преобразование типов из LPTSTR в char * не является хорошей идеей, поскольку TCHAR также может быть широким символом, в зависимости от текущих настроек сборки.
(на самом деле вы приводите LPTSTR к символу, а не к указателю, что еще более неправильно)
Я думаю, что проще всего было бы преобразовать обе строки в std :: string (или wstring), там вы можете использовать оператор ‘+’ для конкатенации.
Одна возможность сделать это:
const std::wstring strPathToFile = cvt2wstring(strPathToSource) + cvt2wstring(PATH_TO_FILE);
cvt2wstring определяется как:
#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;
}
В зависимости от фактического типа, он должен выбрать соответствующую перегрузку.
Для обратного преобразования в std :: string (чтобы вы могли использовать обычный std :: ifstream) вы можете переключить направление:
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);
}
Для меня ifstream :: open (), кажется, работает с wstring (но это может быть расширение MSVC, поскольку стандарт C ++ этого не обеспечивает — в любом случае, если вы используете TCHAR & сост. Вы, вероятно, нацелены на Windows и MSVC).
Мартин Боннер в основном дал правильный ответ.
Короче говоря, лучшее решение — игнорировать TCHAR
вчистую. Это костыль, созданный в последнее десятилетие прошлого века, когда Unicode был проблемой для ПК с 4 МБ ОЗУ. Сегодня распространено 4 ГБ, в тысячу раз больше.
Однако, если вы все еще хотите жить в эту эпоху, будьте последовательны. Не определять
const char* PATH_TO_FILE = "\\source\\Utilities\\File.h";
но использовать
const TCHAR * PATH_TO_FILE = _T("\\source\\Utilities\\File.h");
Также научитесь использовать конкатенацию строк. Ты можешь использовать std::basic_string<TCHAR>::operator+
(легко) или tcscat
(привыкнуть к переполнению буфера).