![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | 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.
По поводу скобок тут сложнее. При обнаружении скобки надо найти закрывающую к ней и сделать рекурсивный вызов на содержимое скобок. Если хочешь, за это можем уже поговорить отдельно, если сам не справишься. |