Переписать код с C++ на Python ( разбиение на слоги)

Есть код на C++, который разбивает слово на слоги, нужно переписать его на Python

Снизу код на C++ и моя попытка переписать его на Python


//Для подключения и использования стандартной библиотеки ввода-вывода
#include <iostream>
//Подключение библиотеки строковых функций:
//memset(), strcpy(), strlen(), strncat()
//их описание легко найти в сети
#include <string.h>
#include "stdlib.h"
//Для вывода русских символов на консоль (см. setlocale(LC_ALL,"Rus"))
#include <clocale>
//Делаем глобальным пространство имен стандартных шаблонов
using namespace std;
//Глобальные константы для длин вспомогательных текстовых буферов
#define SUBL 512
#define BIGL 4096
//------------------------------------------------------------------
//Сам алгоритм разбиения, а также его элементы реализованы
//с помощью функций. Благодаря такому подходу код будет компактным,
//ясным и хорошо структурирован. Кроме того, функция main не будет
//загромождена текстом программы.
//------------------------------------------------------------------
//Сначала реализуем несколько вспомогательных функций, которые
//помогут сделать наглядным наш алгоритм
//------------------------------------------------------------------
//Функция IsVowel возвращает 1 (истина), если проверяемый символ letter
//является гласной буквой русского алфавита и 0 (ложь) в противном
//случае
////////////////////////////////////////////////////////////////////
bool IsVowel(char letter){
  char l = tolower(letter);//приводим символ к нижнему регистру А->а
  char a[] = "аоэиуыеёюя";//10
  for(int i=0;i<strlen(a);i++)//по очереди проверяем
    if(a[i] == l) return true;//является ли символ l одним из a[i]
  return false;
}
//------------------------------------------------------------------
//Функция IsConsonant возвращает 1 (истина), если проверяемый символ letter
//является согласной буквой русского алфавита и 0 (ложь) в противном
//случае
////////////////////////////////////////////////////////////////////
bool IsConsonant(char letter){
  char l = tolower(letter);//приводим символ к нижнему регистру А->а
  char a[] = "бвгдйжзклмнпрстфхцчшщ";//21
  for(int i=0;i<strlen(a);i++)
    if(a[i] == l) return true;
  return false;
}
//------------------------------------------------------------------
//Функция IsLetter возвращает 1 (истина), если проверяемый символ letter
//является буквой русского алфавита и 0 (ложь) в противном
//случае
////////////////////////////////////////////////////////////////////
bool IsLetter(char letter){
  char l = tolower(letter);//приводим символ к нижнему регистру А->а
  char a[] = "абвгдеёжзийклмнопрстуфхцчшщыъьэюя";//33
  for(int i=0;i<strlen(a);i++)
    if(a[i] == l) return true;
  return false;
}
//------------------------------------------------------------------
//Функция ContainVowel возвращает 1 (истина), если в строке str
//есть гласная буква русского алфавита и 0 (ложь) в противном
//случае
////////////////////////////////////////////////////////////////////
bool ContainVowel(char *str){
  for(int k=0;k<strlen(str);k++)
    if(IsVowel(str[k])) return true;
  return false;
}
//------------------------------------------------------------------
//Функция InsertDash вставляет тире в позицию pos строки str
////////////////////////////////////////////////////////////////////
void InsertDash(char *str,int pos){
  int n = strlen(str);
  for(int i=n+1;i>pos;i--)
    str[i] = str[i-1];
  str[pos] = '-';
}
//------------------------------------------------------------------
//Функция GetWord выделяет из текста str первое
//встреченное в ней слово
////////////////////////////////////////////////////////////////////
char* GetWord(char* str,char* buf){
  memset(buf,'\0',SUBL);//заполняем буфер нулями
  int i=0, j=0, n = strlen(str);
  //пропускаем не буквы
  while (!IsLetter(str[i]) && i < n)
    i++;
  //а буквы не пропускаем
  while (IsLetter(str[i]) && i < n){
    buf[j] = str[i];
    i++; j++;
  }
  return buf;
}
//------------------------------------------------------------------
//Функция SubString возвращает фрагмент строки начиная с символа
//в позиции pos и длиной len
////////////////////////////////////////////////////////////////////
char* SubString(char* str, char* buf, int pos, int len){
  int n = strlen(str), i, j = 0, a = len + pos;
  memset(buf,'\0',SUBL);//заполняем буфер нулями

  if(len == 0 || a > n) a = n;//контроль выхода за границы

  for(i=pos;i<a;i++,j++)//копируем элементы в подстроку
    buf[j] = str[i];

  return buf;
}
//------------------------------------------------------------------
//Функция SplitWord - главная функция, которая разбивает слово str
//на слоги и возвращает группу слогов разделенных тире
////////////////////////////////////////////////////////////////////
char* SplitWord(char* str,char* buf){
  char sub[SUBL];
  memset(sub,'\0',SUBL);//заполняем буфер нулями
  strcpy (buf,str);
  int pos = 0, len = strlen(str), i = 1;
  while(i < len){
    if(i+2 < len){
      //проверка первого условия из задания
      // сг-гx (x - хотя бы одна буква)
      if(IsConsonant(str[i-1]) && IsVowel(str[i]) &&
                                                  IsVowel(str[i+1]) ){
        InsertDash(buf,i+1+pos);
        pos++;
      } else
      //проверка второго условия из задания
      // гс-сy (y - имеется хотя бы одна гласная)
      if(IsVowel(str[i-1]) && IsConsonant(str[i]) && IsConsonant(str[i+1]) &&
                                      ContainVowel(SubString(str,sub,i+2,0))){
        InsertDash(buf,i+1+pos);
        pos++;
      } else
      //проверка третьего условия из задания
      // xг-y  (y - имеется хотя бы одна гласная)
      if(IsLetter(str[i-1]) && IsVowel(str[i]) &&
         ContainVowel(SubString(str,sub,i+1,2))){
        InsertDash(buf,i+1+pos);
        pos++;
      }
      //обработка случая, когда два первых символа гласные
      if(i == 1 && IsVowel(str[i-1])  &&
         ContainVowel(SubString(str,sub,i,2))){
        InsertDash(buf,i);
        pos++;
      }
    }
    i++;
  }
  return buf;
}
//------------------------------------------------------------------
//Функция Processing принимает строку str, которая может состоять
//из нескольких слов и возвращает строку с разбитыми на слоги словами
//Эту простую функцию мы будем вызывать в main
////////////////////////////////////////////////////////////////////
char* Processing(char* str,char* buf){
  int start, end  = strlen(str), j=0, i=0;
  char buf1[SUBL], buf2[SUBL], buf3[SUBL], *word = NULL;
  memset(buf,'\0',BIGL);//заполняем буфер нулями
  while(i < end){
    //Вставка знаков препинания
    //если не буква, значит знак препинания
    while(!IsLetter(str[i]) && i < end){
      buf[j] = str[i];
      i++; j++;
    }
    start = i;
    //Получение очередного слова
    word = GetWord(SubString(str,buf1,start,end),buf3);
    i += strlen(word);
    //Разбивка на слоги
    //копируем разбитое слово в буфер
    strcpy (buf1,SplitWord(word,buf2));
    //вставляем слово из буфера в результирующую строку
    strncat(buf,buf1,strlen(buf1));
    j += strlen(buf1);
    //Конец разбивки на слоги
  }
  return buf;
}
//------------------------------------------------------------------
int main(int argc, char *argv[]) {
  //Эта команда позволяет выводить русские символы на консоль
  //забей в гугл "вывод русских символов на консоль C++"
  setlocale(LC_ALL,"Rus");
  char buf[BIGL];//Объявляем вспомогательный текстовый буфер
  char text[] =
  "Пример текста слова которого надо разбить на слоги.";
  cout << text << endl;
  cout << Processing(text,buf) << endl;
  char text1[] =
  "хоккей";
  cout << text1 << endl;
  cout << Processing(text1,buf) << endl;
  //system("cls") - использовать незачем
  system("pause");
  return 0;
}

