Модераторы: Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [C] Разбиение слов на слоги 
:(
    Опции темы
feanaro
Дата 21.12.2006, 16:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 21.12.2006

Репутация: нет
Всего: нет



Собственно, необходимо создать сабжевую программу.
Подскажите, пожалуйста, алгоритм. Заранее спасибо.
PM MAIL   Вверх
Kuvaldis
Дата 21.12.2006, 19:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


Профиль
Группа: Участник Клуба
Сообщений: 1189
Регистрация: 16.6.2006
Где: Минск

Репутация: 32
Всего: 61



feanaro, 
когда-то делал программу по переносу слов, там как раз используется разбиение на слоги.
Вот собственно, алгоритм. Если нужен сам текст, говори, но он достаточно сложный

Как показывает многочисленные эксперименты, разбиение русских слов для переноса с большей вероятностью выполняется правильно, если пользоваться следующими простыми приёмами:
1)    две идущие подряд гласные можно разделить, если первой предше-ствует согласная, а за второй идёт хотя бы одна буква (буква “й” рассматривается вместе с предшествующей гласной как единое це-лое);
2)    две идущие подряд согласные можно разделить, если первой из них предшествует гласная, а в той части слова, которая идёт за второй согласной, идёт хотя бы одна гласная (“ь” и  “ъ” вместе с предшест-вующей согласной рассматриваются как единое целое):
3)    если не удаётся применить первые два правила, то следует попы-таться разбить слово так, чтобы первая часть содержала хотя бы две буквы и оканчивалась на согласную, а вторая содержала одну глас-ную.
Вероятность разбиения увеличивается, если предварительно восполь-зоваться хотя бы неполным списком приставок и попытаться выделить из слова эту приставку.




--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
feanaro
Дата 21.12.2006, 19:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 24
Регистрация: 21.12.2006

Репутация: нет
Всего: нет



Kuvaldis, спасибо, но я не совсем представляю как это реализовать. буду очень признателен за сам код, или хотя бы кусочек. =)
PM MAIL   Вверх
Kuvaldis
Дата 21.12.2006, 19:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


механик-вредитель
***


Профиль
Группа: Участник Клуба
Сообщений: 1189
Регистрация: 16.6.2006
Где: Минск

Репутация: 32
Всего: 61



Код

//---------------------------------------------------------------------------
//                               PERENOS.CPP
//---------------------------------------------------------------------------
#include <string.h>
#include "macro.h"
//---------------------------------------------------------------------------
  /* EDITOR GLOBALS  */
  
extern  int     left;           // left border (1..78)
extern  int     right;          // right border (2..79)
//---------------------------------------------------------------------------
  /* LINE GLOBALS    */

extern  int     prev;           // previous str real size (= length previous str)
extern  int     is_red;         // indicator: if red-line str
extern  int     last;           // previus word end
extern  int     word_cnt;       // words count in str
extern  int     len;            // real str length
extern  int     found;          // indicator: if in word    
//---------------------------------------------------------------------------

char ANSI_to_ASCII(char sym)  // ANSI(Windows) -> ASCII(DOS)
{

    if((sym >= 'А') && (sym <= 'п'))
      sym -= 64;
    else if((sym >= 'р') && (sym <= 'я'))
      sym -= 16;

   return sym;
}

//---------------------------------------------------------------------------

char ASCII_to_ANSI(unsigned char sym)  // ASCII(DOS) ->  ANSI(Windows)
{

    if((sym >= 128) && (sym <= 175))
      sym += 64;
    else if((sym >= 224) && (sym <= 239))
      sym += 16;

   return sym;
}

//---------------------------------------------------------------------------

void get_ASCII_line(char* str)    // ANSI-str  -> ASCII-str
{
   while(*str)
   {
     *str = ANSI_to_ASCII(*str);
     str++;
   }
   return;
}

//---------------------------------------------------------------------------

