C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Поиск текста в Memo, Каким образом осуществляется поиск?
dEEp
  Отправлено: 27.02.2005, 19:44


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Здраствуйте. Подскажите мне...

На форме расположено Memo в котором есть текст.
А также кнопка.
Имеется массив слов...
Например,
CODE
AnsiString w0rds[3]={"help", "your", "send"};


Необходимо, чтобы при клике по кнопке в строке выделилось слово, а именно w0rds[1]. Кликаешь ещё раз и уже в следующей строке (или в этой же) выделяется слово w0rds[2].
Это необходимо для того, чтобы пользователь обратил внимание на выделенное слово.

Вот пример...

Дан текст (английским владею плохо):

Hi! My name is Alexander. You can help me?
What your name?
Please, send me...


User кликает по кнопке и выделяется слово "help", затем кликает ещё раз и выделяется "your", затем ещё раз и уже слово "send". Маленький дополнение Кникаешь ещё раз и опять выделяется первое слово — "help". То есть цикл получается. Понятно? Дело в том, что я пишу программу по изучению английского языка (переводчик (человек) имеется, а то я его плохо знаю). Кто может — помогите. Как всё это реализовать?
Aptem
Отправлено: 28.02.2005, 06:26


Мастер участка

Группа: Участник
Сообщений: 349



Поиск делается очень просто, у класса AnsiString есть методы: Pos и SubString. Вот их и используй!
dEEp
Отправлено: 28.02.2005, 08:26


Дежурный стрелочник

Группа: Участник
Сообщений: 69



В принципе я разобрался.
Слово нахожу, а вот выделить его проблемно.
Вот кусок кода...

CODE

AnsiString w0rds[6]={"gets up", "go to home", "hi", "oh", "very", "work"};
AnsiString Str;
int c0unt=Memo1->Lines->Count;
int Positi0n;
for (int i=0; i<=c0unt; i++)
    {
      if  (Memo1->Lines->Text.AnsiPos(w0rds[1]))
          {
            Str=Memo1->Lines->Strings[i];
            int temp=w0rds[0].Length();
            Positi0n=Str.Pos(w0rds[0]);  
            if (Positi0n>0)
               {
                 Memo1->SelStart=Positi0n;
                 Memo1->SelLength=temp;
//              Memo2->Text=Positi0n;      - нужно было для проверки
               }
          }
    }


Естественно код не доделан. Пока что он ищет только одно слово. А вот что с выделением? Я не знаю как выделить найденное слово. Есть ли простой способ? Хотя давайте любой...

Кстати, Aptem, ты уже не первый раз помогаешь! Выражаю благодарность!
Жду ответов...
Приеду с учёбы (после 19:00) посмотрю. Надеюсь на помощь...
Konstantine
Отправлено: 28.02.2005, 09:21


Мастер участка

Группа: Модератор
Сообщений: 545



Выделяет... просто по default у Memo свойство HideSelection установлено в true, а оно означает — скрывать выделение при неактивном контроле, поэтому чтоб увидеть выделение нужно:
1) сделать Memo1 активным, т.е. после назначения выделения вставить
CODE
 ActiveControl=Memo1;

2) установить HideSelection в false, это можно сделать и через инспектора обьектов;

а ещё лучше — сделать и то и другое, т.к. при неактивном контроле выделение другое по цвету (у меня станд.схема XP — в активном — тёмно-синее, а при неактивном — серое)
dEEp
Отправлено: 28.02.2005, 12:39


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Костя, чего-то я плохо понял. Подробнее можешь?
Konstantine
Отправлено: 28.02.2005, 15:30


Мастер участка

Группа: Модератор
Сообщений: 545



в инспекторе обьектов для обьекта Memo1 установи HideSelection в false... для этого:
1) не запуская программу выдели на форме Memo1;
2) обычно справа от формы имеется инспектор обьектов (Object Inspector) если нету — то включи отображение через меню View;
3) в этом инспекторе открыть вкладку Properties;
4) найти св-во HideSelection и установи его в false;

в коде после строк
CODE
                Memo1->SelStart=Positi0n;
                Memo1->SelLength=temp;
добавь строку
CODE
ActiveControl=Memo1;


