Подсветка с помощью цикла и SelAttributies
Есть простой код:
{
//-------------------------------------
char S1,S2,S3,S4,S5;
S1 = RichEdit1->Text;
S2 = RichEdit1->Text[i+1];
S3 = RichEdit1->Text[i+2];
if((S1=='f')&&(S2=='o')&&(S3=='r'))
{
RichEdit1->SelStart = i-1;
RichEdit1->SelLength = 3;
RichEdit1->SelAttributes->Color = clRed;
}
//-------------------------
}
данный код очень простой, который подсвечивает слово for красным цветом.
Вопрос: можно через этот способ сделать так. чтобы подсвечивалось вводимое слово, типа ввёл int и подсветился int.
Ведь char-ы должны отсюда создаваться динамически, взависимости от того, насколько длинное слово, а во вторых, что ещё сложнее, ввести их в цикл... :)
А можно не морочить себе голову, использовать AnsiString и искать подсвечиваемые слова с помощью метода AnsiString::Pos()
Есть простой код:
{
//-------------------------------------
char S1,S2,S3,S4,S5;
S1 = RichEdit1->Text;
S2 = RichEdit1->Text[i+1];
S3 = RichEdit1->Text[i+2];
if((S1=='f')&&(S2=='o')&&(S3=='r'))
{
RichEdit1->SelStart = i-1;
RichEdit1->SelLength = 3;
RichEdit1->SelAttributes->Color = clRed;
}
//-------------------------
}
данный код очень простой, который подсвечивает слово for красным цветом.
Вопрос: можно через этот способ сделать так. чтобы подсвечивалось вводимое слово, типа ввёл int и подсветился int.
Ведь char-ы должны отсюда создаваться динамически, взависимости от того, насколько длинное слово, а во вторых, что ещё сложнее, ввести их в цикл... :)
ListAnalis->Delimiter = ' ';
int counter = 0;
for(int i = 0;i < reList->Lines->Count;++i){
ListAnalis->Clear();
ListAnalis->DelimitedText = reList->Lines->Strings;
for(int j=0;j < ListAnalis->Count;++j ){
if(ListAnalis->Strings[j].Pos("for")
||ListAnalis->Strings[j].Pos("foR")
|| ListAnalis->Strings[j].Pos("For")
|| ListAnalis->Strings[j].Pos("fOr")
|| ListAnalis->Strings[j].Pos("FOR") ){
ShowMessage("O!!! Це дило! Всего найдено " + IntToStr(++counter));
}
}
}
delete ListAnalis;
Как получить, на основании этого кода, позицию в строке, я оставляю вам на самостоятельную работу. Тем более что сложного тут ничего нет - достаточно просто убрать один цикл. :)
||ListAnalis->Strings[j].Pos("foR")
ну тогда не совсем. Потому что я показал просто что данная функция зависима от регистра. А приводить скорей всего надо к нижнему регистру - если такая задача стоит.
imho, это дело вкуса -- вести вверх или вниз.
чёт с я не нахожу применения вышеуказанного каода для разных слов.
У меня получилось только для конкретного....
У меня получилось только для конкретного....
ну как бэ, имелось ввиду в качестве аргумента метода AnsiString::Pos(...) передавать переменную содержащую искомое слово
причем тут дело вкуса?
в большинстве языков команды fOr нет. И команды FOR тоже.
чёт с я не нахожу применения вышеуказанного каода для разных слов.
и что теперь?
следовательно, данный метод не эффективен и не подходит... :)
Введи переменную (или набор переменных) для хранения состояния и буфер, для хранения текущей лексемы.
Инициализируй переменные состояния перед перебором текста.
Перебирай текст посимвольно, обрабатывай его в зависимости от переменных состояний и меняй сами эти состояния и содержимое буфера.
Ну а если синтаксис того, для чего делаешь подсветку, позволяет это сделать разбиением по пробельным символам, то и Delemited подойдет.
Введи переменную (или набор переменных) для хранения состояния и буфер, для хранения текущей лексемы.
Инициализируй переменные состояния перед перебором текста.
Перебирай текст посимвольно, обрабатывай его в зависимости от переменных состояний и меняй сами эти состояния и содержимое буфера.
Ну а если синтаксис того, для чего делаешь подсветку, позволяет это сделать разбиением по пробельным символам, то и Delemited подойдет.
естественно что без использования переменных состояния тут не обойтись - но перебор тут абсолютно не нужен. в моем коде он присутсвует только для организации входящего потока - а все что нужно - контейнер зарезервированных слов и множество по которым можно судить о окончании ввода лексемы (пробел, точка с запятой и пр.). Можно так же и его оформить в контейнер, можно множеством - не суть важно. Контейнер позволит гибче работать - зато множество быстрее.
и что теперь? (c) kot_
В исходнике проверяется и на foR, и на FOR. Следовательно, в нём декларируется необходимость проверки Case-Insensitive, и, понятно, чем все комбинации регистров проверять, лучше к одному регистру привести. С точки зрения работы программы, абсолютно по барабану, ListAnalis->Strings[j].UpperCase().Pos("FOR"); или ListAnalis->Strings[j].LowerCase().Pos("for");
Я тоже показал. Наличием метода UpperCase(). А ещё в C++ Builder есть Help, в котором вопрошающий может узнать подробности работы AnsiString::Pos().
PS. Извиняюсь за оффтоп.
PPS. Basic, Pascal, PL/SQL -- Case-Insensitive, там могут быть и for, и FOR и любые комбинации регистров (если вдруг программист захочет так оригинально оформить программу).
А можно как нубудь, как я просил...??
или прийдётся проверять с помощью if каждое
int,long,char и т.п. и отдельно подстраивать код к каждому коду??
:confused:
В исходнике проверяется и на foR, и на FOR. Следовательно, в нём декларируется необходимость проверки Case-Insensitive, и, понятно, чем все комбинации регистров проверять, лучше к одному регистру привести. С точки зрения работы программы, абсолютно по барабану, ListAnalis->Strings[j].UpperCase().Pos("FOR"); или ListAnalis->Strings[j].LowerCase().Pos("for");
Ну и чего ты взъелся?
Еще раз повторяю - это отнюдь не "это дело вкуса", как ты выразился. А определяется языком для которого проводится лексический анализ. В чем я не прав? И кстати конструкции типа ListAnalis->Strings[j].UpperCase().Pos... я предпочел бы
String tmp = ListAnalis->Strings[j].UpperCase();
if(tmp.Pos(... - а еще лучше в блоке подсветки этого не делать - вообще - как бы не соблазнительным это казалось. Если пользователь набрал fOr - то он набрал именно fOr. И если данная лексема не отнесена явно к тем которые надо выделять - то не нужно додумывать за пользователя. Задача подсветки - это задача подсветки а не подсветки и корректировки ввода. Если присутсвует функция корректировки - это ее задача. В данном фрагменте мы должны проверить только не входит ли лексема в пространство заданных - а не модифицировать ввод пользователя. ИМХО.
А можно как нубудь, как я просил...??
можно. могу выдать еще один бан.
Что не понятно? Все что нужно тебе - уже сказано. Остальное делаешь сам.
В том, что в случае Case-Insensitive подсветки не всё равно, к какому регистру приводить. Остальные слова -- увод от темы.
ни к какому не нужно. надо проверять те словоформы которые есть. Не нужно за пользователя додумывать - что он ввел. Даже если решение кажется удобным. По крайней мере не нужно смешивать в кучу корректировку и анализ.
---
А хотя, вот глаза шире открыл. Согласен со всеми, с учетом вновь замеченных оговорок. =)
[quote=Plisteron]...В исходнике проверяется и на foR, и на FOR. Следовательно, в нём декларируется необходимость проверки Case-Insensitive...[/quote]
А можно как нубудь, как я просил...??
или прийдётся проверять с помощью if каждое
int,long,char и т.п. и отдельно подстраивать код к каждому коду??
:confused:
Не плачь.
AnsiString colon(" : ");
TStrings *LightLines = memText->Lines;
TStrings *Words = listboxWords->Items;
int LinesCount = LightLines->Count;
int WordsCount = Words->Count;
int LineWidth;
int i;
int j;
int PosBegin;
int PosEnd;
int wLenght;
AnsiString s;
AnsiString w0rd;
AnsiString wTest;
for (j = 0; j < LinesCount; j++)
{
s = LightLines->Strings[j];
LineWidth = s.Length();
PosBegin = 1;
while (PosBegin <= LineWidth)
{
for (i = 0; i < WordsCount && LineWidth; i++)
{
w0rd = Words->Strings;
wLenght = w0rd.Length();
if(wLenght > LineWidth)
continue;
PosEnd = PosBegin + wLenght - 1;
wTest = s.SubString(PosBegin, wLenght);
if ( (wTest == w0rd) &&
(PosEnd >= LineWidth || Separators.Pos(s[PosEnd])) )
{
// Нашли!
memPos->Lines->Add(AnsiString(j) + colon + w0rd + colon + AnsiString(PosBegin) + colon + AnsiString(wLenght));
}
} // <<< for (i = 0; i < WordsCount && LineWidth; i++)
PosBegin++;
} // <<< while (PosBegin <= LineWidth)
} // <<< for (j = 0; j < LinesCount; j++)
listboxWords -- листбокс со словами, которые нужно подстветить в тексте
memPos -- Memo, в которое я складываю найденные позиции подлежащих подсветке слов
Особо код на ошибки не тестировал, знаю только, что он компилируется.
:)) :))
String tmp = ListAnalis->Strings[j].UpperCase();
if(tmp.Pos(... - а еще лучше в блоке подсветки этого не делать - вообще - как бы не соблазнительным это казалось. Если пользователь набрал fOr - то он набрал именно fOr.