다음과 같은 코드를 작성하고 있습니다.
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
break; // **HERE, I want to break out of the loop itself**
}
}
그렇게하는 직접적인 방법이 있습니까?
플래그를 사용할 수 있고 스위치 바로 뒤에 조건부 중단을 두어 루프에서 벗어날 수 있다는 것을 알고 있습니다. C ++에 이미 이것에 대한 구조가 있는지 알고 싶습니다.
답변
전제
다음 코드는 언어 나 원하는 기능에 관계없이 잘못된 형식으로 간주되어야합니다.
while( true ) {
}
찬반론
while( true )
루프는 열악한 형태이다 :
- while 루프의 묵시적 계약을 끊습니다.
- while 루프 선언은 유일한 종료 조건을 명시 적으로 명시해야 합니다.
- 영원히 반복된다는 것을 의미합니다.
- 종료 절을 이해하려면 루프 내의 코드를 읽어야합니다.
- 영원히 반복되는 루프는 사용자가 프로그램 내에서 프로그램을 종료하는 것을 방지합니다.
- 비효율적입니다.
- “true”확인을 포함하여 여러 루프 종료 조건이 있습니다.
- 버그가 발생하기 쉽습니다.
- 각 반복마다 항상 실행되는 코드를 어디에 넣을지 쉽게 결정할 수 없습니다.
- 불필요하게 복잡한 코드로 이어집니다.
- 자동 소스 코드 분석.
- 버그, 프로그램 복잡성 분석, 보안 검사를 찾거나 코드 실행없이 다른 소스 코드 동작을 자동으로 도출하기 위해 초기 차단 조건을 지정하면 알고리즘이 유용한 불변성을 결정하여 자동 소스 코드 분석 메트릭을 개선 할 수 있습니다.
- 무한 루프.
- 모든 사람이 항상
while(true)
무한이 아닌 for 루프를 사용 하는 경우 루프에 실제로 종료 조건이 없을 때 간결하게 통신 할 수있는 기능을 잃게됩니다. (아마도 이것은 이미 일어 났으므로 요점은 논쟁의 여지가 있습니다.)
- 모든 사람이 항상
“이동”의 대안
다음 코드가 더 나은 형식입니다.
while( isValidState() ) {
execute();
}
bool isValidState() {
return msg->state != DONE;
}
장점
플래그가 없습니다. 아니 goto
. 예외 없음. 변경하기 쉽습니다. 읽기 쉬운. 쉽게 고칠 수 있습니다. 추가로 코드 :
- 루프 자체에서 루프의 워크로드에 대한 지식을 분리합니다.
- 코드를 유지하는 누군가가 기능을 쉽게 확장 할 수 있습니다.
- 여러 종료 조건을 한 곳에서 할당 할 수 있습니다.
- 실행할 코드에서 종료 절을 분리합니다.
- 원자력 발전소에 더 안전합니다. 😉
두 번째 요점이 중요합니다. 코드가 어떻게 작동하는지 모르는 상태에서 누군가가 나에게 메인 루프가 다른 스레드 (또는 프로세스)에 CPU 시간을 허용하도록 요청하면 두 가지 솔루션이 떠 오릅니다.
옵션 1
일시 중지를 쉽게 삽입하십시오.
while( isValidState() ) {
execute();
sleep();
}
옵션 # 2
실행 무시 :
void execute() {
super->execute();
sleep();
}
이 코드는 포함 된 루프보다 더 간단합니다 (따라서 읽기 쉽습니다) switch
. 이 isValidState
메서드는 루프가 계속되어야하는지 여부 만 결정해야합니다. 이 방법의 주력이로 추상화한다 execute
서브 클래스가 기본 동작을 재정의 할 수 있습니다 방법, (어려운 작업은 임베디드를 사용 switch
하고 goto
).
Python 예
StackOverflow에 게시 된 다음 답변 (Python 질문에 대한)을 대조하십시오.
- 영원히 반복하십시오.
- 사용자에게 선택 사항을 입력하도록 요청합니다.
- 사용자 입력이 ‘다시 시작’이면 계속 반복됩니다.
- 그렇지 않으면 루프를 영원히 중지하십시오.
- 종료.
암호
while True:
choice = raw_input('What do you want? ')
if choice == 'restart':
continue
else:
break
print 'Break!'
대:
- 사용자의 선택을 초기화하십시오.
- 사용자의 선택이 ‘다시 시작’이라는 단어 인 동안 반복합니다.
- 사용자에게 선택 사항을 입력하도록 요청합니다.
- 종료.
암호
choice = 'restart';
while choice == 'restart':
choice = raw_input('What do you want? ')
print 'Break!'
여기 while True
에서 오해의 소지가 있고 지나치게 복잡한 코드가 생성됩니다.
답변
사용할 수 있습니다 goto
.
while ( ... ) {
switch( ... ) {
case ...:
goto exit_loop;
}
}
exit_loop: ;
답변
다른 해결책은 키워드 continue
를와 함께 사용하는 것입니다 break
.
for (;;) {
switch(msg->state) {
case MSGTYPE
// code
continue; // continue with loop
case DONE:
break;
}
break;
}
continue
문을 사용하여 루프를 계속할 각 케이스 레이블을 완료 하고 문을 사용하여 루프를 break
종료해야하는 케이스 레이블을 완료하십시오.
물론이 솔루션은 switch 문 다음에 실행할 추가 코드가없는 경우에만 작동합니다.
답변
이를위한 깔끔한 방법은 이것을 함수에 넣는 것입니다 :
int yourfunc() {
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
return;
}
}
}
선택적으로 (그러나 ‘나쁜 사례’) : 이미 제안했듯이 goto를 사용하거나 스위치 내부에서 예외를 throw 할 수 있습니다.
답변
AFAIK C ++에는 “이중 브레이크”또는 이와 유사한 구조가 없습니다. 가장 가까운 것은 goto
-이름에 나쁜 의미가 있지만 이유 때문에 언어에 존재합니다-신중하고 드물게 사용되는 한 실행 가능한 옵션입니다.
답변
스위치를 다음과 같이 별도의 기능에 넣을 수 있습니다.
bool myswitchfunction()
{
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
return false; // **HERE, I want to break out of the loop itself**
}
return true;
}
while(myswitchfunction())
;
답변
goto를 좋아하지 않더라도 루프를 종료하기 위해 예외를 사용하지 마십시오. 다음 샘플은 얼마나 추한지 보여줍니다.
try {
while ( ... ) {
switch( ... ) {
case ...:
throw 777; // I'm afraid of goto
}
}
}
catch ( int )
{
}
이 답변 goto
에서와 같이 사용 합니다. 이 경우 다른 옵션보다 코드가 더 명확 해집니다. 이 질문이 도움 이 되기를 바랍니다 .goto
그러나 나는 goto
문자열 때문에 사용하는 것이 유일한 옵션 이라고 생각 합니다 while(true)
. 루프 리팩토링을 고려해야합니다. 다음 솔루션을 가정합니다.
bool end_loop = false;
while ( !end_loop ) {
switch( msg->state ) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
end_loop = true; break;
}
}
또는 다음과 같은 경우도 있습니다.
while ( msg->state != DONE ) {
switch( msg->state ) {
case MSGTYPE: // ...
break;
// ... more stuff ...
}