Можете ли вы переписать этот фрагмент без перехода - PullRequest
4 голосов
/ 19 августа 2009

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

Ограничения:

  1. current=current->child() стоит дорого (это shared_ptr), поэтому я хотел бы свести к минимуму использование этой операции любой ценой.
  2. После операции current должен быть последним найденным ребенком.
  3. cnt должен считать каждого ребенка, с которым встречается.
  4. cnt ++ будет заменен какой-либо другой операцией (или несколькими операциями) и должен появляться только один раз:)

код:

insideloopy:
cnt++;
if ( current->hasChild() )
{
    current = current->child();
    goto insideloopy;
}

Редактировать: Извините, ребята, изначально забыл упомянуть, что cnt ++ должен появляться только один раз. Это будет какая-то операция на узле, и, следовательно, она должна выполняться только один раз. Я также пытаюсь избежать вызова другой функции.

Ответы [ 8 ]

26 голосов
/ 19 августа 2009

Оригинальный ответ

Предполагается, что это C или C ++:

while (cnt++, current->hasChild())
{
    current = current->child();
}

Обычно я не большой поклонник оператора запятых, но я не люблю повторяться:)

Обновленный «забавный» ответ

Узнав, что cnt++ на самом деле является многострочной операцией, этот конкретный синтаксис будет не идеальным. Что-то более похожее на ваш принятый ответ будет лучше.

Если вы хотите быть действительно прикольным, это также сработает:

do 
{
    cnt++;
} while (current->hasChild() && (current = current->child()));

Теперь я чувствую себя очень грязно, потому что злоупотребляю коротким замыканием на операторе && :)

Вменяемый ответ

Упражнения на компактность и стремление к удобочитаемому коду, я вынужден сделать вывод, что один из существующих ответов лучше всего подходит (я просто включаю это для полноты картины):

while (true)
{
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}

Компилятор while (true) будет оптимизирован в обычный бесконечный цикл, поэтому есть только один условный оператор (если вам это нужно).

Единственное, что противоречит этому решению, - это если ваш узел был длинным фрагментом кода. Я не возражаю против бесконечных циклов так долго, пока я могу видеть, где они заканчиваются с первого взгляда. Опять же, если оно действительно длинное, оно все равно должно быть функцией.

18 голосов
/ 19 августа 2009
cnt++;
while(current->hasChild())
{
   cnt++;
   current = current->child();
}

EDIT:

Если вы хотите, чтобы cnt ++ был в вашем коде только один раз:

while(true)
{
    cnt++;
    if(current->hasChild())
       current = current->child();
    else
       break;
}
11 голосов
/ 19 августа 2009
insideloopy:
cnt++;
if ( current->hasChild() )
{
    current = current->child();
    goto insideloopy;
}

Я люблю бесконечные петли.

while (true) {
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}

Конечно, вы можете сделать это многими другими способами (см. Другие ответы). делать время, ставить проверку в то время и т. д. В моем решении я хотел сопоставить почти то, что вы делаете (бесконечный переход, если не перерыв)

3 голосов
/ 19 августа 2009

Вы можете использовать break, чтобы выйти из цикла в середине кода:

while (true) {
   cnt++;
   if (!current->hasChild()) break;
   current = current->child();
}
0 голосов
/ 20 августа 2009

Без операторов перерыва:

notDone=true;
while(notDone){
   cnt++;
   if ( current->hasChild() ){
       current = current->child();
   } else {
       notDone=false;
   }
}
0 голосов
/ 19 августа 2009

Я бы исследовал возможность заставить current->child() возвращать NULL, когда у него нет дочернего элемента, если у него его еще нет - это кажется наилучшим возможным результатом, и оставить его неопределенным в этом случае кажется склонным к ошибкам - и затем использовать :

for (; current; current = current->child())
{
    cnt++;
}
0 голосов
/ 19 августа 2009
for(cnt++ ; current->hasChild() ; cnt++) {
   current = current->child();
}
0 голосов
/ 19 августа 2009
while (current->hasChild())
{
    cnt++;
    current = current->child();
}

Или я что-то упустил?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...