set_locale str_word_count и чёртова буква я

Тема в разделе "Вопросы по программированию на РНР", создана пользователем GrayHound, 25 сен 2007.

  1. GrayHound

    GrayHound Новичок

    Сообщения:
    85
    set_locale str_word_count и чёртова буква я

    Ткните носом чтоли.
    Поставил setlocale(LC_ALL, 'ru_RU.cp1251');
    str_word_count слова находит отлично, но почти... буква "я" у него почему в наш алфавит похоже не входит, и работает как разделитель по сути... что делать?
  2. kruglov

    kruglov Новичок

    Сообщения:
    2.718
    Адрес:
    Moscow, Russia
    Потому что у нее код 255 = EOF
  3. nalim

    nalim Новичок

    Сообщения:
    131
    Адрес:
    Москва
    UTF-8 юзай
  4. GrayHound

    GrayHound Новичок

    Сообщения:
    85
    тяжко переводить всё на utf =/
  5. SiMM

    SiMM Новичок

    Сообщения:
    6.375
    Адрес:
    Чебоксары, Россия
    Самому аналог функции написать - задача 5 минут.
  6. phprus

    phprus Moderator Команда форума

    Сообщения:
    1.865
    Адрес:
    Perm, Russia
    kruglov
    Если мне не изменяет память, то функция isalpha стандартной библиотеки языка С нормально обработает букву с кодом 255, так как она принимает параметр типа int

    255 != EOF
    EOF в С определен как
    #define EOF (-1)
    тоесть по умолчанию он имеет тип int.

    Дальнейшие мои рассуждения основаны на версии php 5.2.3, так как исходников других версий у меня нет.
    В коде файла ext/standard/string.c есть такая строчка:
    Код:
    while (p < e && (isalpha(*p) || (char_list && ch[(unsigned char)*p]) || *p == '\'' || *p == '-')) {
    
    Как мы видим в ней функции isalpha передается разыменованый указатель p, который имеет тип char*. Вот тут то и начинаются преобразования. 255 - это 8 единиц в битовом представлении. Для типа char это равносильно числу -1 Вот тут происходит преобразование типа с char в int и в функцию isalpha передается -1, а не 255(как мы ждали).

    Для исправления этой ситуации достаточно принудительно преобразовать *p к типу unsigned char, тоесть если написать вызов isalpha таким образом:
    Код:
    isalpha([b](unsigned char)[/b]*p)
    
    То буква "я" должна будет обрабатываться нормально.

    P.S. Все вышесказанное писал по памяти, так как скомпилировать и проверить у меня сейчас возможности нет.
  7. GrayHound

    GrayHound Новичок

    Сообщения:
    85
    phprus
    инфо весьма полезное... но когда сайт лежит у хостера - я думаю он перекомпилировать не будет
  8. Андрейка

    Андрейка Senior pomidor developer

    Сообщения:
    990
    Адрес:
    Семипалатинский полигон
    мы конечно сипласпласов не изучали, но у нас есть некоторые сомнения, что интерпритация 8 единичек зависит от того signed или unsigned char передают в одну и ту же функцию
  9. phprus

    phprus Moderator Команда форума

    Сообщения:
    1.865
    Адрес:
    Perm, Russia
    Андрейка
    Интерпретация важна при преобразовании типа. (char -> int). в данном случае, так как оба типа знаковые и int больше char'а. Так как оба типа знаковые, то е единичек char будут преобразованы в 32 единички int, так как и там и там так представлено число -1
  10. kruglov

    kruglov Новичок

    Сообщения:
    2.718
    Адрес:
    Moscow, Russia
    phprus
    Так, подождите, а EOF чему равен в char? И чему равен код "я" в char? Чтобы они преобразовывались в разные intы?
  11. phprus

    phprus Moderator Команда форума

    Сообщения:
    1.865
    Адрес:
    Perm, Russia
    kruglov
    Я просмотрел всю функцию str_word_count и в ней нигде нет сравнения символа с EOF. Библиотечная функция isalpha принимает параметр типа int и по этому внутри нее EOF сравнивается с int'ом, а в инте -1 и 255 - это разные числа. Именно по этому единственное место где тут возможна проблема - это преобразование char в int (при передаче параметра в функцию isalpha). Именно в этом месте мы получаем -1 вместо 255.
  12. baev

    baev ‹°°¬• Команда форума

    Сообщения:
    3.421
    GrayHound, ОС какая?

    И покажите небольшой пример кода.
  13. Farsh

    Farsh ~ on ~ high ~ wave ~

    Сообщения:
    356
    Адрес:
    Moscow
    Блин , народ , кто нибудь смог нормально использовать str_word_count с русским языком ?
    Что только не перепробовал , белеберду выдает .
    Или есть ли у кого нибудь нормальная , несырая функция для подсчета слов в тексте ?
  14. tony2001

    tony2001 TeaM PHPClub

    Сообщения:
    9.261
    Адрес:
    msk.ru/kh.ua
    Farsh
    локаль установи правильную.

    phprus
    протестировать своё предположение насчет unsigned char можешь?
    у меня нет локали cp1251.
  15. phprus

    phprus Moderator Команда форума

    Сообщения:
    1.865
    Адрес:
    Perm, Russia
    Тестовый код:
    PHP:
    <?php
    var_dump
    (setlocale(LC_ALL'ru_RU.cp-1251''ru_RU.CP1251'));
    var_dump(str_word_count('русский текст. я тестер. аябаг. яап. авя'2));
    ?>
    1) До изменения исходников результат:
    Код:
    string(12) "ru_RU.CP1251"
    array(7) {
      [0]=>
      string(7) "русский"
      [8]=>
      string(5) "текст"
      [17]=>
      string(6) "тестер"
      [25]=>
      string(1) "а"
      [27]=>
      string(3) "баг"
      [33]=>
      string(2) "ап"
      [37]=>
      string(2) "ав"
    }
    Вывод: Баг есть.

    2) После изменения исходников результат:
    Код:
    string(12) "ru_RU.CP1251"
    array(7) {
      [0]=>
      string(7) "русский"
      [8]=>
      string(5) "текст"
      [15]=>
      string(1) "я"
      [17]=>
      string(6) "тестер"
      [25]=>
      string(5) "аябаг"
      [32]=>
      string(3) "яап"
      [37]=>
      string(3) "авя"
    }
    Вывод: вроде бы бага нет.

    Что я изменял написано в моем первом сообщении в этой теме.

    P.S. У меня тоже небыло локали cp1251. Пришлось поставить для тестов.
  16. tony2001

    tony2001 TeaM PHPClub

    Сообщения:
    9.261
    Адрес:
    msk.ru/kh.ua
    ок
    заведи плз баг-репорт, я закоммичу.
  17. Farsh

    Farsh ~ on ~ high ~ wave ~

    Сообщения:
    356
    Адрес:
    Moscow
    Оказывается у меня просто локаль не ставится ...
  18. phprus

    phprus Moderator Команда форума

    Сообщения:
    1.865
    Адрес:
    Perm, Russia
    tony2001
    Вот баг: http://bugs.php.net/bug.php?id=43863

    Русские буквы благополучно побились благодаря тому что эта система оборудована "защитой" от спама(честных пользователей) в виде вывода сообщений о том что вам неплохо было бы и поискать по нашей базе перед тем как баг постить. Все бы было ничего если бы при выводе этого сообщения не портились все не английские буквы в полях описания.
  19. tony2001

    tony2001 TeaM PHPClub

    Сообщения:
    9.261
    Адрес:
    msk.ru/kh.ua
    ок, закоммитил.
    спасибо, что дал знать.