2017-02-08 15 views
0

Я пытаюсь перечислить логические диски моего ПК и добавить результат к вектору, но я получаю этот странный result = ;;;.Преобразование char в std :: string не работает

Что мне здесь не хватает?

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; 
} 
+0

Вы пытались выполнить свой код с помощью отладчика? –

+0

Конечно, это то, что я всегда делаю, получая это ";;;" в каждой записи. –

+6

'% c' + lpBuffer [0] - что это должно делать? – Slava

ответ

1
DWORD mydrives = 100; 
char lpBuffer[100]; 

100 не достаточно символов. Технически, компьютер может иметь до 26 букв дисков (реально, никто не имеет столько букв дисков за один раз, но вы все равно должны готовиться к нему). Для 100-символьного буфера достаточно места для получения 24 буквенных букв не более (4 * 24 + 1 = 97, 4 * 25 + 1 = 101). Вам нужно место для не менее 105 символов в вашем буфере для получения 26 буквенных строк (4 * 26 + 1 = 105).

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

Эта линия не делает то, что вы думаете. Вместо этого вы думаете о функции C-style 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() вместо этого, то вы не» t нужно беспокоиться о том, чтобы распределять память или прокручивать любые строки букв на диске:

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); 
     } 
    } 
} 
+0

Спасибо за это удивительное объяснение, знайте, что случилось. –

7

Как указано в documentationGetLogicalDriveStrings() дает вам список 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; 
} 
+0

Это будет работать только в том случае, если вы настроили свой проект на использование кодировки MBCS. Нет уважительной причины не использовать Unicode, о котором я знаю. Вы должны вызвать 'GetLogicalDriveStringsW', заменить' char' на 'wchar_t' и' std :: string' на 'std :: wstring'. – IInspectable

+0

@Intpectable Я ответил на конкретный вопрос OP, вы должны предположить, что замена OP, а не я. – Slava