Здравствуйте. Не могли бы подсказать как сделать вот такую штуку: замешательство в TMemo находится английский текст (например:
Цитата
Hello world
), как сделать так чо бы считывать слова и вставлять их перевод в др мемо из файла-словаря? В файле слова находятса в таком виде:
.................. hello привет .................. .................. world мир ...............
И результат получался бы типа такого:
Цитата
привет мир
Altair
29.08.2005 17:18
все просто. Надо сначала слова выделить в memo, как это сделать читай в FAQе нашем... далее все очевидно...
Н
31.08.2005 1:17
Цитата
Надо сначала слова выделить в memo
это, то есть считать их в массив, или я не правильно понял?
Malice
31.08.2005 13:22
Цитата(Н @ 30.08.05 22:17)
это, то есть считать их в массив, или я не правильно понял?
Я бы не стал выделять слова, т.к. потом после замены придется их опять в строку клеить, да и все знаки запятые и проч. потеряются. Проще читать построчно, искать вхождение каждого слова через Pos и сразу заменять. Правда придется добавить проверку, чтобы не было замен внутри слов, но это прсто
Н
31.08.2005 14:39
Цитата
Проще читать построчно, искать вхождение каждого слова через Pos и сразу заменять. Правда придется добавить проверку, чтобы не было замен внутри слов
А как это сделать, можно пример?
volvo
31.08.2005 15:02
Вот тебе работающий набросок на FPC, просто добавь построчное чтение из Memo в строку S и измени процедуру Replace_Word так, чтобы она меняла переданное ей слово на соотв. слово из файла-словаря:
procedure replace_word(s: string); begin write('(-', s, '-)'); { <--- замени на вывод во второй Memo } end;
var s: string = 'this ::is a, text'; next_word: string; i: byte;
begin i := 1; next_word := ''; while i <= length(s) do begin if upcase(s[i]) in ['A'..'Z'] then begin next_word := next_word + s[i]; inc(i) end else begin if next_word <> '' then replace_word(next_word); write(s[i]); { <--- замени на вывод во второй Memo } next_word := ''; inc(i); end; end;
if next_word <> '' then replace_word(next_word);
end.
Как видишь, все разделители сохраняются... Кстати, эту программку можно еще оптимизировать ;)
Malice
31.08.2005 15:19
Цитата(Н @ 31.08.05 11:39)
А как это сделать, можно пример?
Как то вот так:
for i:=1 to КолвоСловВсловаре do for j:=0 to memo1.Lines.Count-1 do begin p:=1; while p>0 do begin sT:=memo1.Lines.Strings[j]; p:=pos(word[i].en,st); if p>0 then memo1.Lines.Strings[j]:=copy(st,1,p-1)+word[i].ru+ copy(st,p+length(word[i].en),255); end; end;
Н
31.08.2005 17:50
Цитата
построчное чтение из Memo в строку S
блин не получается сделать, и найти не могу как делать ...
Malice
31.08.2005 17:53
Цитата(Н @ 31.08.05 14:50)
блин не получается сделать, и найти не могу как делать ...
Ну так как у меня: s:=memo1.Lines.Strings[j];
Строки нумируются с нуля.
volvo
31.08.2005 17:56
For currLine := 0 To Pred(memo1.Lines.Count) Do Begin s := memo1.Lines.Strings[currLine] ... End;
Н
31.08.2005 19:10
volvo, Malice Спасибо...
Н
31.08.2005 19:55
Цитата
Replace_Word так, чтобы она меняла переданное ей слово на соотв. слово из файла-словаря
Я открываю файл для чтения, а как дальше осуществить писк и замену S ?
hiv
1.09.2005 12:54
Словарь лучше хранить в виде: word=слово
Тогда чтение его и использование упрощается:
var ER :TStrings; . . . // загрузка словаря ER:=TStringList.Create; ER.LoadFromFile('имя файла словаря'); . . . // замена найденного английского слова на русское в переменной sw :string; sw:=ER.Values[sw]; . . .
Вот и все. А как найти в строке все слова можно найти в FAQ.
Н
2.09.2005 1:46
Цитата
как найти в строке все слова можно найти в FAQ.
Пересмотрел FAQ несколько раз но ничего подобного не нашел ...
volvo
2.09.2005 1:54
В каком FAQ-е искал? В Дельфийском? А в Паскалевском посмотреть не догадался? Синтаксис-то один и тот же Вот тут (и в соседних постах) посмотри: FAQ: Строки
Хотя я тебе привел более подходящий для твоего случая алгоритм, сохраняющий все разделители, а функция из FAQ-а все разделители выбрасывает.
Н
2.09.2005 12:51
Цитата
Хотя я тебе привел более подходящий для твоего случая алгоритм, сохраняющий все разделители, а функция из FAQ-а все разделители выбрасывает.
Я просто хотел доделать твой алгоритм, что бы происходил поиск, слов из считанной строки, в словаре и их замена...
hiv
5.09.2005 12:17
Смотри пост 13. Лучше всетаки сделать проверку, что английское слово не найдено, тогда оно остается неизменным в тексте:
var ER :TStrings; . . . // загрузка словаря ER:=TStringList.Create; ER.LoadFromFile('имя файла словаря'); . . . // замена найденного английского слова на русское в переменной sw :string; sw_rus:=ER.Values[sw]; if sw_rus='' then sw_rus:=sw; . . . // освобождаем память, занятую словарем ER.Free; . . .
PS: Не забудь, что в английском есть сокращения с использованием апострофа, а также он используется в именах собственных в притяжательном склонении.
Н
6.09.2005 1:18
Собрал все в одно, вот что получилось:
procedure replace_word(next_word: string); var next_word_rus: string; ER :TStrings;
begin ER:=TStringList.Create; ER.LoadFromFile('voc.txt'); next_word_rus:=ER.Values[next_word]; if next_word_rus='' then next_word_rus:=next_word; Memo2.Lines.Add(next_word_rus); er.free
end;
procedure TForm1.Button1Click(Sender: TObject);
var s, next_word: string; i: byte; currLine: integer;
begin For currLine := 0 To Pred(memo1.Lines.Count) Do Begin s := memo1.Lines.Strings[currLine]; i := 1; next_word := ''; while i <= length(s) do begin if upcase(s[i]) in ['A'..'Z'] then begin next_word := next_word + s[i]; inc(i) end else begin if next_word <> '' then replace_word(next_word); Memo2.Lines.Add(s[i]); next_word := ''; inc(i); end; end;
if next_word <> '' then replace_word(next_word); end; end;
Ну, с этой ошибкой: " [Error] 123.pas(41): Undeclared identifier: 'Memo2' " довольно прозрачно: у тебя просто Memo2 принадлежит классу формы, но вот процедура replace_word - то не является методом этого класса, поэтому для нее Memo2 не существует...
А вот эта: " [Error] 123.pas(41): Missing operator or semicolon " исчезнет сама собой, как только будет исправлена первая, просто сейчас структура программы нарушена, и пока ее не восстановишь - дальше будут "наведенные" ошибки...
hiv
6.09.2005 12:17
Я не зря ставил многоточия в своем примере! В твоей программе при проверке каждого слова будет каждый раз грузиться файл словаря - это просто не нужно делать! Перенеси чтение словаря до начала перевода всех слов, а его уничтожение (освобождение памяти Free) после всего перевода.
Н
6.09.2005 17:10
Вот я исправил, на мемо больше не ругается, но когда нажимаю перевод, вылетает сообщение об ошибке:
"Project Projectl.exe raised exception class EAccessViolation with message 'Access violation at address 00414988 in module 'Projectl.exe'. Read of address 00000004' Process stopped. Use Step or Run to continue."
"Access violation at address 00414988 in module 'Project1.exe'. Read of address 00000004."
И в итоге ни чего не переводит ...
procedure TForm1.replace_word (next_word: string); var next_word_rus: string; ER :TStrings;
begin
next_word_rus:=ER.Values[next_word]; if next_word_rus='' then next_word_rus:=next_word; Memo2.Lines.Add(next_word_rus);
end;
procedure TForm1.Button1Click(Sender: TObject);
var s, next_word: string; i: byte; currLine: integer; ER :TStrings;
begin ER:=TStringList.Create; ER.LoadFromFile('voc.txt'); For currLine := 0 To Pred(memo1.Lines.Count) Do Begin s := memo1.Lines.Strings[currLine]; i := 1; next_word := ''; while i <= length(s) do begin if upcase(s[i]) in ['A'..'Z'] then begin next_word := next_word + s[i]; inc(i) end else begin if next_word <> '' then replace_word(next_word); Memo2.Lines.Add(s[i]); next_word := ''; inc(i); end; end;
if next_word <> '' then replace_word(next_word); end; er.free end;
Н
6.09.2005 17:19
забыл добавить, что показывает при это на вот эту строку:
if next_word_rus='' then next_word_rus:=next_word;
hiv
6.09.2005 17:46
Переменную ER :TStrings; нужно объявить как public в объекте TForm1, для того чтобы можно было к ней обращаться из разных процедур и функций твоей формы. А у тебя она объявлена дважды в разных процедурах - это тогда две разные переменные. Одну из них ты создал и выделил под нее память, а другую нет - но при этом от нее чего-то хочешь получить - вот тебе и ошибка! :yes: А вообще-то ради двух строчек кода городить дополнительную процедуру (replace_word) не имеет смысла.
Н
6.09.2005 18:27
Спасибо, теперь ошибки не выдает :D
Но перевод выводит как то непонятно: каждое слово и знак препинания в новой строке:
Англ текст
Цитата
Hello, world!
Перевод
Цитата
привет ,
мир !
Может это я вывод в мемо не правельно сделал?
hiv
6.09.2005 18:33
У тебя в коде:
Memo2.Lines.Add(s[i]);
эта процедура как раз и добавляет новую строку с содержимым s[i] Тебе нужно вначале перевести всю строку, а только потом записывать ее в Memo2. ЗЫ: Только писать нужно Memo2.Lines.Add(s); т.к. s[i] - это всего-то i-тый символ в строке.
Н
7.09.2005 2:43
Вот делал вывод в мемо так:
procedure TForm1.Button1Click(Sender: TObject);
var s, next_word, next_word_rus, t: string; i: byte; currLine: integer;
begin t:=''; ER:=TStringList.Create; ER.LoadFromFile('voc.txt'); For currLine := 0 To Pred(memo1.Lines.Count) Do Begin s := memo1.Lines.Strings[currLine]; i := 1; next_word := ''; while i <= length(s) do begin if upcase(s[i]) in ['A'..'Z'] then begin next_word := next_word + s[i]; inc(i) end else begin if next_word <> ''then next_word_rus:=ER.Values[next_word]; if next_word_rus='' then next_word_rus:=next_word;
t:= t + next_word_rus;
t:= t + s[i];
next_word := ''; inc(i); end; end;
Memo2.Lines.Append(t);
end; er.free end;
но выводится какая то чуш:
Цитата
Hello, world!!!
перевод
Цитата
привет,привет мир!мир!мир!
Как еще можно сделать вывод в мемо?
volvo
7.09.2005 2:52
У меня вот так работает:
function TForm1.replace_word (var ER: tstrings; next_word: string): string; var next_word_rus: string; begin next_word_rus:=ER.Values[next_word]; if next_word_rus='' then next_word_rus:=next_word; result := next_word_rus; end;
procedure TForm1.Button1Click(Sender: TObject); var s, next_word, t: string; i: byte; currLine: integer; ER :TStrings;
begin t := ''; ER:=TStringList.Create; ER.LoadFromFile('voc.txt'); For currLine := 0 To Pred(memo1.Lines.Count) Do Begin s := memo1.Lines.Strings[currLine]; i := 1; next_word := ''; while i <= length(s) do begin if upcase(s[i]) in ['A'..'Z'] then begin next_word := next_word + s[i]; inc(i) end else begin if next_word <> '' then t := t + replace_word(ER, next_word); t := t + s[i]; next_word := ''; inc(i); end; end;
if next_word <> '' then t := t + replace_word(ER, next_word); memo2.Lines.Add(t); end; er.free end;
hiv
7.09.2005 12:29
Цитата
но выводится какая то чуш:
Как запрограммировал - так и выводит! Вот так надо:
procedure TForm1.Button1Click(Sender: TObject); var s, next_word, next_word_rus, t: string; i: byte; currLine: integer; begin Memo2.Lines.Clear; ER:=TStringList.Create; ER.LoadFromFile('voc.txt'); for currLine := 0 to Pred(memo1.Lines.Count) do begin s := memo1.Lines.Strings[currLine]; t:=''; i := 1; next_word := ''; while i <= length(s) do begin while (i <= length(s)) and (upcase(s[i]) in ['A'..'Z']) do begin next_word := next_word + s[i]; inc(i); end; if next_word<>'' then begin next_word_rus:=ER.Values[next_word]; if next_word_rus='' then next_word_rus:=next_word; t:= t + next_word_rus; next_word := ''; end; if i <= length(s) then t:= t + s[i]; inc(i); end; Memo2.Lines.Add(t); end; ER.Free; end;
Н
8.09.2005 1:52
Как же я сам то не додумался ..... :D
hiv, volvo Огромное спасибо.... Очень выручили.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.