'도(do)'가 필요할 때가 있나요?}, ( )" 루프 중?
Bjarne Strostrup(C++ 크리에이터)은 "do/while" 루프를 피하고 대신 "while" 루프의 관점에서 코드를 쓰는 것을 선호한다고 말한 적이 있다.[아래 인용문 참조]
이 말을 듣고 나는 이것이 사실이라는 것을 알았다.어떻게 생각하세요?대신 "while"을 사용하는 경우보다 "do/while"이 훨씬 깨끗하고 이해하기 쉬운 예가 있습니까?
몇 가지 답변에 대해: 예, "do/while"과 "while"의 기술적 차이를 이해합니다.이것은 루프를 수반하는 가독성과 코드 구조에 관한 보다 깊은 질문입니다.
다른 방법으로 묻겠습니다: "do/while"을 사용하는 것이 금지되었다고 가정해 보겠습니다. "while"을 사용하여 부정한 코드를 작성할 수밖에 없는 현실적인 예가 있습니까?
"C++ 프로그래밍 언어"에서 6.3.3:
내 경험상, 실행 선언은 오류와 혼란의 원천이다.그 이유는 본문이 항상 상태를 평가하기 전에 한 번 실행되기 때문입니다.하지만 신체가 제대로 작동하기 위해서는, 그 상태와 매우 비슷한 것이 첫 번째 단계에서도 견뎌야 한다.프로그램을 처음 작성 및 테스트했을 때나 이전 코드가 수정된 후에 예상대로 유지되지 않는 경우가 많습니다.저도 '앞에서 볼 수 있는 곳'이 좋아요. 결과적으로, 나는 행동 문구를 피하는 경향이 있다. - Bjarne
Do/while 루프는 ES.75로서 C++ 핵심 가이드라인에 포함되어 있는 권장 사항입니다.do-statement는 피하십시오.
네, 루프가 while loop으로 다시 작성될 수 있지만 while loop을 항상 사용하는 것이 더 낫다는 것에는 동의하지 않습니다.항상 한 번 이상 실행하면서 매우 유용한 속성입니다(가장 일반적인 예로는 (키보드를 통한) 입력 확인)
#include <stdio.h>
int main() {
char c;
do {
printf("enter a number");
scanf("%c", &c);
} while (c < '0' || c > '9');
}
물론 이 루프는 잠시 후 다시 작성할 수 있지만, 일반적으로는 훨씬 더 우아한 솔루션으로 간주됩니다.
우선, 저는 동의해요.do-while
가 어렵다while
.
해놓고도 도 그 이유를 못했다는 .do-while
언어에도 존재합니다.을 사용하다
를 들어 ''가 칩시다.do-while
를 틀다N
조건 체크. 조건의 결과는 루프 본체에 따라 달라집니다. R"R"로while
', '루프', '루프', '루프', '루프', '루프'가 나옵니다.N+1
상태 체크 대신 추가 체크가 무의미합니다.큰 가 되지 않지만, 다음과 같은 가 있다고 합시다.
something_t* x = NULL;
while( very_slowly_check_if_something_is_done(x) )
{
set_something(x);
}
첫 랩에 이 됩니다.즉, 「」는 알고 .이치노x
아직 아무것도 정해지지 않았어요.그럼 왜 쓸데없는 오버헤드 코드를 실행했을까요?
상태 내 코드가 비교적 느린 실시간 임베디드 시스템을 코딩할 때(하드웨어 주변기기에서 응답 확인) 바로 이 목적을 위해 do-while을 사용하는 경우가 많습니다.
이것은 지금까지 본 것 중 가장 깨끗한 것이다이것은 do-while 루프가 없는 Python에게 권장되는 관용어입니다.
주의할 점은 ''는 가질 수 입니다.continue
<setup code>
중단 조건을 뛰어넘을 수 있지만, 실행 시간의 이점을 보여주는 예 중 조건 전에 계속할 필요가 있는 것은 없습니다.
while (true) {
<setup code>
if (!condition) break;
<loop body>
}
여기에서는 위의 do-while 루프의 몇 가지 가장 좋은 예에 적용됩니다.
while (true) {
printf("enter a number");
scanf("%c", &c);
if (!(c < '0' || c > '9')) break;
}
입니다.//get data
, 짧다//process data
을 사용하다
while (true) {
// get data
if (data == null) break;
// process data
// process it some more
// have a lot of cases etc.
// wow, we're almost done.
// oops, just one more thing.
}
다음과 같은 일반적인 관용구는 나에게 매우 직설적인 것 같다.
do {
preliminary_work();
value = get_value();
} while (not_valid(value));
를 회피하기 do
음음음같 뭇매하다
value = make_invalid_value();
while (not_valid(value)) {
preliminary_work();
value = get_value();
}
첫 번째 줄은 테스트가 항상 참으로 평가되도록 하기 위해 사용됩니다.다시 말해, 시험은 항상 처음에 불필요한 것이다.만약 이 불필요한 테스트가 없다면, 첫 번째 과제를 생략할 수도 있다.이 코드는 마치 스스로 싸우는 것 같은 느낌을 줍니다.
, 「 」는do
옵션입니다.
나는 데이비드 보작의 예를 좋아한다.그러나 악마의 옹호자 역할을 하기 위해서는 적어도 한 번 실행하고 싶은 코드를 다른 함수로 분리하여 가장 읽기 쉬운 솔루션을 실현할 수 있다고 생각합니다.예를 들어 다음과 같습니다.
int main() {
char c;
do {
printf("enter a number");
scanf("%c", &c);
} while (c < '0' || c > '9');
}
다음과 같은 경우가 있습니다.
int main() {
char c = askForCharacter();
while (c < '0' || c > '9') {
c = askForCharacter();
}
}
char askForCharacter() {
char c;
printf("enter a number");
scanf("%c", &c);
return c;
}
(잘못된 구문은 모두 삭제해 주세요.저는 C 프로그래머가 아닙니다)
do { ... } while (0)
는 매크로가 올바르게 동작하도록 하기 위한 중요한 구성입니다.
실제 코드로 중요하지 않은 경우에도(반드시 동의할 필요는 없지만) 프리프로세서의 결함을 수정하는 데 중요합니다.
편집: 오늘 내 코드로 하면 훨씬 깨끗해지는 상황에 직면했습니다.쌍으로 구성된 LL/SC 명령의 크로스 플랫폼 추상화를 만들고 있었습니다.이들은 다음과 같이 루프에서 사용해야 합니다.
do
{
oldvalue = LL (address);
newvalue = oldvalue + 1;
} while (!SC (address, newvalue, oldvalue));
(전문가는 SC 구현에서는 오래된 가치가 사용되지 않는다는 것을 알 수 있지만, 이 추상화를 CAS에서 에뮬레이트할 수 있도록 포함되어 있습니다.)
LL과 SC는 do/hile이 동등한 while 형식보다 훨씬 깨끗한 상황을 보여주는 좋은 예입니다.
oldvalue = LL (address);
newvalue = oldvalue + 1;
while (!SC (address, newvalue, oldvalue))
{
oldvalue = LL (address);
newvalue = oldvalue + 1;
}
이러한 이유로 Google Go가 do-while constructure를 삭제하기로 결정했다는 사실에 매우 실망했습니다.
구조화 프로그램 정리를 읽습니다.do{} while()은 항상 while() do{}(으)로 다시 쓸 수 있습니다.순서, 선택, 반복만 있으면 됩니다.
루프 본체에 포함된 것은 항상 루틴에 캡슐화될 수 있으므로 while() do{}을(를) 사용해야 하는 더러움이 다음보다 더 심해질 필요는 없습니다.
LoopBody()
while(cond) {
LoopBody()
}
가독성이 중요합니다.
코드의 판독성이 높아지면, 코드의 유지보수에 있어서의 골칫거리가 경감되어 콜라보레이션이 향상됩니다.
대부분의 경우 다른 고려사항(최적화 등)은 훨씬 덜 중요합니다.
여기서 코멘트를 받았으니 자세히 설명하겠습니다.
코드 스니펫 A가 있는 경우do { ... } while()
보다 쉬워요.while() {...}
그럼 난 A에게 투표할 거야B를 선호하는 경우, 루프 조건이 "앞으로" 표시되며, 더 읽기 쉽다고 생각되면(따라서 유지 보수 가능 등), B를 사용하십시오.
제 요점은 여러분(및 동료)이 보기 쉬운 코드를 사용하라는 것입니다.물론 선택은 주관적이다.
do-while은 사후 조건이 있는 루프입니다.루프 본문을 적어도1회 실행해야 하는 경우에 필요합니다.이것은 루프 조건을 합리적으로 평가할 수 있도록 하기 전에 몇 가지 액션이 필요한 코드에 필요합니다.while 루프에서는 2개의 사이트에서 초기화 코드를 호출해야 하며, do-loop에서는 1개의 사이트에서만 호출할 수 있습니다.
또 다른 예로는 첫 번째 반복이 시작될 때 이미 유효한 개체가 있기 때문에 첫 번째 반복이 시작되기 전에 아무것도(루프 조건 평가 포함)를 실행하고 싶지 않은 경우를 들 수 있습니다.예를 들어 FindFirstFile/FindNextFile Win32 함수가 있습니다.FindFirstFile은 오류 또는 검색 핸들을 첫 번째 파일로 되돌리고 FindNextFile은 오류를 반환할 때까지 호출합니다.
유사 코드:
Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
do {
process( params ); //process found file
} while( ( handle = FindNextFile( params ) ) != Error ) );
}
조건이 충족될 때까지 무언가를 "수행"하고 싶을 때 유용합니다.
잠시 후 다음과 같이 퍼지할 수 있습니다.
while(true)
{
// .... code .....
if(condition_satisfied)
break;
}
(양자의 차이를 알고 있다고 가정)
Do/While은 조건이 체크되고 while 루프가 실행되기 전에 부트스트랩/사전 초기화 코드에 적합합니다.
코딩 규약에서는
- 만약/그동안/...조건에 부작용이 없다면
- 변수를 초기화해야 합니다.
우리는 한 도 그런 이 없다.do {} while(xx)
★★★★
int main() {
char c;
do {
printf("enter a number");
scanf("%c", &c);
} while (c < '0' || c > '9');
}
다음과 같이 고쳐 씁니다.
int main() {
char c(0);
while (c < '0' || c > '9'); {
printf("enter a number");
scanf("%c", &c);
}
}
그리고.
Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
do {
process( params ); //process found file
} while( ( handle = FindNextFile( params ) ) != Error ) );
}
다음과 같이 고쳐 씁니다.
Params params(xxx);
Handle handle = FindFirstFile( params );
while( handle!=Error ) {
process( params ); //process found file
handle = FindNextFile( params );
}
내 생각에 그것은 오직 개인의 선택이다.
대부분의 경우 do를 다시 쓰는 방법을 찾을 수 있습니다.while loop을 while loop으로 합니다.다만, 항상은 아닙니다.또, 경우에 따라서는, 현재의 상황에 맞추어 「실행중」을 작성하는 것이, 보다 논리적인 방법이 될 수 있습니다.
TimW로부터의 회답은, 상기의 내용을 나타내고 있습니다.핸들이 달린 두 번째 것은 특히 내 생각에 더 지저분하다.
다음 이유만으로 사용하는 경우는 거의 없습니다.
루프가 포스트 조건을 체크해도 포스트 조건을 처리하지 않도록 루프 내에서 이 포스트 조건을 체크해야 합니다.
샘플 의사 코드를 취합니다.
do {
// get data
// process data
} while (data != null);
이론적으로는 단순하게 들리지만 실제 상황에서는 아마도 그렇게 보일 것입니다.
do {
// get data
if (data != null) {
// process data
}
} while (data != null);
IMO에 추가 "if" 체크는 가치가 없습니다.잠시 루프가 아닌 실행 시간을 단축하는 것이 더 간단한 경우는 거의 없습니다.YMMV
Dan Olson의 답변에 대한 불명(구글)의 질문/댓글에 대한 답변:
"{...}을 실행합니다.반면 (0)은 매크로를 올바르게 동작시키기 위한 중요한 구성입니다."
#define M do { doOneThing(); doAnother(); } while (0)
...
if (query) M;
...
어떻게 요?do { ... } while(0)
는 another()를 하다
do-while 루프는 항상 while 루프로 고쳐 쓸 수 있습니다.
루프 중에만 사용할지, 루프 중에 사용할지, 루프 중에 사용할지 여부는 주로 미학에 대한 취향과 현재 작업 중인 프로젝트의 관례에 따라 달라집니다.
개인적으로 나는 루프 불변 IMHO에 대한 추론을 단순화하기 때문에 루프 불변 IMHO를 선호한다.
do-while 루프가 필요한 상황이 있는지 여부를 확인합니다.대신
do
{
loopBody();
} while (condition());
언제든지 할 수 있다
loopBody();
while(condition())
{
loopBody();
}
따라서 어떤 이유로 do-while을 사용할 필요가 없습니다.(물론 이 예에서는 DRY를 위반하고 있습니다만, 이것은 개념 증명에 지나지 않습니다.지금까지의 경험으로는 일반적으로 DO-while 루프를 While 루프로 변환하고 구체적인 사용 사례에서 DRY를 위반하지 않는 방법이 있습니다.)
로마에 가면 로마법을 따르라.
BTW: 찾으시는 견적서는 다음과 같습니다(섹션 6.3.3의 마지막 단락 [1]).
내 경험으로 볼 때 do-statement는 오류와 혼란의 원인이다.그 이유는 본문이 항상 상태를 테스트하기 전에 한 번 실행되기 때문입니다.그러나, 신체가 올바르게 기능하려면, 1차 주행에서 최종 조건과 유사한 조건이 유지되어야 한다.내가 예상했던 것보다 더 자주 나는 이러한 조건들이 사실이 아니라는 것을 알았다.이 경우는, 문제의 프로그램을 처음부터 작성하고 나서 테스트했을 때와 코드를 변경했을 때 모두 마찬가지입니다.또, 「앞에서 볼 수 있는」조건을 선호합니다.그러므로 나는 행동 선언을 피하는 경향이 있다.
(주의: 독일어판 번역본입니다.만약 당신이 영문판을 소유하고 있다면, 그의 원래 표현에 맞게 인용문을 수정해 주세요.안타깝게도 애디슨 웨슬리는 구글을 싫어합니다.)
[1] B. 스트루스트럽:C++ 프로그래밍 언어.제3판애디슨 웨슬리, 레딩, 1997년
다음과 같은 것을 고려합니다.
int SumOfString(char* s)
{
int res = 0;
do
{
res += *s;
++s;
} while (*s != '\0');
}
공교롭게도 '0'은 0이지만, 요점을 파악해 주셨으면 합니다.
do/while의 문제는 C에서의 구현에 있습니다.while 키워드가 재사용되기 때문에 실수처럼 보여서 사람들을 혼란스럽게 하는 경우가 많습니다.
루프와 do/while을 do/until 또는 repeat/until로 변경했다면 루프(확실히 편리하고 일부 루프를 코드하는 올바른 방법)는 그다지 문제가 되지 않을 것입니다.
C로부터도 이 미안한 선택을 계승한 JavaScript에 대해서, 전에도 큰소리를 친 적이 있습니다.
몇 단계 전으로 거슬러 올라가겠지만
do
{
output("enter a number");
int x = getInput();
//do stuff with input
}while(x != 0);
반드시 읽을 수 있는 것은 아니지만 사용할 수 있습니다.
int x;
while(x = getInput())
{
//do stuff with input
}
0 이외의 숫자를 사용하여 루프를 종료하는 경우
while((x = getInput()) != 4)
{
//do stuff with input
}
그러나 다시 한 번 가독성이 떨어집니다.조건부 내에서 할당문을 사용하는 것은 나쁜 관행으로 간주되는 것은 말할 것도 없고, 루프에 초기 실행임을 나타내기 위해 "예약된" 값을 할당하는 것보다 더 콤팩트한 방법이 있음을 지적하고 싶습니다.
언급URL : https://stackoverflow.com/questions/994905/is-there-ever-a-need-for-a-do-while-loop
'source' 카테고리의 다른 글
Jest를 사용하여 코드 커버리지 보고서를 얻는 방법은 무엇입니까? (0) | 2022.09.13 |
---|---|
JavaScript로 화면 해상도를 검출하는 방법 (0) | 2022.09.13 |
자바 추상 인터페이스 (0) | 2022.09.13 |
dd-mm-yyy 문자열을 최신 상태로 변환합니다. (0) | 2022.09.13 |
Log4j2 구성 - log4j2 구성 파일을 찾을 수 없습니다. (0) | 2022.09.12 |