1. Наш канал codeby в telegram. Пишем об информационной безопасности, методах защиты информации, о программировании. Не пропускай новости с кодебай, будь в тренде ! Подробнее ...

    Скрыть объявление

Шекспир

Тема в разделе "Вопросы новичков и не только", создана пользователем a9x, 1 дек 2012.

  1. a9x

    a9x Гость

    Репутация:
    0
    Задание: написать программу, которая считывает txt файл - Шекспир во оригинале на английском, и считает слова, которые Шекспир употребил в произведении - все слова, кроме тех, которые повторяются. Главное - чтобы прога считала слова в разных формах с окончаниями -ing, -ed, -ies и тд - за одно слово. Я написал программу, которая считает слова, и те, которые повторяются - считает за одно слово. Помогите пож с разными формами.
    Например слова change, changed - считать за одно слово.
    Вот моя прога
    Код:
    procedure TForm1.Button1Click(Sender: TObject);
    const
    // Все, что считается разделителем
    Separator = ['''', '"', '&', '.', ',', ':', ';', '!', '?', '-', ' ', #9, #10, #13];
    var
    sL, sLtxt: TStringList;
    i: integer;
    f: TextFile;
    s: string;
    begin
    sL := TStringList.Create;	 // Создаем переменную для хранения слов
    sL.Sorted :=true;			 // Назначаем ей св-ва Сортировать
    sL.Duplicates := dupIgnore;	// и игнорировать дубликаты
    AssignFile(f,'Otello.txt');		// Связываем f с текстовым файлом
    Reset(f);					 // Начало файла
    while not EOF(f) do			// Пока не дойдем до конца
    begin
    ReadLn(f,s);				 // Читаем строку
    for i := 1 to Length(s) do  // Если есть кавычка ('), заменяем на пробел
    if s[i] = '''' then s[i] := ' ';
    ExtractStrings(Separator, [' '], PAnsiChar(s), sL); // и записываем их в sL
    end;
    ListBox1.Items.Assign(sL);	 // Выводим результат в ЛистБокс
    sL.Free;					  // Освобождаем память от ненужных больше переменных
    CloseFile(f);				 // Закрываем файл
    ShowMessage(IntToStr(ListBox1.Count)); // Показываем кол-во найденных слов
    
    end;
    end.
     
  2. sinkopa

    sinkopa Well-Known Member

    Репутация:
    0
    Регистрация:
    17 июн 2009
    Сообщения:
    344
    Симпатии:
    9
    Это вопрос скорее по английскому языку... :rolleyes:
    Вот. передоделал Ваш код...
    Предложения, замечания в комментариях...
    Код:
    uses
    StrUtils;
    
    procedure TForm1.Button1Click(Sender: TObject);
    const
    // Все, что считается разделителем
    Separator = ['''', '"', '&', '.', ',', ':', ';', '!', '?', '-', ' ', #9, #10, #13];
    var
    sL, sLtxt: TStringList;
    i,j,sLen: integer;
    f: TextFile;
    s: string;
    begin
    sL := TStringList.Create;	 // Создаем переменную для хранения слов
    sL.Sorted :=true;			 // Назначаем ей св-ва Сортировать
    sL.Duplicates := dupIgnore;	// и игнорировать дубликаты
    
    // Поскольку потоковые операции быстрее чем файловые,
    // вместо AssignFile(f,'Otello.txt'); Reset(f) и ReadLn(f,s)
    // предлагаю использовать следующее:
    sLtxt := TStringList.Create;	 // Создаем переменную для загрузки текстового файла
    sLtxt.LoadFromFile('Otello.txt'); // Загружаем текст
    
    for i := 0 to sLtxt.Count-1 do
    begin
    s := Trim(AnsiLowerCase(sLtxt[i])); // Читаем строку !!! в нижнем регистре !!!
    // иначе слова будут дублироваться
    // например: "This" и "this" получится два разных слова
    if (s = '') then Continue; // пустые пропускаем
    
    for j := 1 to Length(s) do		 // !!! Не уверен что это правильно... этот код
    if s[j] = '''' then s[j] := ' '; // поделит такие слова как "It's", "I've" на два слова
    
    ExtractStrings(Separator, [' '], PAnsiChar(s), sL); // и записываем их в sL
    end;
    
    sLtxt.Clear;
    // вынимаем из sL трансформы c окончаниями
    // -ing, -ed, -ies -es -s
    for i := sL.Count-1 downto 0 do
    begin
    s := sL[i];
    if (	AnsiEndsStr('ing', s) // change -> changing
    or AnsiEndsStr('ed', s ) // press -> pressed
    or AnsiEndsStr('ies', s) // dictionary -> dictionaries.
    or AnsiEndsStr('es', s)  // box -> boxes
    or AnsiEndsStr('s', s)	// day --> days
    ) then
    begin
    sLtxt.Add(s); // переносим в sLtxt
    sL.Delete(i);
    end;
    end;
    
    // обрабатываем трансформы
    for i := 0 to sLtxt.Count-1 do
    begin
    s := sLtxt[i];	 // взяли слово
    sLen := Length(s); // получили длину
    
    // вычисляем длину корня слова
    if AnsiEndsStr('ing', s) then
    Dec(sLen,3)
    else if AnsiEndsStr('ies',s ) then
    Dec(sLen,3)
    else if AnsiEndsStr('es', s ) then
    Dec(sLen,2)
    else if AnsiEndsStr('ed', s ) then
    Dec(sLen,2)
    else if AnsiEndsStr('s', s ) then
    Dec(sLen,1);
    
    if (sLen < 2) then // Это не корень базовой формы слова, возвращаем слово в sL
    sL.Add(s)
    else
    begin
    SetLength(s,sLen); // отрезаем окончание (укорачиваем для длины слова)
    
    // пытаемся найти в sL одну из словоформ
    if	( sL.IndexOf(s) < 0 )		 // базовая форма "day", "press" и тп.
    and ( sL.IndexOf(s+'e')  < 0 )  // базовая форма "change" и тп.
    and ( sL.IndexOf(s+'y')  < 0 )  // базовая форма "dictionary" и тп.
    and ( sL.IndexOf(s+'ed') < 0 )  // трансформ "pressed", "changed" и тп.
    and ( sL.IndexOf(s+'ies') < 0 )  // трансформ "dictionaries" и тп.
    and ( sL.IndexOf(s+'ing') < 0 )  // трансформ "pressing", "changing" и тп.
    and ( sL.IndexOf(s+'s')  < 0 )  // трансформ "days", "boys" и тп.
    then
    begin
    // Если не нашлось ни одного из вариантов - возвращаем слово в sL
    sL.Add(sLtxt[i])
    end;
    end;
    end;
    sLtxt.Clear;
    
    ListBox1.Items.Assign(sL);	 // Выводим результат в ЛистБокс
    sL.Free;					  // Освобождаем память от ненужных больше переменных
    sLtxt.Free;
    ShowMessage(IntToStr(ListBox1.Count)); // Показываем кол-во найденных слов
    end;
     
  3. Proger23

    Proger23 New Member

    Репутация:
    0
    Регистрация:
    13 мар 2013
    Сообщения:
    1
    Симпатии:
    0
    Спасибо, очень помогло
     

Поделиться этой страницей