2012-12-24 3 views
2

나는 책에서 C를 배우려고 노력하고 있지만, 나를 위해 충분히 명확하게 설명되지 않은 것이있다.초보자가 재귀 함수에서 잃어버린

다음 코드

1) 재귀 함수를 사용하여 0 내지 99의 병 맥주를 카운트 다운한다. 그것이 내가이 카운트 다운하는 방법을 이해하고, 왜 다음 3)

...  #more of same above 
3 bottles of beer on wall, 3 bottles of beer 
Take one down, pass around, 2 bottls of beer 
2 bottles of beer on wall, 2 bottles of beer 
Take one down, pass around, 1 bottls of beer 
1 bottles of beer on wall, 1 bottles of beer 
Take one down, pass around, 0 bottls of beer 
There are no more bottles on the wall. 
Put bottle in recycling, 1 empty bottles in bin 
Put bottle in recycling, 2 empty bottles in bin 
Put bottle in recycling, 3 empty bottles in bin 
....  #pattern continues 

을 재활용 병, 하나 하나를두고 "벽에 더 이상 병이 없습니다"인쇄 병에서의 일단 2) 더 이상 맥주 한 병은 없다고 말합니다. 그러나 병을 재활용하는 데 걸리는 코드 (printf)가 조건부의 else 부분에 있기 때문에 어떻게 호출되는지 이해하지 못합니다. 일단 병 수가 0에 도달하면 함수는 절대로 조건의 else 부분으로 되돌아 가지 않습니다.

질문 : 마지막 printf ("병을 재활용 중 ...")가 99 번 호출되고 어떻게 병을 하나씩 증가시킬 수 있습니까?

코드

void singTheSong(int numberOfBottles) 

{ 

    if(numberOfBottles == 0){ 
     printf("There are no more bottles on the wall.\n"); 
    }else { 
     printf("%d bottles of beer on wall, %d bottles of beer \n", numberOfBottles,numberOfBottles); 
     int oneFewer = numberOfBottles - 1; 
     printf("Take one down, pass around, %d bottls of beer \n", oneFewer); 
     singTheSong(oneFewer); 
     printf("Put bottle in recycling, %d empty bottles in bin \n", numberOfBottles); 

    } 
} 

int main(int argc, const char * argv[]) 
{ 

    singTheSong(99); 
    return 0; 
} 
+0

'printT' 문을'singTheSong (...) '함수의 시작 부분에 넣고 함수의 마지막 부분에 넣어서 무슨 일이 일어나고 있는지 이해하고 볼 수있게 해보십시오. – t0mm13b

+0

수동 작업 작은 케이스 (2 또는 3)를 통해 – mfrankli

+3

은 OP의 사용자 이름을 좋아할 수도 있습니다 ... – t0mm13b

답변

3

이 세 라인 : 곡의

printf("Take one down, pass around, %d bottls of beer \n", oneFewer); 
singTheSong(oneFewer); 
printf("Put bottle in recycling, %d empty bottles in bin \n", numberOfBottles); 

인쇄 이러한 부분 : 최종 라인 실행이 완료 singTheSong 후 인쇄

Take one down, pass around, n - 1 bottls of beer 
/* The entire song for n - 1 */ 
Put bottle in recycling, n empty bottles in bin 

는 스택 풀려 갖고, 최상위 함수가 계속 실행됩니다. 재귀 호출을 잠시 잊어 버리고 singTheSong이라는 호출이 마술처럼 작동하는 블랙 박스로 표시되는 경우이 세 줄의 코드 동작은 다른 호출이 작동하는 방식과 다르지 않습니다.

+0

그래서 마지막 printf가 스택에 geting을 계속 유지하고 99에서부터 한 번 카운트되면 "unroll"즉 마지막 printfs가 호출됩니다. 1에서 99까지의 재활용을 설명하는 선입 선출 기준에 따라? – BrainLikeADullPencil

0

이 도움이 될 수 있습니다. 함수의 실제 신체의 첫 번째 통화로 치환 생각해 numberOfBottles == 99은 if (numberOfBottles == 0)가 실패하고 오직 다른 부분이 실행되는 최초 호출에

void singTheSong(int numberOfBottles) 

{ 

    if(numberOfBottles == 0){ 
     printf("There are no more bottles on the wall.\n"); 
    }else { 
     printf("%d bottles of beer on wall, %d bottles of beer \n", numberOfBottles,numberOfBottles); 
     int oneFewer = numberOfBottles - 1; 
     printf("Take one down, pass around, %d bottls of beer \n", oneFewer); 
     singTheSong(oneFewer); 
     printf("Put bottle in recycling, %d empty bottles in bin \n", numberOfBottles); 

    } 
} 

int main(int argc, const char * argv[]) 
{ 
    int numberOfBottles=99; 

    if(numberOfBottles == 0){ 
     printf("There are no more bottles on the wall.\n"); 
    }else { 
     printf("%d bottles of beer on wall, %d bottles of beer \n", numberOfBottles,numberOfBottles); 
     int oneFewer = numberOfBottles - 1; 
     printf("Take one down, pass around, %d bottls of beer \n", oneFewer); 
     singTheSong(oneFewer); 
     printf("Put bottle in recycling, %d empty bottles in bin \n", numberOfBottles); 

    } 
    return 0; 
} 

한다. 두 줄을 인쇄하고 singTheSong (98)을 호출 한 다음 재활용에 관한 행을 인쇄합니다.

이와 같은 대체 작업을 계속한다고 상상해보십시오. 어떻게 작동하는지 볼 수 있습니다.

0

재귀를 사용할 때 1. 종료 조건 (이 경우 "맥주 병 없음"(슬픈 상황! -하지만 99로 시작할 경우 나쁘지는 않습니다.)이 없으면 , 당신은 좋은 일이 아니다 무한 재귀를 얻을! 2. 재귀 호출. 3. 당신이 지금까지 완료 재귀 단계 후 않습니다.

그래서, 진정한 술자리처럼, 아무도 파티가 끝나고 더 이상 맥주가 없어 질 때까지 청소하고 벽에서 다른 병을 가져 와서 조금 노래하고 병을 지나쳐 병이 완성되면 벽에서 다른 병을 가져와 노래하고, 음료수, 병 가져 오기, 노래 부르기 등. 일단 모든 병이 끝나면 ed (0 bootles), 우리는 돌아 오는 것으로 정돈했다 (더 이상 노래하고 마시지 않는다, 폐점 시간 등). 그리고 물론 재귀 호출의 "반환"은 가장 깊은 호출 수준에서 시작됩니다 (맥주 마지막 병 = 1 병 '왼쪽'). 그런 다음 한 수준 아래로 이동 (2 병) 한 다음 다른 수준 아래로 이동합니다 병) 등등.

때로는 사람들이 "꼬리 재귀"에 대해 말합니다. 재귀의 최종 단계는 함수 자체를 호출하는 것입니다.

+0

그래서 SingSong의 마지막 printf는 0 병 남을 때까지 호출되지 않습니다. 즉, 계속 병을 쌓은 다음 재활용을 위해 역순으로 호출됩니다. 1시에 시작하니? 후입 선출법? – BrainLikeADullPencil

+0

Jup, 정확히 - 마치 영화 나 TV 쇼 또는 일부에서 술을 많이 드는 것과 같이 - 전체 테이블을 채우는 병을 볼 수 있습니다. –