将char转换为std :: string不起作用

时间:2017-02-08 17:02:43

标签: c++ winapi

我试图列出我的Pc的逻辑驱动器并将结果添加到矢量但我得到了这个奇怪的result = ;;;

我在这里缺少什么?

std::vector<std::string> directory::getLogicalDrives() {
    DWORD mydrives = 100;
    char lpBuffer[100];
    DWORD drives = GetLogicalDriveStrings(mydrives, lpBuffer);

    std::vector<std::string> driveList;
    for (int i = 0; i < 100; i++) {
        std::string drive(3, '%c' + lpBuffer[0]); // Missing something?
        driveList.push_back(drive);
    }
    return driveList;
}

2 个答案:

答案 0 :(得分:7)

documentation GetLogicalDriveStrings()中所述,为您提供以NULL结尾的字符串列表,列表以NULL字符终止。所以只需迭代该列表,例如:

std::vector<std::string> directory::getLogicalDrives() {
    std::vector<std::string> driveList;
    char szBuffer[105];
    DWORD size = GetLogicalDriveStrings(104, szBuffer);
    if ((size > 0) && (size <= 104)) {
        const char *pstr = szBuffer;
        while( *pstr ) {
            std::string drive( pstr );
            driveList.push_back(drive);
            pstr += (drive.length() + 1);
        }
    }
    return driveList;
}

答案 1 :(得分:1)

DWORD mydrives = 100;
char lpBuffer[100];

100个字符不够。从技术上讲,一台计算机最多可以有26个驱动器号(实际上,没有人同时拥有那么多驱动器号,但你仍然应该为此做准备)。 100个字符的缓冲区有足够的空间来容纳最多24个驱动器盘符串(4 * 24 + 1 = 974 * 25 + 1 = 101)。缓冲区中至少需要105个字符的空格才能接收26个驱动器盘符串(4 * 26 + 1 = 105)。

std::string drive(3, '%c' + lpBuffer[0]); // Missing something?

此行不符合您的想法。您正在考虑使用C风格的sprint()函数。您不能像std::string一样使用格式化字符串。这行甚至不应该编译,或者应该编译并带有警告。

此外,您甚至无法正确循环输出字符串。 GetLogicalDriveStrings()<drive>:\<nul>格式返回以双重终止的字符串列表,其中<drive>在列表末尾为<nul>。例如,如果返回驱动器A,B和C,则缓冲区的内容将如下所示:

lpBuffer[ 0] = 'A';
lpBuffer[ 1] = ':';
lpBuffer[ 2] = '\\';
lpBuffer[ 3] = '\0';
lpBuffer[ 4] = 'B';
lpBuffer[ 5] = ':';
lpBuffer[ 6] = '\\';
lpBuffer[ 7] = '\0';
lpBuffer[ 8] = 'C';
lpBuffer[ 9] = ':';
lpBuffer[10] = '\\';
lpBuffer[11] = '\0';
lpBuffer[12] = '\0';

正确的方法是以4个字符为一组循环缓冲区,直到你到达最终的空终止符(并且不要忘记错误检查!),例如:

DWORD drives = GetLogicalDriveStrings(mydrives, lpBuffer);
if ((drives > 0) && (drives <= mydrives)) {
    char *pdrive = lpBuffer;
    while (*pdrive) {
        std::string drive(pdrive);
        driveList.push_back(drive);
        pdrive += 4;
    }
}

可替换地:

DWORD drives = GetLogicalDriveStrings(mydrives, lpBuffer);
if ((drives > 0) && (drives <= mydrives)) {
    for (int i = 0; i < drives; i += 4) {
        std::string drive(&lpBuffer[i]);
        driveList.push_back(drive);
    }
}

话虽如此,请考虑使用GetLogicalDrives()代替,然后您根本不必担心为任何驱动器号字符串分配内存或循环:

DWORD drives = GetLogicalDrives();
if (drives) {
    char drive[] = "?:\\";
    for (int i = 0; i < 26; i++) {
        if (drives & (1 << i)) {
            drive[0] = 'A' + i;
            driveList.push_back(drive);
        }
    }
}