C ++ for 루프 전에는 본 적이 없다


164

C ++ 알고리즘을 C #으로 변환하고있었습니다. 이 for 루프를 발견했습니다.

for (u = b.size(), v = b.back(); u--; v = p[v]) 
b[u] = v;

C ++에서는 오류가 없지만 C #에서는 수행합니다 (int를 bool로 변환 할 수 없음). 나는 이것이 for 루프를 알아낼 수 없다. 조건은 어디에 있습니까?

누군가 설명해 주시겠습니까?

추신. 확인하기 위해 VECTOR를 LIST에 적용하려면 b.back ()이 b [b.Count-1]에 해당합니까?


35
상태는 어디에 있습니까? 그렇습니다 u--. 세미콜론은 for문장 의 다양한 부분을 구분하는 데 사용됩니다 .
David Heffernan

77
이것은 정상적인 루프입니다. C #은 숫자를 묵시적으로 변환하지 않으므로 조건을 다음과 같이 바꿔야합니다.; u-- != 0;
R. Martinho Fernandes

28
@Jessie Good-- 좋은 코드는 언어에서 허용되는 것과 아무 관련이 없으며, 동료가 코드를 읽는 데 걸리는 시간과 관련이 있습니다. 어떤 종류의 혼란이 발생하더라도 합법적 인 경우에도 최선의 해결책은 아닙니다. 더 자세한 솔루션은 간결한 솔루션보다 훨씬 낫습니다. 대부분의 컴파일러는 같은 방식으로 컴파일합니다.
Bill K

18
나는 코드를 변환 한 후, 당신은 변수들에게보다 더 나은 이름을주고, 그 희망 b, u, v, 등 사람이 자신의 코드를 읽을함으로써 스마트보고 싶어 때문에이 방법으로 선정됐다 유일한 이유입니다.
Dan

33
@ houbysoft : 이것은 일반적인 stackoverflow 문제입니다. 특정 리서치 영역에서 매우 상세하고 잘 연구되고 흥미로운 질문을하여 어렵고 흥미로운 문제에 대한 해결책을 제시하고 어려운 일에 대한 연구 후에 그러한 질문에 대답하면 몇 가지만 얻을 수 있습니다. 현장의 몇몇 전문가로부터 12 명의 방문객과 1 ~ 2 개의 공감대 빠르게 많은 답변을 얻으려면 이와 같은 질문을하고 답변해야합니다. "PHP에서 두 숫자를 어떻게 추가합니까?", " doC ++의 의미는 무엇입니까? "-초보자를 대상으로 자습서를 찾고 수천 건의 인기를 얻습니다.
vsz

답변:


320

for루프 상태 는 두 세미콜론 사이의 중간에 ;있습니다.

C ++에서는 거의 모든 표현식을 조건으로 두는 것이 좋습니다. 0으로 평가되는 것은 의미입니다 false. 0이 아닌 의미 true.

귀하의 경우 조건은 u--: C #으로 변환 할 때 간단히 추가하십시오 != 0.

for (u = b.size(), v = b.back(); u-- != 0; v = p[v]) 
    b[u] = v; //                     ^^^^ HERE

55
그건 그렇고, 토마스는 쉼표를 사용하여 혼동되었을 수 있습니다. 세미콜론과는 매우 다르기 때문에 for 루프의 한 섹션에서 여러 가지 작업을 수행 할 수 있습니다 (이 경우 두 변수를 초기화했습니다). 마지막 으로이 특이한 구조를 확인했을 때 가장 읽기 쉬운 솔루션으로 간주되지 않았으므로 일부 사람들은 눈살을 찌푸 릴 수 있습니다.
Bill K

2
내가 올바르게 기억하고 쉼표를 포함하는 표현식은 오른쪽에 마지막 하위 표현식의 값이 있습니다. 이것은 C에서 왔으며 for 루프뿐만 아니라 모든 표현식에서 사용할 수 있습니다.
Giorgio

7
@Roger 이것은 시작이 아니라 루프의 끝에서 u를 감소시키기 때문에 같은 루프가 아닙니다. 실제로 u = b.size() - 1대신 대신 초기화해야합니다 .
Didier L

Fyi : 방금 500K 한도를 넘었습니다. 어딘가에서 백만 번째 고객이되어 뭔가를이기는 것과 같은가? 어쨌든 많은 축하합니다. 항상 정확한 답을 찾으십시오! 계속 가라. 이 세기 말에 백만 개의 물건을 만들어 봅시다.
GhostCat

165

많은 정확한 답변이 있지만 동등한 while 루프를 작성하는 것이 좋습니다.

for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

다음과 같습니다.

u = b.size();
v = b.back();
while(u--) {
   b[u] = v;
   v = p[v];
}

