Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C++ Builder > Выход из функции


Автор: maroonorg 10.5.2008, 09:58
Здравствуйте, форумчане. Подскажите, пожалуйста, вот по какому вопросу:

При нажатии на кнопку происходит большое количество проверок, и последующая проверка вытекает из прошлой, т.е. например:

Код

if (условие1)
{
    if (условие2)
    {
        if (условие3)
        {
            .....
        }
        else ...
    }
    else ...
}
else
{
    ShowMessage("Условие 1 не выполнено");
}


Можно как-нибудь приостановить выполнение функции, как это например реализовано на php (функция exit останавливает работу скрипта), чтобы не создавать множество вложенных if'ов, а сделать например так:

Код

if (!условие1)
{
    ShowMessage("Условие 1 не выполнено");
    // Выход из функции
}

if (!условие2)
{
    ShowMessage("Условие 2 не выполнено");
    // Выход из функции
}

if (!условие3)
{
    ShowMessage("Условие 3 не выполнено");
    // Выход из функции
}


Заранее спасибо за помощь

Автор: almagnit 10.5.2008, 10:07
Конечно:

Код

break;

Автор: maroonorg 10.5.2008, 10:29
Спасибо за предложение, но:

Код

if ( true ) {
    ShowMessage("True now");
    break;
    if ( true ) {
        ShowMessage("And now too");
    }
}


Выходит ошибка Misplaced break

Автор: almagnit 10.5.2008, 10:43
Извиняюсь, последнее время сижу на Java, нужно делать так:

Код

return 0;

Автор: maroonorg 10.5.2008, 10:53
Как я уже говорил, проверки происходят когда мы нажимаем на кнопку. Тогда возникает следующий момент:

Код

void __fastcall TfMainForm::sButton1Click(TObject *Sender)


Функция не возвращает значение и компилятор не разрешает сменить void. Поэтому

Код

return 0;


не подходит

Автор: almagnit 10.5.2008, 11:11
А просто 
Код
return;
, если void.  smile 

Автор: maroonorg 10.5.2008, 11:29
Да, все, спасибо, не подумал об этом  smile 

Благодарю за помощь

Автор: SABROG 10.5.2008, 12:27
Т.е. ради красоты кода (избавления от вложенности условий) ты решил добавить пару десятков return'ов smile ?

А такой вариант в твоей программе не прокатит ?:

Код

if (условие1 && условие2 && условие3 && условие4 && условие5 && условие6)
{
    // Все условия удовлетворяют
}

Автор: maroonorg 10.5.2008, 12:32
Да, так точно. 

Не думаю что это сильно усложнить читабельность кода ( в некоторых случаях даже уменьшит )

К твоему вопросу: на каждое условие должно быть свое сообщение об ошибке. Т.е. если не заполнено поле, то должно вывести что именно это поле не заполнено.

Представь себе 20 вложенных условий (  smile  ) , я бы лично даже читать бы такое отказался

Извиняюсь за smile 

Автор: SABROG 10.5.2008, 12:50
Неправильный подход для создания форм, где есть обязательные для заполнения поля.

Должно быть как-то так:

- есть массив элементов-контролов, каждому элементу соответствует название "Название организации", "Пол", "Дата рождения" и флаг "Обязательно к заполнению" или "Необязательно заполнять".
- в цикле, функция типа isAllValid проверяет каждое из полей
- если поле не заполнено и стоит флаг "Обязательно к заполнению" - выводим сообщение: 'Поле "Название организации" должно быть заполнено'.
- если параметр не обязательный, но данные не валидные (например e-mail не удовлетворяет регулярному выражению, скажем ввели vasya@mailru, т.е. точку забыли), то опять же выводим сообщение: 'Поле "Электронный адрес" не корректно'.

В общем грубо говоря, вместо того, чтобы плодить if'ы надо перебирать контролы на форме и в зависимости от флагов и параметров ругаться. Т.е. работа с динамическим массивом.

