스위치 내부에서 루프를 해제하는 방법은 무엇입니까?
다음과 같은 코드를 작성하고 있습니다.
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 ...
}
이 경우 루프를 벗어나기위한 C ++ 구조가 없습니다.
플래그를 사용하여 루프를 중단하거나 (적절한 경우) 코드를 함수로 추출하고 return
.
잠재적으로 goto를 사용할 수 있지만 루프를 중지하는 플래그를 설정하는 것이 좋습니다. 그런 다음 스위치에서 나오십시오.
while 루프의 조건을 수정하여 문제가 사라지는 이유는 무엇입니까?
while(msg->state != DONE)
{
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
// We can't get here, but for completeness we list it.
break; // **HERE, I want to break out of the loop itself**
}
}
아니요, "break"키워드가 스위치 블록을 종료하기 위해 이미 예약되어 있으므로 C ++에는 이에 대한 구문이 없습니다. 또는 종료 플래그가있는 do..while ()이면 충분할 수 있습니다.
do {
switch(option){
case 1: ..; break;
...
case n: .. ;break;
default: flag = false; break;
}
} while(flag);
나는 생각한다.
while(msg->state != mExit)
{
switch(msg->state)
{
case MSGTYPE: // ...
break;
case DONE:
// ..
// ..
msg->state =mExit;
break;
}
}
if (msg->state ==mExit)
msg->state =DONE;
The simplest way to do it is to put a simple IF before you do the SWITCH , and that IF test your condition for exiting the loop .......... as simple as it can be
The break
keyword in C++ only terminates the most-nested enclosing iteration or switch
statement. Thus, you couldn't break out of the while (true)
loop directly within the switch
statement; however you could use the following code, which I think is an excellent pattern for this type of problem:
for (; msg->state != DONE; msg = next_message()) {
switch (msg->state) {
case MSGTYPE:
//...
break;
//...
}
}
If you needed to do something when msg->state
equals DONE
(such as run a cleanup routine), then place that code immediately after the for
loop; i.e. if you currently have:
while (true) {
switch (msg->state) {
case MSGTYPE:
//...
break;
//...
case DONE:
do_cleanup();
break;
}
if (msg->state == DONE)
break;
msg = next_message();
}
Then use instead:
for (; msg->state != DONE; msg = next_message()) {
switch (msg->state) {
case MSGTYPE:
//...
break;
//...
}
}
assert(msg->state == DONE);
do_cleanup();
It amazes me how simple this is considering the depth of explanations... Here's all you need...
bool imLoopin = true;
while(imLoopin) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
imLoopin = false;
break;
}
}
LOL!! Really! That's all you need! One extra variable!
while(MyCondition) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
MyCondition=false; // just add this code and you will be out of loop.
break; // **HERE, you want to break out of the loop itself**
}
}
I got same problem and solved using a flag.
bool flag = false;
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
flag = true; // **HERE, I want to break out of the loop itself**
}
if(flag) break;
}
If I remember C++ syntax well, you can add a label to break
statements, just like for goto
. So what you want would be easily written:
while(true) {
switch(msg->state) {
case MSGTYPE: // ...
break;
// ... more stuff ...
case DONE:
break outofloop; // **HERE, I want to break out of the loop itself**
}
}
outofloop:
// rest of your code here
while(true)
{
switch(x)
{
case 1:
{
break;
}
break;
case 2:
//some code here
break;
default:
//some code here
}
}
참고URL : https://stackoverflow.com/questions/1420029/how-to-break-out-of-a-loop-from-inside-a-switch
'Programming' 카테고리의 다른 글
MySQL Insert Where 쿼리 (0) | 2020.08.08 |
---|---|
WKWebView에서 사용할 쿠키를 설정할 수 있습니까? (0) | 2020.08.08 |
Vim 접기에 대한 혼란-비활성화하는 방법? (0) | 2020.08.08 |
NHibernate로 어떻게 페이징을 할 수 있습니까? (0) | 2020.08.08 |
dyld : 라이브러리가로드되지 않음 : @ rpath / libswiftAVFoundation.dylib (0) | 2020.08.08 |