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

 
Алгоритм анализа, как написать?
Лена
Отправлено: 22.02.2007, 16:10


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

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



Подскажите, как реализовать следующий алгоритм:
На форме есть 10 штук компонента Edit. Пользователь может ввести в эти окна в произвольном порядке следующие значения: int, short, double, VARIANT, BSTR, bool, long плюс значения (см. рисунок).
Мне нужен алгоритм, который, проанализировав ввод пользователя, определил, сколько параметров заполнил пользователь и какие они имею значения.
Например, пользователь написал в первом поле int 2, а во втором bool false. Алгоритм, проанализировав строки, дает понять, что в функцию надо передать цифру 2 и значение false.
Помогите написать такой алгоритм анализа ввода. Я его уже реализовала, но это получился километр кода с огромным кол-вом операторов if. Очень не красиво. sad.gif А если добавить еще один Edit то вообще получиться два километра кода. smile.gif


Ниже фрагмент моего кода где анализируется ситуация если пользователь заполнил только один Edit. Анализировать этот код не надо — он правильный, но такой подход порождает километр кода за ним. smile.gif
Подскажите, как сделать красиво?


CODE

//три строки ниже определены в другом месте
//AnsiString Types[10];
//AnsiString P1Znachenie[10]; содержит значение за типом
//AnsiString ALLParamsR; определено в другом месте
//GetPropWord анализируется в другом месте программы

//анализ если введено значение только в первый Edit
//главное понять, что написал пользователь и занести это в Variant par1;

case 1:
{
Variant par1;
//bool
if(Types[0] == "bool" || Types[0] == "BOOL")
{
if (P1Znachenie[0] == "1" || P1Znachenie[0] == "TRUE" || P1Znachenie[0] == "true")
{
bool v = true;
Variant varS;
varS.vt = VT_BOOL;
varS.iVal = v;
par1 = varS;
}
if (P1Znachenie[0] == "0" || P1Znachenie[0] == "FALSE" || P1Znachenie[0] == "false")
{
bool v = false;
Variant varS;
varS.vt = VT_BOOL;
varS.iVal = v;
par1 = varS;
}
}
if(Types[0] == "short" || Types[0] == "SHORT")
{
short newpar1 = P1Znachenie[0].ToInt();
Variant varS;
varS.vt = VT_I2;
varS.iVal = newpar1;
par1 = varS;

}
if(Types[0] == "long" || Types[0] == "LONG")
{
long newpar1 = P1Znachenie[0].ToDouble();
Variant varS;
varS.vt = VT_I4;
varS.lVal = newpar1;
par1 = varS;

}
if(Types[0] == "double" || Types[0] == "DOUBLE")
{
double newpar1 = P1Znachenie[0].ToDouble();
Variant varS;
varS.vt = VT_R8;
varS.dblVal = newpar1;
par1 = varS;

}
if(Types[0] == "int" || Types[0] == "INT")
{
int newpar1 = P1Znachenie[0].ToInt();
Variant varS;
varS.vt = VT_INT;
varS.intVal = newpar1;
par1 = varS;

}
if(Types[0] == "float" || Types[0] == "FLOAT")
{
float newpar1 = P1Znachenie[0].ToDouble();
Variant varS;
varS.vt = VT_R4;
varS.fltVal = newpar1;
par1 = varS;

}
if(Types[0] == "bstr" || Types[0] == "BSTR")
{

BSTR x = SysAllocString(WideString(P1Znachenie[0]).c_bstr());
Variant varS;
varS.vt = VT_BSTR;
varS.bstrVal = x;
par1 = varS;
SysFreeString(x);

}

//для Variant
if(Types[0] == "VARIANT")
{
par1 = P1Znachenie[0];
}
//именно сюда надо передать то, что нужно из окна edit
TAutoArgs<1> args;
args[1] = par1; //здесь главное!!!

try{

if(ALLParamsR == "void" || ALLParamsR == "void*")
{
if(GetPropWord == "PROPERTYPUT")
Form1->OleContainer1->OleObject.OlePropertySet(NFunck,static_cast<TAutoArgsBase&>(args));
if(GetPropWord == "PROPERTYGET")
Form1->OleContainer1->OleObject.OlePropertyGet(NFunck,static_cast<TAutoArgsBase*>(&args));
if(GetPropWord == "FUNC")
Form1->OleContainer1->OleObject.OleFunction(NFunck,static_cast<TAutoArgsBase*>(&args));
}
else
{

Variant X;
if(GetPropWord == "PROPERTYGET")
X = Form1->OleContainer1->OleObject.OlePropertyGet(NFunck,static_cast<TAutoArgsBase*>(&args));
if(GetPropWord == "FUNC")
X = Form1->OleContainer1->OleObject.OleFunction(NFunck,static_cast<TAutoArgsBase*>(&args));
Form1->Edit2->Text = X;


}
}
catch(...) {
ShowMessage("Не удалось вызвать функцию c параметрами " + NFunck);
return;
}
//return;
//конец одного параметра;

break; }

//далее километр из других case…
//для двух, трех и т.д. edit-ов.



Отредактировано Лена — 22.02.2007, 16:13

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

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

AVC
Отправлено: 22.02.2007, 16:29


Ветеран

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



