Прекращение действия WCHAR - PullRequest
       5

Прекращение действия WCHAR

4 голосов
/ 27 ноября 2009

У меня есть это

WCHAR fileName [1];

как возвращаемое значение из функции (это функция sys 32, поэтому я не могу изменить возвращаемый тип). Мне нужно сделать так, чтобы fileName заканчивался нулем, поэтому я пытаюсь добавить к нему '\ 0', но, похоже, ничего не работает.

Как только я получу WCHAR с нулевым символом в конце, мне нужно будет передать его другой функции sys 32, чтобы он оставался WCHAR.

Может ли кто-нибудь дать мне какое-нибудь предложение, пожалуйста?

=============================================== =

Большое спасибо за вашу помощь. Похоже, моя проблема связана не только с отсутствием строки с нулевым символом в конце.

// Это работает:

WCHAR szPath1[50] = L"\\Invalid2.txt.txt";
    dwResult = FbwfCommitFile(szDrive, pPath1); //Successful

// Это не:

std::wstring l_fn(L"\\");  
    //Because Cache_detail->fileName is \Invalid2.txt.txt and I need two
l_fn.append(Cache_detail->fileName);
l_fn += L""; //To ensure null terminated
fprintf(output, "l_fn.c_str: %ls\n", l_fn.c_str()); //Prints "\\Invalid2.txt.txt"

    iCommitErr = FbwfCommitFile(L"C:", (WCHAR*)l_fn.c_str()); //Unsuccessful

// Тогда, когда я сделаю сравнение по этим двум, они неравны.

int iCompareResult = l_fn.compare(pPath1);  // returns -1

Так что мне нужно выяснить, как эти два оказались разными.

Большое спасибо!

Ответы [ 4 ]

4 голосов
/ 27 ноября 2009

Поскольку вы упомянули fbwffindfirst / fbwffindnext в комментарии, вы говорите об имени файла, возвращенного в FbwfCacheDetail . Таким образом, из поля fileNameLength вы знаете длину fileName в байтах. Длина fileName в WCHAR - это fileNameLength / sizeof (WCHAR). Таким образом, простой ответ заключается в том, что вы можете установить

fileName[fileNameLength/sizeof(WCHAR)+1] = L'\0'

Теперь это важно вам нужно убедиться, что буфер, который вы отправляете для параметра cacheDetail в fbwffindfirst / fbwffindnext, имеет размер в байтах (WCHAR) больше, чем вам нужно, приведенный выше фрагмент кода может работать за пределами границы вашего массива. Поэтому для параметра размера fbwffindfirst / fbwffindnext передайте размер буфера sizeof (WCHAR).

Например, это:

// *** Caution: This example has no error checking, nor has it been compiled ***
ULONG error;
ULONG size;
FbwfCacheDetail *cacheDetail;

// Make an intial call to find how big of a buffer we need
size = 0;
error = FbwfFindFirst(volume, NULL, &size);
if (error == ERROR_MORE_DATA) {
    // Allocate more than we need
    cacheDetail = (FbwfCacheDetail*)malloc(size + sizeof(WCHAR));
    // Don't tell this call about the bytes we allocated for the null
    error = FbwfFindFirstFile(volume, cacheDetail, &size);
    cacheDetail->fileName[cacheDetail->fileNameLength/sizeof(WCHAR)+1] = L"\0";

    // ... Use fileName as a null terminated string ...

    // Have to free what we allocate
    free(cacheDetail);
}

Конечно, вам придется изменить немного, чтобы соответствовать вашему коду (плюс вам также придется вызывать fbwffindnext)

Если вас интересует, почему структура FbwfCacheDetail оканчивается полем WCHAR [1], см. Это сообщение в блоге . Это довольно распространенный шаблон в Windows API.

2 голосов
/ 27 ноября 2009

Используйте L '\ 0', а не '\ 0'.

0 голосов
/ 27 ноября 2009

WCHAR fileName[1]; - это массив из 1 символа, поэтому, если нулевое значение завершено, оно будет содержать только нулевой терминатор L'\0'.

Какую функцию API вы вызываете?

Отредактировано

Элемент fileName в FbwfCacheDetail - это всего 1 символ, который является распространенным методом, используемым, когда длина массива неизвестна, а элемент является последним элементом в структуре. Как вы, вероятно, уже заметили, если ваш выделенный буфер имеет длину sizeof (FbwfCacheDetail), то FbwfFindFirst возвращает ERROR_NOT_ENOUGH_MEMORY.

Так что, если я понимаю, что вы хотите сделать, выведите имя файла, не оканчивающееся NULL, используя fprintf. Это можно сделать следующим образом

fprintf (outputfile, L"%.*ls", cacheDetail.fileNameLength, cacheDetail.fileName);

При этом будут напечатаны только первые fileNameLength символов fileName.

Альтернативным подходом было бы добавить терминатор NULL в конец fileName. Сначала вам нужно убедиться, что буфер достаточно длинный, что можно сделать, вычтя sizeof (WCHAR) из аргумента size, который вы передаете в FbwfFindFirst. Поэтому, если вы выделите буфер в 1000 байтов, вы передадите 998 в FbwfFindFirst, зарезервировав последние два байта в буфере для вашего собственного использования. Затем, чтобы добавить терминатор NULL и вывести имя файла, используйте

cacheDetail.fileName[cacheDetail.fileNameLength] = L'\0';
fprintf (outputfile, L"%ls", cacheDetail.fileName);
0 голосов
/ 27 ноября 2009

Поскольку каждый символ WCHAR имеет 16-битный размер, возможно, вам следует добавить к нему \0\0, но я не уверен, что это работает. Кстати, WCHAR fileName[1]; создает WCHAR длины 1, возможно, вам нужно что-то вроде WCHAR fileName[1024];.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...