
механик-вредитель
  
Профиль
Группа: Участник Клуба
Сообщений: 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; }
//---------------------------------------------------------------------------
|
--------------------
Помни - когда ты спишь, враг не дремлет Спи чаще и дольше, изматывай врага бессоницей
|