带有char的C ++格式char?

时间:2017-02-14 20:07:06

标签: c++ format

我很确定这已在某个地方得到解答,但我找不到答案(我可能是盲人)。但是,我有这段代码:

TCHAR name[UNLEN + 1];
DWORD size = UNLEN + 1;

char path[250]; = "X:\\users\\HEREname\\Documents\\Games\\";

注意:TCHAR只是char的typedef而DWORDunsigned int的typedef。

所以我很想知道格式化namepath的正确方法是什么,以便“HEREname”被name字符替换。我无法真正找到如何使用字符串和dunno为什么我找不到它....:/

谢谢!

2 个答案:

答案 0 :(得分:1)

TCHAR 可能char的typedef,或者可能wchar_t的typedef。这取决于您的项目是否配置为MBCS(char)或Unicode(wchar_t)。由于path[]明确charname应该使用char来匹配,而不是TCHAR。否则,如果TCHARwchar_t,则必须执行运行时转换。

对于您尝试的内容,您可以使用snprint()(或TCHAR等效,_sntprintf())或类似功能,例如:

char name[UNLEN + 1];
DWORD size = UNLEN + 1;

if (GetUserNameA(name, &size))
{
    char path[MAX_PATH] = {0};

    int len = snprintf(path, MAX_PATH, "X:\\users\\%s\\Documents\\Games\\", name);
    if ((len > 0) && (len < MAX_PATH))
    {
        ...
    }
}

或者:

TCHAR name[UNLEN + 1];
DWORD size = UNLEN + 1;

if (GetUserName(name, &size))
{
    TCHAR path[MAX_PATH] = {0};

    int len = _sntprintf(path, MAX_PATH, _T("X:\\users\\%s\\Documents\\Games\\"), name);
    if ((len > 0) && (len < MAX_PATH))
    {
        ...
    }
}

或者,如果你真的需要混合TCHARchar(我不推荐):

#ifdef UNICODE
#define PRINTF_TSTR_FMT "%ls"
#else
#define PRINTF_TSTR_FMT "%s"
#endif

TCHAR name[UNLEN + 1];
DWORD size = UNLEN + 1;

if (GetUserName(name, &size))
{
    char path[MAX_PATH] = {0};

    int len = snprintf(path, MAX_PATH, "X:\\users\\" PRINTF_TSTR_FMT "\\Documents\\Games\\", name);
    if ((len > 0) && (len < MAX_PATH))
    {
        ...
    }
}

话虽这么说,你真的不应该假设Windows存储用户配置文件的位置。不同机器上的位置可能不同,尤其是在不同版本的Windows上。使用Shell API来查询系统路径,例如:

TCHAR path[MAX_PATH] = {0};

if (SHGetFolderPath(NULL, CSIDL_MYDOCUMENTS, NULL, SHGFP_TYPE_CURRENT, path) == S_OK)
{
    if (PathAppend(path, TEXT("Games")))
    {
        // use path as needed...
    }
}

或者,在Vista及更高版本上:

PWSTR pDocsPath = NULL;

// or maybe even FOLDERID_Games...
if (SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &pPath) == S_OK)
{
    TCHAR path[MAX_PATH] = {0};

    bool bOK = (PathCombine(path, pDocsPath, TEXT("Games")) != NULL);
    CoTaskMemFree(pDocsPath);

    if (bOK)
    {
        // use path as needed...
    }
}

答案 1 :(得分:0)

有两种方法:

//Paths in C++ can all use '/', they don't need to have system-specific delimiters
std::string root = "X:/users/"
std::string user_name = /*...*/;
std::string path = "/Documents/Games/";

std::string final_path = root + user_name + path;
//TODO: Input sanitizing, to ensure no chance of rogue code

std::fstream file(final_path + file_name, /*...*/);

这可能是最简单的方法。

这种方法更具性能:

std::stringstream path;
path << "X:/Users/";
path << user_name;
path << "/Documents/Games/";
path << file_name;

std::string final_path = path.str();
std::fstream file(final_path, /*...*/);

如果你有一个符合C ++ 17的编译器,那么这是非常受欢迎的:

std::filesystem::path path = "X:/users";
path /= user_name;
path /= "Documents";
path /= "Games";

std::fstream file(path / file_name, /*...*/);