C #으로 변환 할 때 while () 형식으로 리팩토링을 고려할 수 있습니다. 내 생각에 그것은 새 프로그래머에게는 더 명확하고 덜 함정이며 똑같이 효율적입니다.

다른 사람들이 지적했지만 (내 대답을 완성시키기 위해) C #에서 작동하게하려면로 변경 while(u--)해야 while(u-- != 0)합니다.

... 또는 while(u-- >0)u가 음수로 시작하는 경우. (좋아, b.size()절대 부정적인 것은 아니지만 아마도 다른 것이 u를 초기화 한 일반적인 경우를 고려하십시오).

또는 더 명확하게하기 위해 :

u = b.size();
v = b.back();
while(u>0) {
   u--;
   b[u] = v;
   v = p[v];
}

간결한 것보다 명확하게하는 것이 좋습니다.


29
이 답변은 잘못된 코드를 명확하게 할뿐만 아니라 좋은 대안을 제공합니다. 1 개 !!
polvoazul

2
제쳐두고, 나는 while (u-- >0)양식에 주의를 기울일 것 입니다. 간격이 엉망이되면 "0에서 down"루프로 끝날 수 있습니다. while (u --> 0)이는 모든 사람을 언뜻보기에 혼란스럽게 만드는 경향이 있습니다. ( 유효한 C #인지 확실하지 않지만 C로되어 있으며 C ++에서도 가능하다고 생각하십니까? )
Izkata

9
귀하의 코드가 반드시 더 명확하다고 생각하지 않습니다. for대신 요점은 while초기화와 증분 / 감소를 하나의 명령문에 넣는 것이므로 코드를 이해하기 어렵게 만드는 것은 아닙니다. 그렇지 않으면, 우리는 전혀 사용하지 않아야 for합니다.
musiphil

1
가능한 한 적은 코드를 다시 작성하는 것도 중요합니다. (for 루프는 결국 변경 될 수 있습니다.) "u--"를 두 개의 별도 위치에두고 루프가 더 명확하지 않습니다 (for 루프가 한 눈에 한눈에 볼 수 있습니다. 스캔해야합니다). 여러 줄로). 간결한 것도 장점이 있습니다. 그들을 경시하지 마십시오. 그래도 다른 방법으로 쓸 수있는 좋은 예입니다. C ++의 문장에 익숙하지 않은 사람 (또는 어쩌면 전혀)을 이해하기가 더 쉽습니다.
NotKyon

2
@ Izkata : 그것은 결코 연산자가 아니며 --토큰과 토큰으로 구문 분석됩니다 >. 두 개의 별도 연산자. "0에서 다운"루프는 단순히 감소 후와 그 이상을 간단하게 조합 한 것입니다. C ++ 연산자 오버로딩은 새 연산자를 만들지 않고 기존 연산자를 용도 변경합니다.
벤 Voigt

66

조건은 for 명령 u--;의 두 번째 위치에 있기 때문에입니다 .

의 값이 u--;0과 다른 true경우이 값 은 (즉, boolean value로 암시 적으로 캐스트 됨) 으로 해석됩니다 true. 대신 값이 0이면로 캐스팅됩니다 false.

이것은 매우 나쁜 코드 입니다.

업데이트 :블로그 게시물 에서 "for"루프 작성에 대해 논의 했습니다 . 권장 사항은 다음 단락에 요약되어 있습니다.

for 루프는 실용적이고 읽기 쉽고 (한 번 익숙해지면) 간결한 구성이지만 잘 사용해야합니다. 흔하지 않은 구문으로 인해 너무 상상적인 방식으로 사용하는 것은 좋은 생각이 아닙니다.

for 루프의 모든 부분은 짧고 읽을 수 있어야합니다. 이해하기 쉽도록 변수 이름을 선택해야합니다.

이 예는 이러한 권장 사항을 분명히 위반합니다.


3
아니면 u == 0에서 멈출 것입니다 ...?
Thomas

2
아니; C ++에는 int에서 bool 로의 암시 적 변환이 있으며 0은 false로 변환됩니다. 루프는 u-- == 0 일 때 종료됩니다. C #에는 그러한 암시 적 변환이 없으므로 명시 적으로 u-- == 0이라고 말해야합니다. 편집 : 이것은 첫 번째 주석에 대한 응답입니다.
Chris

48
이다 끔찍한 일 아주 간단한 이유 코드; 읽을 때 쉽게 이해할 수 없었습니다. "영리한", "해킹"입니다. 코딩 구조의 조합과 장면 뒤에서 어떻게 작동하는지에 대한 지식을 사용하여 언어 작성자가 구상하고 대부분의 사람들에게 전달한 형식이 아니기 때문에 업무를 수행하지만 이해를 거부하는 구조를 만듭니다. 언어 사용자.
KeithS