int glasn(int sym)    // return 1 - if glasn, else return 0
{
   if((sym == 'а') ||(sym == 'А') ||(sym == 'Е') ||(sym == 'е') ||(sym == 'Ё') ||
      (sym == 'ё') ||(sym == 'И') ||(sym == 'и') ||(sym == 'О') ||(sym == 'о') ||
      (sym == 'У') ||(sym == 'у') ||(sym == 'ы') ||(sym == 'Э') ||(sym == 'э') ||
      (sym == 'Ю') ||(sym == 'ю') ||(sym == 'Я') ||(sym == 'я'))
      return 1;
    else
      return 0;
}

//---------------------------------------------------------------------------

int is_rus_letter(int sym)     // if symbol from russian alphabet
{
   if((sym >= 'А') && (sym <= 'я'))
     return 1;
   else
     return 0;
}

//---------------------------------------------------------------------------

int soglasn(int sym)   // return 1 - if soglasn, else return 0
{   
   if(is_rus_letter(sym) && (!glasn(sym)))
     return 1;
   else
     return 0;  
}

//---------------------------------------------------------------------------

// if any visible symbol not BACKSPACE, GAP, ENTER
int rus_graph(int sym)
{
   if(is_rus_letter(sym) || (sym >= 0x21 && sym <= 0x7E))
     return 1;
   else
     return 0;

}

//---------------------------------------------------------------------------

// return 1 - if there is glasn in str else return 0

int find_glasn(char* str)
{
   while(*str)
   {
      if(glasn(*str))
        return 1;
      else if(!is_rus_letter(*str))
        return 0;
      str++;
   }
   return 0;
}

//---------------------------------------------------------------------------

void get_lower(char* str)     // str -> lower register
{
   while(*str)
   {
      if((*str >= 'А') && (*str <= 'Я'))
        *str += 32;
      str++;
   }

   return;
}

//---------------------------------------------------------------------------

// binary search: return first word index with first letter sym, kol - words_count
// else: return -1

int bs(char sym, char** mas, int kol)
{
  int  x, l, r;

  r = kol - 1;                 // right member
  l = 0;                       // left member


  while(l < r)
  {
    x = (r + l) / 2;           // choose middle member
    if(mas[x][0] >= sym)
      r = x;
    else
      l = x + 1;
  }

  if(mas[l][0] == sym)
    return l;
  else
    return -1;
}

//---------------------------------------------------------------------------

// separate prefix, return index of next word part after prefix or 0

int get_pref(char* str)
{
    int   i = 0;        // index in str
    int   len = 0;            // prefix length
    int   n;            // str length
    char* pref_list[] = {"без", "беc", "воз", "вос", "дез", "за", "из", "ис", "контр",
                         "меж", "на", "не", "низ", "нис", "обо", "об", "пан", "пол",
                         "пост", "под", "по", "пред", "пре", "при", "раз", "рас",
                         "рос", "сверх", "со", "суб", "транс", "чрез", "чрес" };
    // at first largest prefixes, for example, "под", "по"

    char* curr_pref;        // current prefix
    char  temp_str[MAXSTR]; // to duplicate str
    int   found = FALSE;    // found = TRUE - prefix found
    int   pref_count = sizeof(pref_list) / sizeof(char*);

    n = strlen(str);
    strcpy(temp_str, str);                   // store str in temp_str
    i = bs(str[0], pref_list, pref_count);   // first letter prefix
    if(i == -1)                              // not found first letter
    {
      strcpy(str, temp_str);                 //restore str
      return 0;
    }

    do
    {
      curr_pref = pref_list[i];            // get new prefix
      // cmp with mask of next prefix
      if(!(strncmp(curr_pref, str, strlen(curr_pref))))
      {
        found = TRUE;
        break;
      }
      i++;
    }
    while((i < pref_count) && (pref_list[i][0] == str[0]));
    // while not end of pref_list and prefix begins from the same letter

    if(found == FALSE)
    {
      strncpy(str, temp_str, n);             //restore str
      return 0;
    }

    len = strlen(curr_pref);                 // get prefix length

    // example: "подъ-езд" , "пой-ти" -> increase len
     if((str[len] == 'ъ') || ((str[len] == 'й') && glasn(str[len - 1])))
      len++;

    //  if prefix ends with soglasn nd next letter "ы", example: "ра-зыграть"
    //  "раз-ыграть"  - error
    // -> decrease len
    else
    {                                        // "об-ыскать"  - error
      if((str[len] == 'ы') && soglasn(str[len - 1]) && len > 2)
        len--;                               // "по-дыскать"
      else if((str[len] == 'ы') && soglasn(str[len - 1]) && len <= 2)
        len = 0;                             // "о-быскать"  - error
    }

    strcpy(str, temp_str);                  //restore str

    return len;
}