Код на Python:

def is_vowel(letter):
    if letter.lower() in "аоэиуыеёюя":
        return True 
    return False

def is_consonant(letter):
    if letter.lower() in "бвгдйжзклмнпрстфхцчшщ":
        return True 
    return False

def is_russian_letter(letter):
    letter = letter.lower()
    if letter.lower() in "абвгдеёжзийклмнопрстуфхцчшщыъьэюя":
        return True
    return False 


def check_vowel(string):
    for letter in string:
        if is_vowel(letter):
            return True
    return False

def insert_dash(string, position):
    length = len(string)
    for letter in range(position, length+1, -1):
        string[letter] = string[letter - 1]
    string[position] = '-'


def get_word(string):
    buf = [0]*512
    i = 0; j = 0
    length = len(string)
    while not is_russian_letter(string[i]) and i < length:
        i += 1
    while is_russian_letter(string[i]) and i < length:
        buf[j] = string[i]
        i += 1; j += 1
    return buf


def substring(string, position, length):
    n = len(string)
    i = 0; j = 0
    a = length + position
    buf = [0]*512

    if length == 0 or a > n: a = n

    for _ in range(position, a):
        buf[j] = string[i]
        i += 1; j += 1

    return buf

def split_word(string):
    sub = [0]*512
    buf = string
    pos = 0
    length = len(string)
    i = 1
    while i < length:
        if i+2 < length:
            if is_consonant(string[i-1]) and is_vowel(string[i]) and is_vowel(string[i+1]):
                insert_dash(buf, i + 1 + pos)
                pos += 1
            else:
                if is_vowel(string[i-1]) and is_consonant(string[i]) and is_consonant(string[i+1]) and check_vowel(substring(string, sub, i+1, 0)):
                    insert_dash(buf, i+1+pos)
                    pos += 1

                else:
                    if is_russian_letter(string[i-1]) and is_vowel(string[i]) and check_vowel(substring(string,sub,i+1,2)):
                        insert_dash(buf, i+1+pos)
                        pos += 1

                    if i == 1 and is_vowel(string[i-1]) and check_vowel(substring(string, sub, i, 2)):
                        insert_dash(buf, i)
                        pos += 1

        i += 1

    return buf