4
훌륭한 답변입니다. "+1입니다."이것은 매우 나쁜 코드입니다. " statement;)
Sandman4

14
왜 그렇게 많은 사람들이 u 를 생각하는 것처럼 보지 못합니다. (C ++에서 암시 적) ! = 0 때문에 실제로 나쁜 코드 입니다. 분명히 코드를 사용하는 사람은 0 = false, 다른 모든 value = true 입니다. u의 사전 / 사후 증가와 관련하여 더 많은 혼동의 여지가 있거나 아마도 u = b.size ()항상 v = b.back () 전에 실행 된다고 가정하는 사람들이 있습니다 (내 이해는 정의되지 않은 실행 순서입니다. 그러나 나는 정정되어야한다.)
FumbleFingers

23

이것이 루프의 C # 형식입니다.

// back fetches the last element of vector in c++.
for (u = b.size(), v = b.back(); (u--) != 0; v = p[v]) 
{      
  b[u] = v;      
}

size () 및 back ()에 해당하는 것을 대체하십시오.

그것이하는 일은 목록을 뒤집고 배열에 저장하는 것입니다. 그러나 C #에서는이를 위해 시스템 정의 함수를 직접 가지고 있습니다. 따라서이 루프도 작성할 필요가 없습니다.

b = b.Reverse().ToArray();

1
취함으로써 v = b.back();가 있기 때문에, 당신은 단지 그것이 작동하는 방식을 변경하지 않은 대한 intializer 밖으로 v = p[v]우선합니다
주앙 포르텔

이 줄은 마지막에 실행되므로 v = p [v]는 최종 결과에 영향을 미치지 않습니다. 그리고 그 이후 v는 루프에서 참조되지 않습니다. 이 줄은 루프가 c ++에서 C #으로 어떻게 변환되는지 보여주기위한 것입니다.
Narendra

1
C ++ 코드 v = b.back();에서 반복이 시작되기 전에 한 번 v = p[v]실행되었으며 각 반복의 시작에서 실행되었습니다. 이 C # 버전 v = p[v]은 각 반복의 시작 부분에서 여전히 실행되지만 v = b.back();바로 다음에 실행 v되어 다음 명령어 의 값을 변경합니다 b[u] = v;. (아마도 질문을 읽은 후에 편집되었을 수도 있습니다)
João Portela

5
@Rain 문제는 v = b.back()입니다. 당신은 대신 첫 번째의 모든 루프 반복에서 실행해야 - 우리가 모르는 back()않는다 (어떤 부작용이있는가의 내부 표현을 변경 하는가? b,이 루프는 그래서?) 하지 의 하나에 해당 질문.
이즈 카타

1
@Rain 정확히, 자세히 살펴보십시오. 초기화 단계는 단지 루프가 시작되기 전에 한 번 발생 하지 의 시작 부분에 모든 반복 . v = b.back()루프 밖으로 루프 위로 이동 하면 코드가 정확 합니다. (또한, 당신이 누군가에게 응답하려고한다면, @그들의 이름 앞에서 사용하십시오 , 그래서 우리는 통지를받습니다)
Izkata


14

조건은의 결과이며 u--, u감소하기 전의 값입니다 .

C 및 C ++에서은 int 이다 암시 적으로 수행하여 부울로 변환 != 0비교 (0 false, 다른 모든 것들입니다 true).

b.back()인 용기 내의 마지막 요소 인 b[b.size() - 1]경우는 size() != 0.


11

C true에서 0이 아닌 모든 것은 루프 종료 조건 또는 조건문과 같은 "부울"컨텍스트에 있습니다. C #에서는 명시 적으로 확인해야합니다 u-- != 0.


이것은 OP의 문제가 아닙니다. 그는 단말기 상태 (즉,이 경우 'u--')의 평가에 대해 묻고 있습니다.
ApplePie

6

다른 사람들이 말했듯이 C ++에 부울로 암시 적 캐스트가 있다는 것은 조건부가임을 의미하며 u--, 값이 0이 아닌 경우에 해당됩니다.

"조건이 어디에 있습니까?"라는 잘못된 가정을 추가 할 가치가 있습니다. C ++ 및 C # (및 유사하게 구문이 지정된 언어)에서 빈 조건을 가질 수 있습니다. 이 경우 항상 루프가 영원히 계속, 또는, 그래서 true로 평가 다른 조건이 종료 될 때까지 그것을 (를 통해 return, break또는 throw).

for(int i = 0; ; ++i)
  doThisForever(i);

실제로 for 문의 일부를 생략 할 수 있으며이 경우에는 수행되지 않습니다.

일반적으로 for(A; B; C){D}또는 다음과 같이 for(A; B; C)D;됩니다.

