WinAPI和c ++ I / O中的字符串

时间:2014-05-25 12:12:44

标签: c++ winapi

我正在用c ++教我自己的WinAPI,但随着我的进步,我注意到WinAPI中的每个函数都返回char *,DWORD,LPCSTR等。我担心的是我喜欢使用字符串,所以我在做什么呢我得到了将其转换为字符串的返回值。是好还是坏?或者如果我每次都转换它会有什么不同吗?或者它会使过程变慢或任何不好的东西。对于c ++中的I / O,考虑到exe的大小或性能/功能问题,什么是更好的cout或printf?

2 个答案:

答案 0 :(得分:2)

首先学习各种字符串类型。例如,char*LPSTRLPCSTR都是相关的并存储ANSI字符;最后一个是指向const字符串的指针。同样,wchar_t*WCHAR*LPWSTRLPCWSTR都是相关的并存储Unicode字符;最后一个是指向const字符串的指针。

当你说“返回char *”之类的内容时,请注意你的意思,因为大多数Windows API都没有这样做。相反,它们采用LPSTR(指向char缓冲区的指针)或LPWSTR(指向WCHAR缓冲区的指针),并写入缓冲区。这些API几乎总是要么计算缓冲区中可用的字符数,要么具有记录的缓冲区大小要求,例如MAX_PATH

您可以利用此优势。 C ++ 11要求std::wstringstd::string连续存储其字符,并且所有已知的实现在此之前都做得很好。因此,给定像GetEnvironmentVariable这样的API,您可以直接使用字符串作为缓冲区并避开大多数转换。使用与此类似的代码,但随时可以修改它与代码其余部分的交互方式:

std::wstring GetEnvironmentVariable(const std::wstring& strName)
{
    DWORD cchValue = MAX_PATH;
    std::wstring strValue;

    // call API once or twice, to get required buffer size
    strValue.resize(cchValue);
    cchValue = GetEnvironmentVariable(strName.c_str(), &strValue[0], cchValue);
    if (cchValue > MAX_PATH)
    {
        strValue.resize(cchValue);
        cchValue = GetEnvironmentVariable(strName.c_str(), &strValue[0], cchValue);
    }

    // process errors such as ERROR_ENVVAR_NOT_FOUND
    if (0 == cchValue)
    {
        // throw exception? return empty string? (current code does latter)
    }

    // remove null character and any extra buffer
    strValue.resize(cchValue);
    return strValue;
}

您可以对此方法进行大量进一步的改进。

  • 如果您需要支持旧的Windows 9x时代操作系统,可以使用LPTSTR来创建一个typedef tstring,根据定义创建映射到std::wstringstd::string的{​​{1}} UNICODE的{​​{1}}(否则我建议只做我上面所示的宽字符串)。您可以执行在C ++中重载的显式A和W函数调用,或遵循Windows命名约定。
  • 您可以将双重调用重构为某个帮助程序,或至少分解其所需的一些步骤。
  • 您可以处理为缓冲区大小输入in-out参数的API。
  • 您可以找到一种处理API的方法,例如GetWindowText仅返回成功/失败但不返回所需缓冲区大小的API,并隐藏在新包装函数后面的舞蹈。有关示例方法,请参阅相关的questionanswer。 (另请注意,对于该特定情况,其他方法可能更好。)

就I / O而言,没有一个明显的赢家。你会发现在Windows中使用控制台和控制台I / O是相当罕见的,所以也许这个问题毕竟不是很有趣。除此之外,在国际化方面存在重大权衡;即翻译完整的句子格式字符串比翻译因使用iostream而产生的片段要容易得多。但如果翻译不是你的问题,那不会影响你的决定。

答案 1 :(得分:1)

您提出的几乎所有内容都是基于意见的。是的,将你得到的每个字符*转换为std :: string会比较慢,但不会产生太大影响。当然,这完全取决于你经常这样做,以及你将在哪里运行这个程序。在这种情况下将事物转换为std :: string绝对没有问题,但是要注意,你不会有一个有趣的时间来对抗任何API(转换为所有类型的转换将会更加繁琐时间。)最后,这完全取决于你。请记住,仅仅因为您将使用new或malloc分配的char *转换为std :: string并不意味着您不必释放或删除它。

我没有看到printf或std :: cout的问题。再一次,这完全是基于意见的。但是,std :: cout可能更容易使用,并且当然更加类型安全。