Обнаружить первый проход через do-while
У меня есть цикл do-while, который должен регистрировать сообщение один раз (чтобы он не загромождал журнал) каждый раз, когда изменяется его состояние (например, проход / сбой), но все равно приходится делать другие вещи каждый раз, когда проходит цикл, Используя простую логическую переменную, вы можете узнать, записали ли вы уже это сообщение, и это сработает, когда вы будете в известном состоянии. Однако, если вы хотите, чтобы сообщение было напечатано в первый раз в любом случае (пройти / не пройти), вы должны учитывать это. Например, если по умолчанию ваше состояние true
и на самом деле это правда в первый раз, оно не будет записывать сообщение "Истина", потому что думает, что оно уже истинно (и наоборот для ic ложно).
Похоже, что это было бы хорошим местом для логического значения, допускающего нулевое значение с ic =Null, но в языках, где их нет, что делать?
Самое простое решение, о котором я мог бы подумать, - это использовать дополнительную логическую переменную, такую как 'firstTime = True', но использование этого всегда мешает мне в качестве элементарного обходного пути, когда я чувствую, что должен быть более тонкий способ справиться с этим. Другой вариант - использовать условие прорыва do-while в качестве исходного условия для любой переменной, которую вы используете в качестве условия, но это может сбивать с толку, когда кто-то читает int status = STATUS_QUIT
и, конечно, требует больше пояснительных комментариев, чем bool firstTime = true
, Третий вариант - использовать enum вместо bool и иметь {firstTime, true, false} или что-то в этом роде.
Есть ли другие причины для использования одного над другим, или есть лучшие способы сделать это?
Пример кода с двумя вариантами, которые я придумал:
С помощью bool firsttime
:
bool firstTime = true, infoFound = false;
do
{
if (getInfo())
{
if (!infoFound)
{
// log it (ONCE)(important)
infoFound = true;
}
// use info (every time)
}
else if (infoFound || firstTime)
{
// log it (ONCE)(important)
infoFound = false;
firstTime = false;
}
// FYI, WaitForStatusUpdate is a blocking call...
} while (STATUS_QUIT != WaitForStatusUpdate());
Использовать while
Цикл 'условие разрыва' в качестве начального условия для проверочной переменной:
(status
обновляется в конце do-while, поэтому do
раздел больше не будет выполняться, если status == breakOutCondition
; мы можем использовать это в наших интересах здесь и установить status = breakOutContition
изначально - первый раз через него будет breakOutCondition
но любой последующий цикл будет чем-то другим... Еще не уверен, что мне это нравится, так как это своего рода хак...
bool infoFound = false;
int status = STATUS_QUIT;
do
{
if (getInfo())
{
if (!infoFound)
{
// log it (ONCE)(important)
infoFound = true;
}
// use info (every time)
}
else if (infoFound || firstTime)
{
// log it (ONCE)(important)
infoFound = false;
}
status = WaitForStatusUpdate();
} while (STATUS_QUIT != status);
(Я отмечаю это как C++, так как это то, что я использую, но это действительно может относиться к любому языку с подобными конструкциями)
2 ответа
Разве перечисление не будет яснее?
enum State { Unknown, Pass, Fail };
State state = Unknown;
...
State newState = getInfo() ? Pass : Fail;
if (newState != state) { log(); state = newState; }
C++ почти имеет допускающие логическое значение логические значения, boost::optional<bool>
сделал бы трюк, я верю.
Одним из распространенных способов сделать это в C++ является потоковая оболочка, которую вы создаете в правильном контексте, и она запоминает, например, сколько раз она сбрасывается и предотвращает дальнейшее ведение журнала. Вы просто ведете запись как обычно и позволяете потоку решать, отправлять ли его в завернутый поток.