{A}
loopBack:
if(!(B))
  goto escapeLoop;
{D}
{C}
goto loopBack;
escapeLoop:

A, B, C 또는 D 중 하나 이상을 제외 할 수 있습니다.

결과적으로 for(;;) 무한 루프에 유리 합니다. 나는 while(true)더 인기 가 있기 때문에 나는 "진실이 진실로 끝날 때까지"로 읽습니다. 이것은 for(;;) "영원히" 읽는 것과 비교하여 다소 묵시적인 것처럼 들립니다 .

그것은 맛의 문제이지만, for(;;)그것이 세상의 유일한 사람이 아니기 때문에 그것이 무엇을 의미하는지 아는 것이 가치가 있습니다.


4

모든 답변이 정확합니다 :-

for 루프는 다음과 같이 다양한 방식으로 사용될 수 있습니다.

Single Statement inside For Loop
Multiple Statements inside For Loop
No Statement inside For Loop
Semicolon at the end of For Loop
Multiple Initialization Statement inside For
Missing Initialization in For Loop
Missing Increment/Decrement Statement
Infinite For Loop
Condition with no Conditional Operator.

4
for (u = b.size(), v = b.back(); u--; v = p[v]) 
   b[u] = v;

위의 코드에서, u그리고 v초기화됩니다 b.size()하고 b.back().

조건을 확인할 때마다 감소 문도 실행 u--합니다.

for때 루프는 종료됩니다 u될 것입니다 0.


3

C # 자체에서 발생한 오류는 의심을 없애줍니다. for-loop는

그릇된

종료 조건. 그리고 우리가 알듯이

(BOOL) FALSE = (int) 0

그러나 C #과 달리 C #에서는이를 자체적으로 처리 할 수 ​​없습니다. 그래서 당신이 찾고있는 조건은

유--

그러나 C #에서 명시 적으로 조건을 제공해야합니다.

u--! = 0

또는

u--> 0

그러나 여전히 이런 종류의 코딩 연습을 피하십시오. 그만큼

while 루프

위에 언급 된 답변은 가장 단순화 된 버전 중 하나입니다.

for 루프.


@Downvoter : 솔루션에 만족하지 않는 한 Downvoting은 괜찮습니다. 동시에 답변을 개선 할 수 있도록 이유를 설명하는 데 시간을 내십시오.
Abhineet

3

C / C ++에 익숙하다면이 코드는 읽기가 어렵지 않지만 아주 간결하고 코드는 많지 않습니다. 그래서 다른 어떤 것보다 더 Cism 인 부분을 설명하겠습니다. 먼저 C for 루프의 일반적인 구문은 다음과 같습니다.

for (<initialization> ; <condition>; <increment>)
{
    <code...>
}

초기화 코드가 한 번 실행됩니다. 그런 다음 조건은 모든 루프 전에 테스트되고 마지막으로 증분이 모든 루프 후에 호출됩니다. 따라서 귀하의 예에서 조건은 다음과 같습니다.u--

u--C #이 아닌 C에서 조건으로 작동하는 이유는 무엇 입니까? C는 암시 적으로 너무 많은 것들을 변환하기 때문에 부패하고 문제를 일으킬 수 있습니다. 숫자가 0이 아닌 것은 true이고 0은 false입니다. 따라서 b.size ()-1에서 0으로 카운트 다운됩니다. 조건에서 부작용을 갖는 것은 약간 성가 시며 for 루프의 증분 부분에 넣는 것이 좋습니다. 코드가 이것을 수행합니다. 내가 쓰고 있다면 다음과 같이 할 것입니다.

for (u = b.size() - 1, v = b.back(); u>=0; --u) 
{
    b[u] = v;
    v = p[v]
}

그 이유는 적어도 나에게는 분명하다. for 루프의 각 부분은 작동하지만 다른 것은 없습니다. 원래 코드에서 조건은 변수를 수정했습니다. 증가 부분은 코드 블록 등에 있어야하는 일을하고있었습니다.

쉼표 연산자로 인해 루프가 발생할 수 있습니다. C에서는 x=1,y=2컴파일러가 관련되고 초기화 코드에 맞는 한 하나의 문장 처럼 보입니다. 각 부분을 평가하고 마지막 부분의 값을 반환합니다. 예를 들어 :

std::cout << "(1,2)=" << (1,2) << std::endl;

2를 인쇄합니다.


다시 쓰기의 문제는 b.size ()가 부호가 없으면 매우 오랫동안 반복된다는 것입니다. (또한 세미콜론이 누락되었습니다.) 그러나 최소한 " 'Dick and Jane'은 좋은 영어"접근 방식을 취하지 않았기 때문에 다른 많은 답변과 의견이 그랬습니다. 신 생물 및 기타 비 숙련 프로그래머가 읽을 수 있습니다.
Jim Balter
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.