/ / Безопасно ли е да се използва `strstr` за търсене на многобайтови символи utf-8 в низ? - c, string, utf-8, многобайтови функции

Безопасно ли е да използвате `strstr`, за да търсите многобройни utf-8 знака в низ? - c, низ, utf-8, многобайтови функции

Следвайки предишния ми въпрос: Защо `strchr` изглежда да работи с многобайтови символи, въпреки, че man page disclaimer?, Разбрах това strchr беше лош избор.

Вместо това мисля да използвам strstr за да търсим един символ (многобайтово не char):

const char str[] = "This string contains é which is a multi-byte character";
char * pos = strstr(str, "é"); // "é" = 0xC3A9: 2 bytes
printf("%sn", pos);

Изходен:

Е, която е многобайтова

Това е, което очаквам: позицията на първия байт от моя многобайтов характер.

A priori, това не е каноничното използване на strstr но изглежда, че работи добре.
Безопасно ли е това решение? Можете ли да помислите за някакви странични ефекти или специални случаи, които биха довели до грешка?

[РЕДАКТИРАНЕ]: Трябва да уточня, че не искам да използвам wchar_t тип и че низовете, които обработвам, са utf-8 кодирани (знам това избор може да се обсъжда, но това е без значение дебат)

Отговори:

4 за отговор № 1

Не strstr не е подходящ за низове, съдържащи многобайтови знаци.

Ако търсите низ, който не съдържа многобайтови символи в низ, който съдържа многобайтови символи, той може да даде фалшиво положително. кодиране shift-jis в японски локал, strstr ("нещо", "@some") може да даде фалшиво положително)

+---------+----+----+----+
|   c1    | c2 | c3 | c4 |  <--- string
+---------+----+----+----+

+----+----+----+
| c5 | c2 | c3 |  <--- string to search
+----+----+----+

Ако част от c1 (случайно) съвпада с c5, може да получите неправилен резултат. Бих предложил да използвате Unicode с Unicode функция за проверка на подлиния или многобайтови функции за проверка на подлинии. (_mbsstr например)

редактиране
Въз основа на актуализиран въпрос от ОП, че "може такъв."фалшиво положителни съществуват в контекст utf-8 " Така че отговорът е utf-8 е проектиран по такъв начин, че е имунизиран срещу частично несъответствие на характера, както е показано по-горе и причинява фалшиво положително. Така че е напълно безопасно да се използва strstr с utf-8 кодирани многобайтови символи.


1 за отговор № 2

Модерните системи използват utf-8 (или ASCII) като многобайтово кодиране, където използването на тази функция е безопасно.

За да сте строго съобразени и да накарате кода да работи дори на стари / екзотични платформи, трябва да вземете под внимание допълнителни проблеми.

Първо, добрата новина: Във всяко многобайтово кодиране 0-байт показва края на низ, независимо от състоянието. Това означава, вашето strstr няма да предизвика катастрофа или нещо подобно, но резултатът може да е грешен.

Като пример, помислете за UTF-7, 7-битов чист начин за кодиране на Unicode. UTF-7 е многобайтово кодиране, имащо a състояние на смяна, което означава как един байт се интерпретира може да зависи от контекста, в който се появява. Например (Вж Wikipedia) “£ 1AKM” е кодиран като +AKM-AKM в UTF-7, където + Знакът променя състоянието и тълкуването на буквите като A, правене strstr(str, "AKM") ще съответства на първата част на АКМ (след. \ t +), въпреки че това е част от кодирането на £ и всъщност трябва да съответства на AKM част след - (настройка на състоянието на превключване обратно в първоначалното състояние).


-2 за отговор № 3

Безопасно ли е това решение? Можете ли да помислите за някакви странични ефекти или специални случаи, които биха довели до грешка?

Един страничен ефект е, че ако strtr() не открива съвпадение, тогава ще отпечатате нулева стойност на показалеца, която ще предизвика Segmentation fault.

Трябва да проверите дали показалецът има стойност NULL, преди да отпечатате низа. Проверете го така:

if(pos == NULL)
printf("letter not found");
else
printf("%sn", pos);