Я вижу только перебор и аналаз первого и второго слова
Примерная схема может быть такая
.Проход по всем едитам
.. для каждого из едит
... функция анализа Text
.... trim, попытка получить два слова, каждое trim
.... нет двух -> элемент не заполнен
.... анализ первого слова на элемент множества {int, double ...} привести к Upper или Lower — меньше проверок
.... не попали -> элемент не заполнен
.... попытка привести второе к типу первого
.... не получилось -> элемент не заполнен
.... добавляем в массив типа вариантов код типа и значение
.... конец анализа

Что бы не было километров — нужна отдельная функция анализа у которой на входе либо Edit либо AnsiString и функция которая преобразует строку символов к значению нужного типа или дает ошибку (на подобии As... у класса Field).
Editы можно собрать в массив
Если подцепить анализ на, допустим, потерю фокуса едитом то можно проверять "на лету".
Лена
Отправлено: 22.02.2007, 16:42


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

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



QUOTE (AVC @ 22.02.2007, 16:29)
Editы можно собрать в массив
Если подцепить анализ на, допустим, потерю фокуса едитом то можно проверять "на лету".

Можно подробнее об этом варианте?
Анализ начинается при нажатии кнопки. Анализирую строки в edita-x (тип и значение введенное пользователем — функции работы со строками). На выходе километр кода. sad.gif

Отредактировано Лена — 22.02.2007, 16:42
AVC
Отправлено: 22.02.2007, 17:16


Ветеран

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



Editы можно собрать в массив
CODE

TEdit *oarr[] = {Edit1,...,Editn};
очитска приемника (массив вариантов?)
for (int i(0); i < (sizeof(earr) / sizeof(TEdit*)); i++)
   проверка_содержимого(earr[i]->Text, приемник);

правильно_заполнено_эдитов = число_элементов приемника

beginner
Отправлено: 22.02.2007, 18:27


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

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



QUOTE (Лена @ 22.02.2007, 16:42)
QUOTE (AVC @ 22.02.2007, 16:29)
Editы можно собрать в массив
Если подцепить анализ на, допустим, потерю фокуса едитом то можно проверять "на лету".

Можно подробнее об этом варианте?
Анализ начинается при нажатии кнопки. Анализирую строки в edita-x (тип и значение введенное пользователем — функции работы со строками). На выходе километр кода. sad.gif

Немношко подкорректировал код, как минимум компилится
CODE

// Переменная формы:
TEdit *m_edits[10];

// И скорей всего в OnCreate событии формы написать:
 m_edits[0] = Edit1;
 m_edits[1] = Edit2;
...
 m_edits[9] = Edit10;


Variant vars[10];
int var_cnt = 0;
Variant var;
bool bErr = false;
for(int i=0; i<10; i++)
{
 AnsiString Str = m_edits[i]->Text.Trim().UpperCase();
 int pos = Str.Pos(" ");
 if(pos > 0)
 {
   AnsiString type = Str.SubString(1, pos-1);
   AnsiString value = Str.SubString(pos+1, 1000).Trim();
   if(type=="BOOL")
   {
     bool v = (value=="0"||value=="FALSE");
     var.vt = VT_BOOL;
     var.iVal = v;
     vars[var_cnt++] = var;
   }
   else if(type=="SHORT")
   {
     short newpar1 = value.ToInt();
     var.vt = VT_I2;
     var.iVal = newpar1;
     vars[var_cnt++] = var;
   }
   else if(type=="LONG")
   {
     long newpar1 = value.ToDouble();
     var.vt = VT_I4;
     var.lVal = newpar1;
     vars[var_cnt++] = var;
   }
   else if(type=="DOUBLE")
   {
     double newpar1 = value.ToDouble();
     var.vt = VT_R8;
     var.dblVal = newpar1;
     vars[var_cnt++] = var;
   }
   else if(type=="INT")
   {
     int newpar1 = value.ToInt();
     var.vt = VT_INT;
     var.intVal = newpar1;
     vars[var_cnt++] = var;
   }
   else if(type=="FLOAT")
   {
     float newpar1 = value.ToDouble();
     var.vt = VT_R4;
     var.fltVal = newpar1;
     vars[var_cnt++] = var;
   }
   else  if(type=="BSTR")
   {
     BSTR x = SysAllocString(WideString(value).c_bstr());
     var.vt = VT_BSTR;
     var.bstrVal = x;
     vars[var_cnt++] = var;
     SysFreeString(x);
   }
   else if(type=="VARIANT")
   {
     vars[var_cnt++] = value;
   }
   else
   {
     bErr = true;
     ShowMessage("В edit введены неправильные параметры");
     m_edits[i]->SetFocus();
     break;
   }
 }
 else
   break; // Выход из цикла, если текущий edit не содержит параметров
}
//именно сюда надо передать то, что нужно из окна edit
if(var_cnt>0 && !bErr)
{
 // ЗДЕСЬ НАЧИНАЮТСЯ ПРОБЛЕМЫ, ТАК КАК
 // В TAutoArgs ПАРАМЕР МОЖЕТ БЫТЬ ТОЛЬКО ЧИСЛОМ.
 // Т.е. или сase с 10 вариантами или ... ?
 TAutoArgs<1> args1;

}

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