2015-06-26 10 views
0

У меня есть функция api. Я беру указатель на массив char. Вызывающая функция находится вне моего контроля. Массив является динамическим, но все еще нужны некоторые проверкиПроверьте длину char [] перед преобразованием в wstring()

extern "C" int __stdcall calcW2(LPWSTR foo) 

Если кто-то сделать звонок с

char foo[5000]; 
    LPSTR lpfoo2 = foo; 
    calcW2(lpfoo2); 

Я понимаю, что мне нужно сделать некоторые проверки. Я могу проверить для nulltpr. Но если я хочу проверить. То, что массив символов имеет некоторую ценность. Как это лучше всего сделать? Самый безопасный способ для строки от 0 до 2500 символов. Нужно проверить что-то еще?

if(foo != nullptr) 
{ 
    //Size checking 
    //size_t newsize = strlen(SerialNumber) + 1 not good? 
    std::wstring test(foo); 
} 
+0

Зачем вам нужно проверять длину? – juanchopanza

ответ

0

Вы пропустили один важный момент. Подпись функции говорит LPWSTR не LPSTR. Это означает, что функция ожидает (или должна ожидать) получить wchar_t[] не char[]. См. https://msdn.microsoft.com/en-us/library/cc230355.aspx.

Я имею в виду:

extern "C" int __stdcall calcW2(LPWSTR foo) <--- LP-W-STR 

char foo[5000]; 
LPSTR lpfoo2 = foo;      <--- LP-STR 
calcW2(lpfoo2);       <--- LP-STR passed into LP-W-STR ?? 

, которые не должны компилировать. Типы аргументов неверны.

Если вы изменили массив на wchar_t [], и он начинает сбой компиляции, то, скорее всего, у вас есть некоторая установка #UNICODE #defines. В WINAPI и т. Д. Многие функции имеют двойственные определения. Когда установлен флаг «UNICODE», они берут LPWSTR, но когда флаг очищается, заголовки переключают их на LPSTR. Поэтому, если вы видите, что это должен быть LPWSTR, и вы хотите, чтобы он был LPWSTR, и он настаивает на том, чтобы быть LPSTR, тогда вы либо испортили имена функций, либо флаг UNICODE (или заголовок, который у вас есть, просто неверен).

char и wchar_t отличаются. Упрощение, char - «singlebyte», а wchar_t - «twobyte». Оба используют '\ 0' в качестве маркера конца строки, но в wchar_t это на самом деле '\ 0 \ 0', так как это два байта на символ. Кроме того, в wchar_t [] простые данные ASCII не похожи на a|b|c|d|e|f, это 0|a|0|b|0|c|0|d|0|e|0|f, так как это два байта на символ. Поэтому strlen не может корректно работать с 16-битными закодированными данными - он выбирает первый \ 0 из первого символа как конец строки. Наличие данных wchar_t, насильственно упакованных в char [], явно неверно или, по крайней мере, очень ошибочно и подвержено ошибкам.

Вот почему вы должны использовать вместо этого wchar_t* вместо char*.

Это общее правило. Для любой функции, работающей на char (strlen, strcat, strcmp, ..), вы должны найти соответствующую функцию w * (wstrlen, wstrcat, wstrcmp, ..). Иногда могут быть некоторые символы подчеркивания. Поиск документов. Не смешивайте типы символов. Теперь это просто байтовый массив. Для них есть семантика, и обычно, если некоторые типы называются по-разному, есть причина для этого.

+0

Thats ju type. Измените подпись на extern «C» int __stdcall calcW2 (LPSTR foo). Это не имеет ничего общего с широким или ansi только тем, что лучше всего выполняет Std :: functions для проверки действительности. –

+0

@JohanBertilsdotter: Итак, LPWSTR - это опечатка? ОК. Просто отредактируйте свой пост и исправьте это. Но я прочитал то, что вы написали, и перечитал второй раз, и я не понимаю, что вам нужно. Если проблем с широким/символом нет, тогда почему вы используете char [5000], когда ваша строка будет до 2500chars при макс? О какой «действительности» вы говорите все время? Нет никакого способа, чтобы данные в массиве могли быть «недопустимыми». Могут быть данные, более или менее или вообще отсутствующие данные. Но данные будут действительны.Нет такой вещи, как «недопустимый символ». Итак, проясните: что вы подразумеваете под «действительностью»? – quetzalcoatl

+0

И если это действительно просто 'char []' not wchar, то почему бы вам не использовать классический 'strlen', о котором вы уже упоминали? Если char-data '\ 0'-terminated, то хороший ol 'strlen будет работать нормально. Если данные прекращены чем-то другим или если вы не хотите, чтобы strlen по какой-то причине, то вам, вероятно, понадобится использовать 'find' /' distance' (std :: ish-way) или ручной цикл (yuck!) найти терминатор данных в массиве. – quetzalcoatl

Смежные вопросы