Выйти из двух циклов сразу
От: LeonGorbachev Россия  
Дата: 27.05.02 10:21
Оценка: 18 (1) :)
while(1)
{
  for(int i = 0; i < 100; i++)
  {
    if(i == 77)
      // вот тут хочу выйти вообще из всех циклов - из  for и из while
  }
}


Как это сделать?
Re: Выйти из двух циклов сразу
От: Mish Россия  
Дата: 27.05.02 10:26
Оценка: +3 -1
Здравствуйте LeonGorbachev, Вы писали:



LG>
LG>while(1)
LG>{
LG>  for(int i = 0; i < 100; i++)
LG>  {
LG>    if(i == 77)
LG>      // вот тут хочу выйти вообще из всех циклов - из  for и из while
LG>  }
LG>}
LG>


LG>Как это сделать?


Использовать goto. Ничего страшного не будет при умеренном использовании goto.

Удачи.
Re: Выйти из двух циклов сразу
От: OlegO Россия http://www.mediachase.ru
Дата: 27.05.02 10:31
Оценка: -1 :))
Здравствуйте LeonGorbachev, Вы писали:



LG>
LG>while(1)
LG>{
LG>  for(int i = 0; i < 100; i++)
LG>  {
LG>    if(i == 77)
LG>      // вот тут хочу выйти вообще из всех циклов - из  for и из while
LG>  }
LG>}
LG>


LG>Как это сделать?


Например сгенерить исключение:

try
{
   while(1)
   {
     for(int i = 0; i < 100; i++)
     {
       if(i == 77)
          throw 77;
     }
   }
}
catch(int e)
{
   // e==77
}
С уважением, OlegO.
Re[2]: Выйти из двух циклов сразу
От: Mishka<T> Великобритания  
Дата: 27.05.02 10:38
Оценка: -3
Здравствуйте OlegO, Вы писали:

OO>
OO>try
OO>{
OO>   while(1)
OO>   {
OO>     for(int i = 0; i < 100; i++)
OO>     {
OO>       if(i == 77)
OO>          throw 77;
OO>     }
OO>   }
OO>}
OO>catch(int e)
OO>{
OO>   // e==77
OO>}
OO>


Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.
Re[3]: Выйти из двух циклов сразу
От: LeonGorbachev Россия  
Дата: 27.05.02 10:39
Оценка:
Здравствуйте Mishka<T>, Вы писали:

MT>Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.


я вот как раз и не хочу через исключения. И не хочу гоу-ту.
Чего делать?
Re[4]: Выйти из двух циклов сразу
От: Mishka<T> Великобритания  
Дата: 27.05.02 10:42
Оценка:
Здравствуйте LeonGorbachev, Вы писали:

LG>я вот как раз и не хочу через исключения. И не хочу гоу-ту.

LG>Чего делать?

Можно так:
while(1)
{
  for(int i = 0; i < 100; i++)
  {
    if(i == 77)
      break;
  }
  if (i < 100) break;
}
Re[5]: Выйти из двух циклов сразу
От: Андрей Россия  
Дата: 27.05.02 10:53
Оценка: 14 (2)
Здравствуйте Mishka<T>, Вы писали:

MT>Здравствуйте LeonGorbachev, Вы писали:


LG>>я вот как раз и не хочу через исключения. И не хочу гоу-ту.

LG>>Чего делать?

MT>Можно так:

MT>
MT>while(1)
MT>{
MT>  for(int i = 0; i < 100; i++)
MT>  {
MT>    if(i == 77)
MT>      break;
MT>  }
MT>  if (i < 100) break;
MT>}
MT>


Это прокатит только на VC6

Я обычно делаю так:

bool bContinue = true;
while(bContinue) {
  for(int i = 0; i < 100; i++) {
    if (i == 77) {
      bContinue = false;
      break;
    }
  }
}


Возможны варианты, в зависимости от контекста
Re[3]: Выйти из двух циклов сразу
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 27.05.02 10:56
Оценка: 6 (1) +1 -1 :)
Здравствуйте Mishka<T>, Вы писали:


MT>Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.


Не пугай так народ, от и так уже запуганный.

terminate вызывается, только если второй exception не был перехвачен внутри деструктора, чего не наблюдается в данном примере.

Так что выход из вложенного цикла через исключение — нормальная ситуация.
Re[4]: return
От: Vi2 Удмуртия http://www.adem.ru
Дата: 27.05.02 10:57
Оценка: 1 (1) +1 -1
Здравствуйте LeonGorbachev, Вы писали:

LG>я вот как раз и не хочу через исключения. И не хочу гоу-ту.

LG>Чего делать?

Если есть возможность ВЫНЕСТИ эти циклы (не очень много переменных и т.д.),
можно сделать функцию и сделать возврат