если чего-то неясно — уточни где именно...
dEEp
Отправлено: 28.02.2005, 19:38


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Я не понял, что мне это даёт.
Он итак выделяет. Проблема со строкой. То есть в какой строке что
выделить...
Bond
Отправлено: 28.02.2005, 19:54


Станционный диспетчер

Группа: Участник
Сообщений: 142



идешь по мемо, ищешь абсолютную позицию нужного слова, задаешь
Memo1->SelStart = AbsOffset;
Memo1->SelLength = WordLength;
dEEp
Отправлено: 01.03.2005, 02:34


Дежурный стрелочник

Группа: Участник
Сообщений: 69



QUOTE (Bond @ 28/02/2005, 19:54)
идешь по мемо, ищешь абсолютную позицию нужного слова, задаешь
Memo1->SelStart = AbsOffset;
Memo1->SelLength = WordLength;

Ничего не понял...
Bond
Отправлено: 01.03.2005, 11:01


Станционный диспетчер

Группа: Участник
Сообщений: 142



Свойства класса TMemo SelStart и SelLength — это переменные, которые задают первый символ отмеченного текста и длину отмеченного текста в символах соответственно.
Эти свойства не работают со строками, они работают со всем текстовым буфером класса TMemo. Например в TMemo есть следующие строки:
------------------------------------
1
234
567890
------------------------------------
и нам необходимо выделить 89.
Подсчитаем абсолютное смещение относительно буфера (не забываем что нужно учитывать символ переноса строки "\n"):
CODE
Memo1->SelStart =
strlen( "1 " ) + 1 +
strlen( "234" ) + 1 +
strlen( "567") = 9
и считаем длину отмеченного текста:
CODE
Memo1->SelLength = strlen( "89" ) = 2
Bond
Отправлено: 01.03.2005, 11:03


Станционный диспетчер

Группа: Участник
Сообщений: 142



Извини, тут нужно к длине каждой строки прибавлять не единицу, 2
dEEp
Отправлено: 01.03.2005, 16:35


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Большое спасибо. В принципе я понял. Сегодня вечером попробую, а ночью напишу ответ. Так что ждите. Уверен, что ваша помощь мне ещё понадобится.
dEEp
  Отправлено: 05.03.2005, 14:15


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Всё получилось! Сделал! Работает! Спасибо всем!
*.exe я присоединить не смог — ругается сервер.
Протестируйте пожалуйста. Увидете глюки — пишите
Вот исходник. В библиотеке объявлен int flag.

CODE

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

#include <vcl.h>
#pragma hdrstop

