wcscpy_s не влияет на wchar_t*

#c #struct #wchar-t

#c #структура #wchar-t

Вопрос:

Я пытаюсь загрузить некоторые строки из базы данных в структуру, но я продолжаю сталкиваться со странной проблемой. Использование моей структуры данных,

 struct datum {
    wchar_t*    name;
    wchar_t*    lore;
};
 

Я попробовал следующий фрагмент кода

 datum thisDatum;
size_t len = 0;
wchar_t wBuffer[2048];

mbstowcs_s(amp;len, wBuffer, (const char*)sqlite3_column_text(pStmt, 1), 2048);
if (len) {
    thisDatum.name = new wchar_t[len   1];
    wcscpy_s(thisDatum.name, len   1, wBuffer);
} else thisDatum.name = 0;

mbstowcs_s(amp;len, wBuffer, (const char*)sqlite3_column_text(pStmt, 2), 2048);
if (len) {
    thisDatum.lore = new wchar_t[len   1];
    wcscpy_s(thisDatum.lore, len   1, wBuffer);
} else thisDatum.name = 0;
 

Однако при thisDatum.name правильном копировании thisDatum.lore всегда остается мусор, за исключением двух случаев. Если проект отлаживается, все в порядке, но это просто не вариант. Я также обнаружил, что переписывание данных структуры

 struct datum {
    wchar_t*    lore;
    wchar_t*    name;
};
 

полностью устраняет проблему для thisDatum.lore , но дает мне мусор для thisDatum.name .

Комментарии:

1. Не то чтобы это имело значение, но в последнем else случае обнуляется неправильная переменная.

2. Упс, спасибо. Это могло быть плохо.

3. Почему бы просто не использовать std::wstring вместо wchar_t* ?

4. Разве вы не должны использовать len вместо len 1 того, чтобы при вызове wcscpy_s ?

5. Кроме того, mbstowcs_s задает размер выходных данных, сохраненный в len , чтобы отразить включение терминатора. Нет необходимости в арифметике 1.

Ответ №1:

Попробуйте что-то более похожее на это:

 struct datum {
    wchar_t*    name;
    wchar_t*    lore;
};
 
 wchar_t* widen(const char *str)
{
    wchar_t *wBuffer = NULL;
    size_t len = strlen(str)   1;
    size_t wlen = 0;
    mbstowcs_s(amp;wlen, NULL, 0, str, len);
    if (wlen)
    {
        wBuffer = new wchar_t[wlen];
        mbstowcs_s(NULL, wBuffer, wlen, str, len);
    }
    return wBuffer;
}
 
 datum thisDatum;
thisDatum.name = widen((const char*)sqlite3_column_text(pStmt, 1));
thisDatum.lore = widen((const char*)sqlite3_column_text(pStmt, 2));
...
delete[] thisDatum.name;
delete[] thisDatum.lore;
 

При этом я бы использовал std::wstring вместо:

 struct datum {
    std::wstring    name;
    std::wstring    lore;
};
 
 #include <locale>
#include <codecvt>

std::wstring widen(const char *str)
{
    std::wstring_convert< std::codecvt<wchar_t, char, std::mbstate_t> > conv;
    return conv.from_bytes(str);
}
 
 datum thisDatum;
thisDatum.name = widen((const char*)sqlite3_column_text(pStmt, 1));
thisDatum.lore = widen((const char*)sqlite3_column_text(pStmt, 2));
 

Комментарии:

1. 1 за то, что фактически предоставил C решение проблемы C