Никогда не видел перед циклом С++

Я преобразовал алгоритм С++ в С#. Я наткнулся на это для цикла:

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

Он не дает ошибок в С++, но он работает в С# (не может преобразовать int в bool). Я действительно не могу понять это для цикла, где это условие?

Может кто-нибудь объяснит?

PS. Просто проверить, чтобы адаптировать VECTOR к СПИСОК   b.back() соответствуют   б [b.Count-1]

Ответ 1

Условие цикла for находится посередине между двумя точками с запятой ;.

В С++ нормально поставить почти любое выражение как условие: все, что оценивается до нуля, означает false; ненулевое значение означает true.

В вашем случае условие u--: при преобразовании в С# просто добавьте != 0:

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

Ответ 2

Много точных ответов, но я думаю, что стоит записать эквивалентный цикл 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];
}

Вы можете рассмотреть возможность реорганизации в формате while() при переходе на С#. По-моему, это яснее, меньше ловушки для новых программистов и одинаково эффективно.

Как указывали другие, но чтобы завершить мой ответ, чтобы заставить его работать на С#, вам нужно изменить 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];
}

Лучше быть ясным, чем быть кратким.

Ответ 3

Условие u--;, потому что оно находится во второй позиции инструкции для.

Если значение u--; отличается от 0, оно будет интерпретироваться как true (т.е. неявно отбрасывается в булево значение true). Если вместо этого его значение равно 0, оно будет отлито от false.

Это очень плохой код.

Обновление: Я обсуждал запись циклов "для" в этом сообщении . Его рекомендации можно резюмировать в следующих параграфах:

A для цикла является практичным, читаемым (как только вы привыкнете к нему) и но вам нужно использовать его хорошо. Из-за его необычного синтаксис, используя его слишком образно, это не очень хорошая идея.

Все части цикла for должны быть короткими и читаемыми. Имена переменных следует выбирать, чтобы было легко понять.

Этот пример явно нарушает эти рекомендации.

Ответ 4

Это будет форма С# вашего цикла.

// 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().

Что он делает, это изменить список и сохранить в массиве. Но в С# мы непосредственно имеем функцию, определенную системой для этого. Поэтому вам тоже не нужно писать этот цикл.

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

Ответ 5

Условие является результатом u--, который является значением u, прежде чем он будет уменьшен.

В C и С++ a int конвертируется в bool, неявно выполняя сравнение != 0 (0 - false, все остальное - true).

b.back() - последний элемент в контейнере, который b[b.size() - 1], когда size() != 0.

Ответ 6

u = b.size(), v = b.back()

- инициализация.

u--

- условие.

v = p[v]

- итерация

Ответ 7

В C все ненулевое значение true в "булевых" контекстах, таких как конечное условие цикла или условное выражение. В С# вы должны сделать эту проверку явной: u-- != 0.

Ответ 8

Как указано другими, тот факт, что С++ имеет неявное литье в boolean, означает, что условие u--, которое будет истинным, если значение отличное от нуля.

Стоит добавить, что у вас есть ложное предположение в вопросе "где условно". В С++ и С# (и других аналогично синтаксических языках) вы можете иметь пустой условный. В этом случае он всегда оценивает значение 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(;;), стоит знать, что это значит.

Ответ 9

все ответы верны: -

для цикла можно использовать различными способами следующим образом:

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.

Ответ 10

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

В приведенном выше коде u и v инициализируются с помощью b.size() и b.back().

Каждый раз, когда условие проверяется, оно также выполняет инструкцию декремента i.e. u--.

Цикл for выйдет, когда u станет 0.

Ответ 11

Ошибка, встречающаяся в С#, сама устраняет сомнения. For-loop ищет

FALSE

условие прекращения. И, как мы знаем,

(BOOL) FALSE = (int) 0

но С# не может обрабатывать это самостоятельно, в отличие от С++. Таким образом, условие, которое вы ищете,

и -

но вы должны явно указать условие в С# как

u--!= 0

или

u-- > 0

Но постарайтесь избежать такой практики кодирования.

while loop

указанный выше в ответе, является одной из наиболее упрощенных версий вашего

для цикла.

Ответ 12

Если вы привыкли к C/С++, этот код не так уж трудно прочитать, хотя он довольно краткий и не такой классный код. Поэтому позвольте мне объяснить те части, которые больше Cism, чем что-либо еще. Прежде всего, общий синтаксис цикла C for выглядит следующим образом:

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

Код инициализации запускается один раз. Затем условие проверяется перед каждым циклом, и, наконец, приращение вызывается после каждого цикла. Итак, в вашем примере вы найдете условие u--

Почему u-- работает как условие в C, а не С#? Потому что C неявно преобразует много вещей, и это может вызвать проблемы. Для числа любое значение, отличное от нуля, истинно, а ноль - false. Таким образом, он будет обратный отсчет с b.size() - 1 до 0. Наличие побочного эффекта в состоянии немного раздражает, и было бы предпочтительнее поместить его в инкрементную часть цикла for, хотя много C код делает это. Если бы я писал это, я бы сделал это более как это:

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.