#include "Main.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int flag2=0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
{
       Application->Terminate();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
{
       int c0unt=Memo1->Lines->Count;
       if (flag2>0)
               {
                       flag++;
               }
       if (flag>7)
               {
                       flag=0;
               }
       flag2=1;
       Memo2->Text=flag;
       for (int i=0; i<=c0unt; i++)
               {
                 switch (flag)
                       {
                         case (0): {
                                          Memo1->SelStart=68;
                                          Memo1->SelLength=strlen("gets up");
                                          Edit1->Text="gets up — вставать";
                                        } break;

                        case (1): {
                                         Memo1->SelStart=183;
                              Memo1->SelLength=strlen("gets the breakfast ready");
                              Edit1->Text="gets the breakfast ready — завтракать";
                                       } break;

                        case (2): {
                                         Memo1->SelStart=219;
                              Memo1->SelLength=strlen("gets washed");
                              Edit1->Text="gets washed — умываться";
                                       } break;

                        case (3): {
                                         Memo1->SelStart=244;
                              Memo1->SelLength=strlen("gets dressed");
                              Edit1->Text="gets dressed — одеваться";
                                      } break;

                       case (4): {
                                       Memo1->SelStart=461;
                                       Memo1->SelLength=strlen("gets ready");
                                       Edit1->Text="gets ready — готовиться";
                                      } break;

                      case (5): {
                                       Memo1->SelStart=695;
                                       Memo1->SelLength=strlen("In the evening");
                                       Edit1->Text="In the evening — вечером";
                                     } break;

                      case (6): {
                                       Memo1->SelStart=980;
                                       Memo1->SelLength=strlen("newspaper");
                                       Edit1->Text="newspaper — газета";
                                     } break;

                      case (7): {
                                      Memo1->SelStart=1323;
                                      Memo1->SelLength=strlen("get undressed");
                                      Edit1->Text="get undressed — раздеваться";
                                      flag=0;   // f0r go to begin text...
                                      flag2=0;
                                    } break;
                               }
                       break;
               }
}
//---------------------------------------------------------------------------


void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
       int c0unt=Memo1->Lines->Count;
       if (flag2>0)
               {
                       flag--;
               }
       if (flag<0)
               {
                       flag=7;
               }
       flag2=1;
       Memo2->Text=flag;
       for (int i=0; i<=c0unt; i++)
               {
                 switch (flag)
                     {
                      case (0): {
                                      Memo1->SelStart=68;
                                      Memo1->SelLength=strlen("gets up");
                                      Edit1->Text="gets up — вставать";
                                      flag=7;
                                      flag2=0;
                                    } break;

                     case (1): {
                                     Memo1->SelStart=183;
                               Memo1->SelLength=strlen("gets the breakfast ready");
                               Edit1->Text="gets the breakfast ready — завтракать";
                                    } break;

                     case (2): {
                                      Memo1->SelStart=219;
                                      Memo1->SelLength=strlen("gets washed");
                                      Edit1->Text="gets washed — умываться";
                                    } break;

                     case (3): {
                                      Memo1->SelStart=244;
                                      Memo1->SelLength=strlen("gets dressed");
                                      Edit1->Text="gets dressed — одеваться";
                                    } break;
 
                     case (4): {
                                      Memo1->SelStart=461;
                                      Memo1->SelLength=strlen("gets ready");
                                      Edit1->Text="gets ready — готовиться";
                                    } break;
 
                     case (5): {
                                      Memo1->SelStart=695;
                                      Memo1->SelLength=strlen("In the evening");
                                      Edit1->Text="In the evening — вечером";
                                    } break;
 
                     case (6): {
                                      Memo1->SelStart=980;
                                      Memo1->SelLength=strlen("newspaper");
                                      Edit1->Text="newspaper — газета";
                                    } break;

                     case (7): {
                                      Memo1->SelStart=1323;
                                      Memo1->SelLength=strlen("get undressed");
                                      Edit1->Text="get undressed — раздеваться";
                                    } break;
                               }
                       break;
               }
}
//---------------------------------------------------------------------------


Вот такой вод код. Теперь объясняю...
1. flag — это, по сути дела, индекс слова.
2. flag2 — с помощью его проверяем нажатие кнопок.

Остальное всё должно быть понятно. Вот только проблемка...
В моей программе выделение слова происходит путём назначения номера символа с которого нужно выделять. Так вот теперь мне нужно переписать эту программу так, чтобы поиск по словам происходил. Т.е. так, как я описывал раньше.
Мысли есть? Пишите... ночью посмотрю....
dEEp
Отправлено: 05.03.2005, 14:29


Дежурный стрелочник

Группа: Участник
Сообщений: 69



ScreenShot

Присоединить изображение

Присоединить изображение

Bond
Отправлено: 05.03.2005, 15:25


Станционный диспетчер

Группа: Участник
Сообщений: 142



в Unit1.cpp
CODE
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
       : TForm(Owner)
{
       ComboBox1->ItemIndex = 0;
       LastFind = 0;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
       AnsiString text = Memo1->Lines->Text;
       AnsiString subString = text.SubString( LastFind+1, text.Length() );
       int result = subString.Pos( ComboBox1->Text );
       if( result > 0 )
       {
               Memo1->SelStart = LastFind + result — 1; Memo1->SelLength = ComboBox1->Text.Length();
               LastFind += result;
       }
       else
       {
               LastFind = 0;
               Memo1->SelLength = 0;
               result =
                       MessageBox(NULL,"Слово не найдено. Начать с начала текста?","Поиск",MB_YESNOCANCEL);
               switch( result )
               {
                       case IDNO:
                               if( ComboBox1->ItemIndex < ComboBox1->Items->Count-1 ) ComboBox1->ItemIndex++;
                               else ComboBox1->ItemIndex = 0;
                               Button1Click(Sender);
                               break;
                       case IDYES:
                               Button1Click(Sender);
                               break;
               }
       }
}


