IT TIP

분기를 단순화하기위한`while (1)`의 대안

itqueen 2020. 12. 31. 23:12
반응형

분기를 단순화하기위한`while (1)`의 대안


이 질문에 이미 답변이 있습니다.

때때로 나는 while(1)블록을 사용하여 if..else비율을 벗어나는 연속을 평평하게 만듭니다 . 이 선을 따라갑니다.

대신 :

// process 
if (success) {
  // process 
  if (success) {
    //process
    if (success) {
      // etc
    }
  }
}

나는한다:

while (1) {
  // process
  if (!success) break;
  // process
  if (!success) break;
  // process
  if (!success) break;
  // etc
  break;
}

의 끝에서 암시 적 점프로 인해 약간 짜증이납니다 while. 더 간결한 구조로 벗어날 수 break있습니까 (즉 , 끝에는 없음)?

최종 결과 break를 변수 (또는 등록?)와 거래 할 수 있습니다. 그것은 정확히 더 희박하거나 명확하지 않습니다.

int once = 1;
while (once--) {
  // process
  if (!success) break;
  // process
  if (!success) break;
  // process
  if (!success) break;
  // etc
}

for 루프가 좀 더 좋아 보일 것입니다 (C99).

for (int once = 1 ; once--; once) {
  // process
  if (!success) break;
  // process
  if (!success) break;
  // process
  if (!success) break;
  // etc
}

스위치 케이스 사용을 생각했습니다. 작동하지만 훨씬 좋아 보이지는 않습니다.

switch (1) { default:
  // process
  if (!success) break;
  // process
  if (!success) break;
  // process
  if (!success) break;
  // etc
}

이 특별한 경우 라벨의 개념은 타의 추종을 불허합니다.

// process
if (!success) goto end;
// process
if (!success) goto end;
// process
if (!success) goto end;
// etc

end:

너희들이 알고 사용하는 다른 접근 방식은 무엇입니까?


다음은 루프를 사용하여 수행하는 작업과 매우 유사한 방법이지만 break끝에 카운터 나 이 필요하지 않습니다 .

do
{
    // process
    if (!success) break;
    // process
    if (!success) break;
    // process
    if (!success) break;
    ...
    // No need for a break statement here
}
while(0);

너희들이 알고 사용하는 다른 접근 방식은 무엇입니까?

while루프를 함수로 캡슐화 할 수 있습니다 ( 루프가있는 곳에서이 함수를 호출 while).

static void process(void)
{
   // process
   if (!success) return;
   // process
   if (!success) return;
   // process
   if (!success) return;
   // process
}

중간 정도의 괜찮은 컴파일러 (예 : gcc최적화가 비활성화 된 static경우에도)는 한 번 호출되면 함수 를 인라인합니다 . (물론 일부 변수는 process함수 의 어휘 범위에 있어야 할 수 있습니다 .이 경우 함수의 매개 변수로 제공하기 만하면됩니다.)

가로가 아닌 위에서 아래로 코드를 작성하는 것 (예 : nested if가있는 예제 )을 더핑 이라고 합니다 . 여기에 주제에 대한 좋은 기사가 있습니다.

"Reading Code From Top to Bottom"

Also, in the Linux kernel coding style there is a specific warning writinh against horizontal code:

"if you need more than 3 levels of indentation, you're screwed anyway, and should fix your program"


If you arrange that the body of each conditional block generating success is a function as follows or each // process can otherwise be reduced to a boolean expression, such as:

success = f1() ; 
if( success ) 
{
  success = f2() ; 
  if( success ) 
  {
    success = f3() ; 
    if( success ) 
    {
      success = f4()
    }
  }
}

Then you can reduce this to a single boolean expression exploiting short-circuit evaluation:

success = f1() && 
          f2() && 
          f3() && 
          f4() ;

Here f2() will not be called if f1() returns false and the same for each successive call - expression evaluation aborts on the first && operand sub-expression to return false.


Not clear why you'd need to nest or break. I do this all the time when a sequence needs to bail at first failure:

// process

if (success) {
  // more process
}

if (success) {
  // still more process
}

if (success) {
  // even more process
}

Fiddling bits has provided a common approach. Another common approach is to use a single status variable/flag to achieve a similar result.

bool bErr = false;

if (!bErr && success) {
   // do something
} else {
   bErr = true;
}
if (!bErr && success2) {
   // do something
} else {
   bErr = true;
}

if (bErr) {
   // hanlde cleanup from errors
}

Another option would be using a simple flag variable

bool okay = true;

if(okay &= success){
    // process
}

if(okay &= success){
    // process
}

if(okay &= success){
    // process
}

ReferenceURL : https://stackoverflow.com/questions/25145321/alternatives-to-while-1-to-simplify-branching

반응형