//---------------------------------------------------------------------------

/* return 0 - if position i is not valid for perenos
  else return valid perenos index
  str - word, i - index for checking, rpos - max vlid index for perenos
*/

int rule_gl(char* str, int i, int rpos)
{
       int  k, j;
       int  pos;

       pos = k = j = 0;
       if(str[i + 1] == 'й')
         j = 1;           // glasn + 'й' = one letter

       if((str[i - 1] == 'ъ') ||(str[i - 1] == 'ь'))
           k = 1;           // soglasn + 'ъ' = one letter

 // if next letter - glasn, prev letter - soglasn, at least 2 letters after possible perenos
       if(glasn(str[i + j + 1]) && soglasn(str[i - k - 1]) &&
         is_rus_letter(str[i + j + 2]))
       {
         pos = (pos > rpos) ? 0 : (i + j);
       }
 // if next letter - soglasn, prev letter - glasn, there is at least one glasn in rpart
       else if(soglasn(str[i + j + 1]) && soglasn(str[i - k - 1]) && find_glasn(str + i + j + 2))
       {
         pos = (pos > rpos) ? 0 : (i + j);
       }
         
       return pos;
}

//---------------------------------------------------------------------------

/* return 0 - if position i is not valid for perenos
  else return valid perenos index
  str - word, i - index for checking, rpos - max vlid index for perenos
*/

int rule_sogl(char* str, int i, int rpos)
{
       int  j;
       int  pos = 0;

       pos = j = 0;
       if((str[i + 1] == 'ъ') ||(str[i + 1] == 'ь'))
         j = 1;  // soglasn + 'ъ' = one letter

 // if next letter - soglasn, prev letter - glasn, there is at least one glasn in rpart
       if(soglasn(str[i + j + 1]) && glasn(str[i - 1]) &&
         find_glasn(str + i + j + 2))
       {
           pos = (pos > rpos) ? 0 : (i + j);
       }

       return pos;
}

//---------------------------------------------------------------------------

// rpos - max right perenos position, lpart - left_str + '-', rpart - right_str