Автор: maroonorg 10.5.2008, 12:53
А нельзя привести пример такого приложения, пожалуйста?
 smile 
Заранее спасибо.

Автор: SABROG 10.5.2008, 13:35
Вот упрощенный вариант.

user posted image

Идея тут такая:

- в поле Tag пишем либо 0 либо 1 в зависимости от того требуется ли обязательное заполнение или нет. Если 1 - требуется, если 0 (по умолчанию) - не требуется
- в коде я намеренно использую фильтр по классу TEdit, чтобы кнопки и ярлыки не обрабатывались. По сути грязный хак. Потом объясню почему.
- если контрол нашелся и он должен быть заполнен (TAG == 1), но он пустой, то выдается ошибка, что такое-то поле не заполнено. Название поля берется из параметра Hint, который заполняется во время проектирования программы.

На самом деле в поле Tag можно пихать не только цифры, но и указатели на структуры и классы, но это на этапе выполнения программы. Я бы создал структуру с двумя параметрами: bool и AnsiString. Т.е. обязательность заполнения и название объекта. При переборе всех контролов на форме я бы проверял, если Tag не равен нулю, то значит это нужный нам объект, который содержит ссылку на нужные данные. Можно конечно еще много чего напридумывать.

Автор: maroonorg 10.5.2008, 14:31
Идея интересная, но почему бы ее немного не упростить?

Немного измененная версия. На 2007 Builder'е. Если нет 2007 билдера:

user posted image

Имена элементов Label1, Edit1,  Label2, Edit2,  Label3, Edit3.
У Edit1 и Edit3 параметр Tag == 1. Воообще не имеет смысла, надо хоть одну единицу для проверки работы  smile

При нажатии на кнопку:

Код

    for (register int i = 1; i <= 3; i++)
    {
        TEdit *pEdit = dynamic_cast <TEdit*> (this->FindComponent("Edit" + IntToStr(i) ) );
        if ( pEdit->Tag && pEdit->Text.IsEmpty() )
        {
            TLabel *pLabel = dynamic_cast <TLabel*> (this->FindComponent("Label" + IntToStr(i) ) );
            ShowMessage("Заполните поле \"" + pLabel->Caption + "\"");
            return;
        }
    }


И еще вопрос, что будет работать быстрее:
Код

Edit->Text.isEmpty()

или
Код

Edit->Text == ""


Автор: SABROG 10.5.2008, 16:42
Тут у тебя жестко задано количество элементов, косяк появится, когда добавишь или удалиш поле:

Код

for (register int i = 1; i <= 3; i++)


Я бы не советовал привязываться к именам компонентов, также как и к их названиям классов. К ссылкам/указателям - пожалуйста. Кстати указывать this-> не обязательно, достаточно FindComponent.

Тут тоже я бы не привязывался жестко:

Код

if ( pEdit->Tag && pEdit->Text.IsEmpty() )


Как я писал выше, вполне возможно, что поле может и не быть обязательным, но если его все-таки указали, то вероятно есть смысл проверить его на валидность (e-mail, ip адрес, номер ИНН, день рождения). К Label'ам я вообще не стал привязываться по той причине, что их может и не быть (например группа элементов для дня рождения: Edit - день рождения, combobox - месяц рождения, combobox - год рождения, элемента 3, а label один).

Насчет того, что будет работать быстрее. Я использую isEmpty() потому, что именно для этого она и создана, следовательно любая оптимизация по ускорению проверки будет касаться именно этой функции, а сравнение строки с пустой строкой может оказаться медленней, хотя я в этом сомневаюсь потому, что обычно в таких функциях если длинны строк не совпадают изначально, то проверки вообще не происходит, т.к. ясно что они не могут быть идентичными.

Автор: maroonorg 10.5.2008, 17:19
SABROG, спасибо, учту, запомню

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)