в Unit1.h
CODE
int LastFind;
dEEp
  Отправлено: 05.03.2005, 20:17


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Не могли бы Вы вкратце раъяснить?
dEEp
Отправлено: 05.03.2005, 20:49


Дежурный стрелочник

Группа: Участник
Сообщений: 69



До меня "дошло". Попытаюсь внедрить в свой код...
dEEp
Отправлено: 06.03.2005, 10:47


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Каким образом можно добавить слово в массив искомых слов.
Т.е. есть массив слов, которые мы ищем в Memo, а вдруг приспичило добавить туда ещё
одно или несколько слов. Что тогда? Как лдобавить в массив. Было бы хорошо, чтобы при следующем запуске
был уже новый массив (с добавленным словом). Я предполагаю, что можно сделать
файл, в котором будут храниться искомые слова. А если приспичит, то тогда открываем файл
и дописываем туда слово (всё это делать не в ручную, а с помощью Edit'ов и Button'ов). Так?
Или есть способ получше?

Присоединить изображение

Присоединить изображение

GIZMO
Отправлено: 09.03.2005, 10:27


Машинист паровоза

Группа: Участник
Сообщений: 174



QUOTE (dEEp @ 06/03/2005, 10:47)
Каким образом можно добавить слово в массив искомых слов.
Т.е. есть массив слов, которые мы ищем в Memo, а вдруг приспичило добавить туда ещё
одно или несколько слов. Что тогда? Как лдобавить в массив. Было бы хорошо, чтобы при следующем запуске
был уже новый массив (с добавленным словом). Я предполагаю, что можно сделать
файл, в котором будут храниться искомые слова. А если приспичит, то тогда открываем файл
и дописываем туда слово (всё это делать не в ручную, а с помощью Edit'ов и Button'ов). Так?
Или есть способ получше?

TStringList — 4 your...
CODE

//in hp
private:
  TStringList* sl
//in cpp
__fastcall TForm1::TForm1(TComponent* Owner)
      : TForm(Owner)
{
  sl = new TStringList();
  sl->LoadFromFile("filename.txt");
}
void __fastcall TForm1::Edit1Exit(TObject *Sender)
{
   if(sl->IndexOf(Ediit1->Text) == -1)
           sl->Add(Edit1->Text);
}
__fastcall TForm1::~TForm1()
      : TForm(Owner)
{
  sl->SaveToFile("filename.txt");
  delete sl;
}


Bond
Отправлено: 09.03.2005, 11:37


Станционный диспетчер

Группа: Участник
Сообщений: 142



Можешь добавить кнопочку "Back". Для этого необходимо:
- при нахождении слова добавлять в список а) искомое слово; б) позицию слова в тексте и BackButton->Enabled = false;
- [B]при редактировании текста список обнулять, BackButton->Enabled = false;
Bond
Отправлено: 09.03.2005, 11:40


Станционный диспетчер

Группа: Участник
Сообщений: 142



Извините, допустил ошибки cool.gif .
Можешь добавить кнопочку "Back". Для этого необходимо:
- при нахождении слова добавлять в список а) искомое слово; б) позицию слова в тексте и BackButton->Enabled = true;
- при редактировании текста список обнулять, BackButton->Enabled = false;
Bond
Отправлено: 09.03.2005, 12:51


Станционный диспетчер

Группа: Участник
Сообщений: 142



P.S.
- при нажатии клавиши "Back" контролировать начало списка: если уже некуда "Бэкать" — BackButton->Enabled = false;
dEEp
Отправлено: 10.03.2005, 17:28


Дежурный стрелочник

Группа: Участник
Сообщений: 69



Это я уже реализовал.
telepath
Отправлено: 10.03.2005, 17:38


Станционный диспетчер

Группа: Участник
Сообщений: 132



Странная конструкция...
CODE
switch(/*----*/)
{
case 0:
{
/*---------*/
} break;
}


не будет ли тут ошибочки?

Отредактировано telepath — 10/03/2005, 17:39
Bond
Отправлено: 10.03.2005, 18:04


Станционный диспетчер

Группа: Участник
Сообщений: 142



Это простые операторные скобки, которые объединяют несколько операторов. Никакой ошибки не будет

Вернуться в Вопросы программирования в C++Builder