void get_perenos(char* str, int rpos, char* lpart, char* rpart)
{
    int   len;
    int   t = 0;         // word part after non-letter symbols - (, " e.t.c.
    int   st = 0;        // word part after prefix
    int   i;             // current str index
    int   pos = 0;       // found perenos position
    int   max = FALSE;   // indicator: if maxlen str without perenos
    char  temp[MAXSTR];  // to duplicate str

    if(rpos <= 1)        // if there is space for only letter - > impossible
    {
      *lpart = '\0';
      strcpy(rpart, str);
      return;
    }

    strcpy(temp, str);                       // store str
    get_lower(str);                          // get str in lower register
    while(str[t] && !is_rus_letter(str[t]))  // missing non-letter symbols
    {
      t++;                                   // count of non-letter symbols
      str++;                                 // cut str beginning
    }
    if((*str == '\0') || (t >= rpos))        // if all str consists of non-letter symbols
    {                                        // or letters are too far to get perenos
      *lpart = '\0';
      strcpy(rpart, temp);                   // impossible
      return;
    }
    rpos -= t;                              // correction rpos for new str
    len = strlen(str);                      // str length
    st = get_pref(str);                     // try to get prefix
    if(st > rpos)             // if no enough space to get perenos of one_slog prefix
    {                         // we need 1 position for '-'
      *lpart = '\0';
      strcpy(rpart, temp);    // impossible
      return;
    }

    i = (rpos > (len - 3)) ? (len - 3) : rpos;
    // set max possible i index for perenos (at least 2 letters must be for right)
    // or pred-pred last letter, or rpos

    while(i > st)           // try to get perenos after prefix
    {
       if(glasn(str[i]))
       {
         if(pos = rule_gl(str, i, rpos))
           break;
       }
       else if(soglasn(str[i]))
       {
         if(pos = rule_sogl(str, i, rpos))
           break;
       }
       i--;    // take prev position to try get perenos
    }

    // after cycle:
    // if found prefix and no perenos after prefix and
    // 1) only one letter after prefix   or
    // 2) no glasn in rpart
    if(!pos && st && (((len - st) == 1) || !(find_glasn(str + st))))
    {
      *lpart = '\0';            // impossible
      strcpy(rpart, temp);
      return;
    }

    // if no prefix and no perenos
    if(!pos && !st)
    {
      if((len < (right - left + 1 - is_red - t)))  // if not the whole str without perenos
      {
        *lpart = '\0';
        strcpy(rpart, temp);
        return;
      }
      else
      {
        pos = len - 2;        // if "ппппппппппппппппп"  (only soglasn without glasn)
        max = TRUE;
      }

    }

    // if 1) found prefix
    //    2) no perenos after prefix
    //    3) rpart  - not one letter
    //    4) first glasn after prefix  - Ы
    if(!pos && st && ((len - st) > 1))
      if(str[st] == 'ы')
        pos = st - 2;               // "по-дытожить"
      else
        pos = st - 1;                   // "под-ставить"

    pos += t;                       // return folowwing non-letter symbols
    strncpy(lpart, temp, pos + 1);  // fill lpart
    if(!max)                        // if not the whole str without perenos
    {
      lpart[pos + 1] = '-';         // add '-'
      lpart[pos + 2] = '\0';
    }
    else
      lpart[pos + 1] = '\0';        // without '-'
    strcpy(rpart, temp + pos + 1);  // fill rpart

    return;
}

//---------------------------------------------------------------------------







--------------------
Помни - когда ты спишь, враг не дремлет
Спи чаще и дольше, изматывай врага бессоницей
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Центр помощи"

ВНИМАНИЕ! Прежде чем создавать темы, или писать сообщения в данный раздел, ознакомьтесь, пожалуйста, с Правилами форума и конкретно этого раздела.
Несоблюдение правил может повлечь за собой самые строгие меры от закрытия/удаления темы до бана пользователя!


  • Название темы должно отражать её суть! (Не следует добавлять туда слова "помогите", "срочно" и т.п.)
  • При создании темы, первым делом в квадратных скобках укажите область, из которой исходит вопрос (язык, дисциплина, диплом). Пример: [C++].
  • В названии темы не нужно указывать происхождение задачи (например "школьная задача", "задача из учебника" и т.п.), не нужно указывать ее сложность ("простая задача", "легкий вопрос" и т.п.). Все это можно писать в тексте самой задачи.
  • Если Вы ошиблись при вводе названия темы, отправьте письмо любому из модераторов раздела (через личные сообщения или report).
  • Для подсветки кода пользуйтесь тегами [code][/code] (выделяйте код и нажимаете на кнопку "Код"). Не забывайте выбирать при этом соответствующий язык.
  • Помните: один топик - один вопрос!
  • В данном разделе запрещено поднимать темы, т.е. при отсутствии ответов на Ваш вопрос добавлять новые ответы к теме, тем самым поднимая тему на верх списка.
  • Если вы хотите, чтобы вашу проблему решили при помощи определенного алгоритма, то не забудьте описать его!
  • Если вопрос решён, то воспользуйтесь ссылкой "Пометить как решённый", которая находится под кнопками создания темы или специальным флажком при ответе.

Более подробно с правилами данного раздела Вы можете ознакомится в этой теме.

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Poseidon, Rodman

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Центр помощи | Следующая тема »


 




[ Время генерации скрипта: 0.0466 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.