![]() |
|
|
Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
Опции темы | Поиск в этой теме | Опции просмотра |
#1
|
|||
|
|||
![]() Здравствуйте уважаемые программисты! У меня такя проблемма: мне нужно считать из memo набор символов, затем распознать эти симфолы, т.е. если в memo написано HSO2, то нужно чтобы программа распознала каждый из этих символов отдельно и присвоила каждому из этих символов соответствующие значения например: H:=3, S:=7, O:=1*2. Подскажите пожалуста как можно это осуществить в виде кода?!
|
#2
|
|||
|
|||
![]() case ставишь, и каждый символ проверяешь...
|
#3
|
|||
|
|||
![]() Во первых, тебе надо иметь константный массив соответсвия символов значениям. Во вторых, надо писать парсер, который разбирает выражение и с помощью соотв. массива возвращает тебе твои циферки.
Ты не написал что надо делать с этими цифрами (куда их "складывать"). Для твоего примера будет где-то так: Код:
type TVal = record Letter : String; Value : Integer; end; const Vals : Array [1..3] Of TVal = ((Letter:'H'; Value:3),(Letter:'S'; Value:7),(Letter:'O'; Value:1)); function GetValue(ALetter : String) : Integer; var I : Integer; begin Result := -1; For I := 1 To 3 Do If Vals[i].Letter = ALetter Then Begin Result := Vals[i].Value; Break; End; end; function Parse(AText : String) : String; var I : Integer; Buf : String; V : Integer; begin Result := ''; I := 1; While I <= Length(AText) Do Begin // Получить хим элемент. If Not (AText[i] In ['A'..'Z']) Then Raise Exception.CreateFmt('Ошибка в формуле в позиции %d',[i]); Buf := AText[i]; If AText[I+1] In ['a'..'z'] Then Begin Inc(I); Buf := Buf + AText[i]; End; V := GetValue(Buf); If V = -1 Then Raise Exception.CreateFmt('Введенный хим элемент не найден (%s)',[Buf]); Result := Result + IntToStr(V); Inc(I); // Проверяем на цифру Buf := ''; While AText[i] In ['0'..'9'] Do Begin Buf := Buf + AText[i]; Inc(I); End; If Buf <> '' Then Result := Result + '*' + Buf; Result := Result + ' - '; End; end; procedure TForm1.Button1Click(Sender: TObject); begin Edit2.Text := Parse(Edit1.Text); end; Код понимает "правильное" написание химэлементов (первая буква большая, вторая, если есть, маленькая) и цифры. Цифра не может идти первой. Результат выводит в виде строки. Для увеличения поддерживаемых элементов надо "добить" их в константный массив в соотв. виде и скорректировать цикл в функции GetValue. |
#4
|
|||
|
|||
![]() Да, скобки не поддерживаютя.
|
#5
|
|||
|
|||
![]() Спасибо Вам огромное! А как можно вывести в Edit2 конечное число, т.е. уже результат расчета? И будет ли все работать если значения элементов будут не целыми числами?Заранее премного благодарен за исчерпывающий ответ!
|
#6
|
|||
|
|||
![]() Да, можно.
Ты же не написал что надо делать с этими числами. Просто сложить? Тогда там надо немного переделать функцию Parse. Изменения: Код:
function Parse(AText : String) : Integer; var I : Integer; Buf : String; V : Integer; begin Result := 0; I := 1; While I <= Length(AText) Do Begin // Получить хим элемент. If Not (AText[i] In ['A'..'Z']) Then Raise Exception.CreateFmt('Ошибка в формуле в позиции %d',[i]); Buf := AText[i]; If AText[I+1] In ['a'..'z'] Then Begin Inc(I); Buf := Buf + AText[i]; End; V := GetValue(Buf); If V = -1 Then Raise Exception.CreateFmt('Введенный хим элемент не найден (%s)',[Buf]); Inc(I); // Проверяем на цифру Buf := ''; While AText[i] In ['0'..'9'] Do Begin Buf := Buf + AText[i]; Inc(I); End; If Buf <> '' Then V := V * StrToInt(Buf); Result := Result + V End; end; procedure TForm1.Button1Click(Sender: TObject); begin Edit2.Text := IntToStr(Parse(Edit1.Text)); end; С дробными числами где? В формуле - ну можно, но муторно. В весах элементов - можно. А зачем? Вроде атомные веса всегда считают приблизительно целыми. |
#7
|
|||
|
|||
![]() Спасибо большое! Атомные веса действительно считаются, чаще всего, целыми числами, как например в школе считали, но во-первых для некоторых элементов, таких как Cu(Mr=63.5) и Cl (Mr=35.5) не допускается округление, А вообще для более точных расчетов пользуются атомными весами с двумя значащими цифрами после запятой.
А не скажете как быть со скобками? очень бы хотелось сделать модуль к моей программе по-универсальнее! Очень Вам благодарен!!! |
#8
|
|||
|
|||
![]() Перевод на дробные - вместо Integer надо указать Double везде, где это надо. Все. В проверочном вызове надо использовать FloatToStr.
По поводу скобок тут сложнее. При обнаружении скобки надо найти закрывающую к ней и сделать рекурсивный вызов на содержимое скобок. Если хочешь, за это можем уже поговорить отдельно, если сам не справишься. |
#9
|
|||
|
|||
![]() Спасибо, все исправил где надо, вроде нормально работает, а вот на счет скобок пока еще не думал, но сделать так чтобы со скобкеня к Ваами работал надо. У меня к вам еще маленький вопросик: как в memo поставить нижний индекс в строке?
|
#10
|
|||
|
|||
![]() Никак. Мемо такого не поддерживает.
|
#11
|
|||
|
|||
![]() а в edite можно это сделать, или еще в каком-нибудь компоненте?
|
#12
|
|||
|
|||
![]() Можно попробовать в TRichEdit. просто для цифры выставлять маленький шрифт.
|
#13
|
|||
|
|||
![]() При выставлении меньшего шрифта все становится меньше
|
#14
|
|||
|
|||
![]() Как писал выше lmikle вместь Мемо юзаешь RichEdit
Код:
RichEdit1.SelStart := ; // начальная позиция RichEdit1.SelLength := ; // число символов RichEdit1.SelAttributes.Size := ; // новая высота шрифта Если не изменяет память, тот там какимто образом необходимо менять еще параметр Height |