C++用字符格式化字符

C++ format char with char?

本文关键字:字符 格式化 C++      更新时间:2023-10-16

我很确定这已经在某处得到了回答,但我真的找不到答案(我可能是盲人(。但是,我有以下代码:

TCHAR name[UNLEN + 1];
DWORD size = UNLEN + 1;
char path[250]; = "X:\users\HEREname\Documents\Games\";

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

所以我想知道格式化path中的name的正确方法是什么,以便将"HEREname"替换为name字符。我也无法真正找到如何使用字符串执行此操作,也不知道为什么我找不到它...... :/

谢谢!

TCHAR可能是char的typedef,也可能是wchar_t的typedef。 这取决于您的项目是针对 MBCS (char ( 还是 Unicode (wchar_t ( 进行配置的。 由于path[]是显式charname应该使用char来匹配,而不是TCHAR。 否则,如果wchar_t TCHAR,则必须执行运行时转换。

对于您正在尝试的内容,您可以使用像 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 上。 改用命令行管理程序 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...
    }
}

几种方法:

//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, /*...*/);