...f(...)
{
  while(1)
  {
    for(int i = 0; i < 100; i++)
    {
      if(i == 77)
      // вот тут хочу выйти вообще из всех циклов - из  for и из while
        return;
    }
  }
}
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[3]: Выйти из двух циклов сразу
От: Рек Россия  
Дата: 27.05.02 10:57
Оценка:
Здравствуйте Mishka<T>, Вы писали:

MT>Здравствуйте OlegO, Вы писали:


OO>>
OO>>try
OO>>{
OO>>   while(1)
OO>>   {
OO>>     for(int i = 0; i < 100; i++)
OO>>     {
OO>>       if(i == 77)
OO>>          throw 77;
OO>>     }
OO>>   }
OO>>}
OO>>catch(int e)
OO>>{
OO>>   // e==77
OO>>}
OO>>


MT>Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.



То что не надо так делать — это ты прав.
А на счет того, что программа будет завершена — не совсем.

Исключение ведь перехватывется, и из деструктора не выпускаться не будет, потому всё будет работать.

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

По мне так вариант с goto наиболее понятен, слно предпочтителен.

Если с души воротит от goto, то можно оформить внутренний цикл как функцию
и делать из неё return вместо goto.
Re[6]: Выйти из двух циклов сразу
От: LeonGorbachev Россия  
Дата: 27.05.02 11:00
Оценка: 2 (1)
А>Я обычно делаю так:
А>
А>bool bContinue = true;
А>while(bContinue) {
А>  for(int i = 0; i < 100; i++) {
А>    if (i == 77) {
А>      bContinue = false;
А>      break;
А>    }
А>  }
А>}
А>


Я в общем то так и делаю, только подумалось, что можно по-другому...
Re[4]: Выйти из двух циклов сразу
От: slonnik  
Дата: 27.05.02 11:19
Оценка:
Здравствуйте DarkGray, Вы писали:

DG>Здравствуйте Mishka<T>, Вы писали:



MT>>Не надо так делать. Если такой код будет находиться в деструкторе, то при раскрутке стека в строке throw 77; программа будет заверешена и никакой catch (int e) не поможет.


DG>Не пугай так народ, от и так уже запуганный.


DG>terminate вызывается, только если второй exception не был перехвачен внутри деструктора, чего не наблюдается в данном примере.


DG>Так что выход из вложенного цикла через исключение — нормальная ситуация.


А если не cекрет а почему именно ВТОРОЙ exception и в чем его отличие от первого
Re[6]: Выйти из двух циклов сразу
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 27.05.02 11:51
Оценка:
Здравствуйте Андрей, Вы писали:

MT>>
MT>>while(1)
MT>>{
MT>>  for(int i = 0; i < 100; i++)
MT>>  {
MT>>    if(i == 77)
MT>>      break;
MT>>  }
MT>>  if (i < 100) break;
MT>>}
MT>>


А>Это прокатит только на VC6

Что именно? Scoping? Тогда да. А выход прокатит везде.

2 Mishka<T>
Только это неправильное условие. Надо выйти из циклов при i == 77, а if — совсем другое условие дает (расширяет диапазон значений немеряно).
Алексей Кирдин
Re[7]: Выйти из двух циклов сразу
От: LeonGorbachev Россия  
Дата: 27.05.02 12:01
Оценка:
Здравствуйте Kaa, Вы писали:

Kaa>Здравствуйте Андрей, Вы писали:


А>>Это прокатит только на VC6

Kaa>Что именно? Scoping? Тогда да. А выход прокатит везде.
Что такое Scoping?
Re[4]: Выйти из двух циклов сразу
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 27.05.02 12:04
Оценка: :)
Здравствуйте Рек, Вы писали:

Рек>А делать так не надо, потому что исключение это дорогое средство и должны

Рек>происходить редко (так в книжках пишут), слно алгоритмы с их помощью реализовывать не нужно,
Рек>только обработку ошибок.

Есть еще способ с использованием __leave у Microsoft, и им некоторые писатели книжек пользуются, но тогда SEH надо привлекать, что часто невозможно/трудно.

Рек>Если с души воротит от goto, то можно оформить внутренний цикл как функцию

Рек>и делать из неё return вместо goto.

Стоит добавить, что для встроенной функции никакого оверхеда не будет (если она компилятору понравится, конечно), а способ самый красивый. Но с добавочной переменной типа bool — еще красивее. Не так наглядна декомпозиция алгоритма, но зато потерь в производительности не будет.
Алексей Кирдин
Re[8]: Выйти из двух циклов сразу
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 27.05.02 12:07
Оценка: 15 (1) +1
Здравствуйте LeonGorbachev, Вы писали:

LG>Здравствуйте Kaa, Вы писали:


Kaa>>Здравствуйте Андрей, Вы писали:


А>>>Это прокатит только на VC6

Kaa>>Что именно? Scoping? Тогда да. А выход прокатит везде.
LG>Что такое Scoping?
Я имел ввиду, что область видимости переменной, объявленной в заголовке цикла, ограничена самим циклом (так написано в стандарте). В VC6 же это не так. Областью видимости переменных, там объявленых, является объемлющая для цикла область видимости.
Алексей Кирдин
Re: Выйти из двух циклов сразу
От: VladD2 Российская Империя www.nemerle.org
Дата: 27.05.02 12:57
Оценка: 6 (1) -1
Здравствуйте LeonGorbachev, Вы писали:

LG>
LG>while(1)
LG>{
LG>  for(int i = 0; i < 100; i++)
LG>  {
LG>    if(i == 77)
LG>      // вот тут хочу выйти вообще из всех циклов - из  for и из while
LG>  }
LG>}
LG>


LG>Как это сделать?


goto это единственный сто процентный выход из ситуации. Но выход это плохой. Лучше переделать условие циклов так, чтобы они учитывали такую ситуацию. Например:
bool b = true;
while(1)
{
  for(int i = 0; b && i < 100; i++)
  {
    if(i == 77)
    {
      // вот тут хочу выйти вообще из всех циклов - из  for и из 
      b = false;
      break;
    }
    // Если далее есть кол...
    // то дописываем проверку:
    if(b)
      break;
    // некоторый код
  }
}
http://nemerle.org/Banners/?g=dark
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[5]: Выйти из двух циклов сразу
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 27.05.02 13:33
Оценка: 11 (4)
Здравствуйте slonnik, Вы писали:

S>А если не cекрет а почему именно ВТОРОЙ exception и в чем его отличие от первого


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

Рассмотрим, пример:
//есть класс A, деструктор которого кидает исключение Exception2;
struct A
{
  ~A() {throw Exception2();}
};
//есть сервер, который кидает исключение
void Server()
{
  A a;
  throw Exception1();

}

//и есть клиент, который их ловит
void Client()
{
  try
  {
    Server();
  }
  catch (...)
  {
  }
}


Так вот, если при размотке стека при обработке исключения Exception1, окажется, что сгенерировалось еще одно исключение Exception2, которое ловится "выше", чем генериется первое, то у компилятора возникает дилема, какое исключение из этих двух передать в catch. В C++ пошли наиболее простым путем, и грохают всю программу(что очень сильно мешает написанию устойчивых программ), в остальных языках(Java, C#) второе исключение просто игнорируется.

Рассматривать программу, как дерево, и проведем линии от возникновений исключений до их обработки. Если линии сливаются, то в этом случае программа будет завершена.
Re[6]: Выйти из двух циклов сразу
От: KA it-knowledge-base.blogspot.com
Дата: 27.05.02 16:30
Оценка:
Здравствуйте DarkGray, Вы писали:

[skipped]

DG>Так вот, если при размотке стека при обработке исключения Exception1, окажется, что сгенерировалось еще одно исключение Exception2, которое ловится "выше", чем генериется первое, то у компилятора возникает дилема, какое исключение из этих двух передать в catch. В C++ пошли наиболее простым путем, и грохают всю программу(что очень сильно мешает написанию устойчивых программ), в остальных языках(Java, C#) второе исключение просто игнорируется.


По указанному простому пути идут программы, которые в деструкторах выбрасывают исключения и при этом не вызывают функцию
bool std::uncaught_exception();
//
#import <windows.bas>
class IWindows9x:protected DOS { private: virtual HANDLE EnumClouds()=0; };
Re[7]: Выйти из двух циклов сразу
От: DarkGray Россия http://blog.metatech.ru/post/ogni-razrabotki.aspx
Дата: 27.05.02 17:28
Оценка:
Здравствуйте KA, Вы писали:

KA>По указанному простому пути идут программы, которые в деструкторах выбрасывают исключения и при этом не вызывают функцию

KA>
bool std::uncaught_exception();


Так обычно выброс исключения происходит не прямо в деструкторе, а в функции, которая вызывается из деструктора. Сама функция может и не предполагать, что ее будут вызывать из деструктора.
В С++ нельзя, например, защититься от обращения по нулевому указателю внутри деструктора, что очень мешает жить программе — 24x7x365.


Предлагаешь завернуть каждый деструктор в такой код. ИМХО, это уже издевательство над программистом, лучше было бы предложить выбрать, какую модель я хочу.
void ~Destructor()
{
try
{
   //bla-bla
}
catch (...)
{
  if (std::uncaught_exception())
  {
    throw;
  }
}
}
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.