def processing(string):
    end = len(string)
    j = 0; i = 0
    buf = [0]*512
    buf1, buf2, buf3 = [], [], []
    while i < end:
        while not is_russian_letter(string[i]) and i < end:
            buf[j] = string[i]
            i+=1; j+=1

        start = i 
        word = get_word(substring(string, start, end))
        i += len(word)
        buf1 = split_word(word)
        j += len(buf1)

    return buf

def main():
    buf = [0]*512
    text = 'Суета'
    print(processing(text))

if __name__ == '__main__':
    main()

Вылезают различные ошибки: исправляю одну - появляется другая. Вот последняя: AttributeError: 'int' object has no attribute 'lower' line 12, in is_russian_letter Вроде заполняю нулями массив, и он берет не букву, а число, что делать - не знаю.


Ответы (2 шт):

Автор решения: Zhihar
  1. Вот последняя: AttributeError: 'int' object has no attribute 'lower' line 12, in is_russian_letter Вроде заполняю нулями массив, и он берет не букву, а число, что делать - не знаю.

    потому что функция у вас букву переводит в нижний регистр

    letter.lower()
    

    но в массив вы кроме букв пишите еще и нули - а это ЧИСЛА, числа нельзя переводить в нижний регистр, так что вам надо делать или:

     if letter == 0:
         return False
    

    или

     if str(letter).lower()
    
  2. кроме этого у вас в коде еще много ошибок, например

     i = 0; j = 0
    

    в питоне так не пишут

  3. кроме того вы используете функцию

     substring(string, sub, i+1, 0)
    

    хотя ей надо на вход 3 параметра

  4. внутри функции substring вы делаете

     a = length + position
    

    но position у вас принимает список, а вы число складываете со списком

P.S.

на самом деле выгоднее в таких случаях писать код чуть ли не с нуля, а C++ код использовать лишь как инструкцию

→ Ссылка
Автор решения: Zhihar

кое что сделал, но логические ошибки уже ищите сами:

def IsVowel(letter):
    return letter.lower() in "аоэиуыеёюя"


def IsConsonant(letter):
    return letter.lower() in "бвгдйжзклмнпрстфхцчшщ"


def IsLetter(letter):
    return letter.lower() in "абвгдеёжзийклмнопрстуфхцчшщыъьэюя"


def ContainVowel(text):
    for letter in text:
        if IsVowel(letter):
            return True
    return False


def SplitWord(text):
    size = len(text)

    buf = []

    for i in range(size):
        buf.append(text[i])
        if 0 < i < size - 2:
            # проверка первого условия из задания
            # сг-гx (x - хотя бы одна буква)
            if IsConsonant(text[i - 1]) and IsVowel(text[i]) and IsVowel(text[i + 1]):
                buf.append('-')
            else:
                # проверка второго условия из задания
                # гс-сy (y - имеется хотя бы одна гласная)
                if IsVowel(text[i - 1]) and IsConsonant(text[i]) and IsConsonant(text[i + 1]) and ContainVowel(text[i + 2:]):
                    buf.append('-')
                else:
                    # проверка третьего условия из задания
                    # xг-y  (y - имеется хотя бы одна гласная)
                    if IsVowel(text[i]) and ContainVowel(text[i + 1:]):
                        buf.append('-')

        # обработка случая, когда два первых символа гласные
        if i == 1 and IsVowel(text[i - 1]) and ContainVowel(text[i]):
            buf.append('-')

    return ''.join(buf)


text = "Кооператив Пример текста слова которого надо разбить на слоги."

# разбить предложения на слова
words = text.split()

# разбить каждое слово на слога
new_words = []
for word in words:
    # разбить текущее слово на слога
    new_words.append(SplitWord(word))

# соединить слова в предложение
print(' '.join(new_words))
→ Ссылка