Eu estava convertendo um algoritmo C ++ para c #. Me deparei com isso para loop:
for (u = b.size(), v = b.back(); u--; v = p[v])
b[u] = v;
Ele não fornece erro em C ++, mas em C # (não é possível converter int em bool). Eu realmente não consigo descobrir isso para loop, onde está a condição?
Alguém pode me explicar?
PS. Apenas para verificar, para adaptar um VETOR a uma LIST, b.back () corresponde a b [b.Count-1]?
u--
. Os pontos-e-vírgulas são usados para delimitar as várias partes dafor
declaração.; u-- != 0;
b
,u
,v
, etc. A única razão pela qual eles foram nomeados dessa maneira é porque alguém queria olhar inteligente, fazendo seu código ilegível.do
significa em C ++" - receberá milhares de acessos de iniciantes à procura de um tutorial.Respostas:
A condição do
for
loop está no meio - entre os dois ponto e vírgula;
.Em C ++, não há problema em colocar quase qualquer expressão como condição: qualquer coisa que avalie como zero significa
false
; meios diferentes de zerotrue
.No seu caso, a condição é
u--
: quando você converter para C #, basta adicionar!= 0
:fonte
u = b.size() - 1
.Muitas respostas precisas, mas acho que vale a pena escrever o equivalente while.
É equivalente a:
Você pode refatorar para o formato while () ao traduzir para C #. Na minha opinião, é mais claro, menos uma armadilha para novos programadores e igualmente eficiente.
Como outros já apontaram - mas para completar minha resposta - para que funcione em C #, você precisaria mudar
while(u--)
parawhile(u-- != 0)
.... ou
while(u-- >0)
apenas no caso de você começar negativo. (OK,b.size()
nunca será negativo - mas considere um caso geral em que talvez algo mais tenha sido inicializado em u).Ou, para deixar ainda mais claro:
É melhor ser claro do que ser conciso.
fonte
while (u-- >0)
formulário. Se o espaçamento for prejudicado, você poderá acabar com um loop "de baixo a zero":,while (u --> 0)
que tende a confundir todos à primeira vista. ( Não tenho certeza se é válido C #, mas é em C, e eu acho que pode ser bem em C ++? )for
vez dewhile
é precisamente que você coloque a inicialização e o incremento / decremento em uma instrução, e isso não necessariamente torna o código mais difícil de entender. Caso contrário, não deveríamos estar usandofor
.--
token seguido por um>
token. Dois operadores separados. Um loop "até zero" é apenas uma combinação direta de pós-decremento e maior que. A sobrecarga de operadores em C ++ não cria novos operadores, apenas redireciona os existentes.A condição é
u--;
, porque está na segunda posição da instrução for .Se o valor de
u--;
for diferente de 0, será interpretado comotrue
(ou seja, convertido implicitamente no valor booleanotrue
). Se, em vez disso, seu valor for 0, ele será convertido emfalse
.Este é um código muito ruim .
Atualização: discuti a redação dos loops "for" nesta postagem do blog . Suas recomendações podem ser resumidas nos seguintes parágrafos:
Este exemplo viola claramente essas recomendações.
fonte
Esse será o formato C # do seu loop.
Apenas substitua o equivalente por size () e back ().
O que ele faz é reverter a lista e armazenar em uma matriz. Mas em C #, temos diretamente uma função definida pelo sistema para isso. Então você não precisa escrever esse loop também.
fonte
v = b.back();
para fora do para intializer não basta mudar a forma como ele funciona, uma vez que ov = p[v]
é substituído porv = b.back();
foi executado uma vez antes do início das iterações ev = p[v]
foi executado no início de cada iteração. Nessa versão C #,v = p[v]
ainda é executado no início de cada iteração, masv = b.back();
é executado logo após, alterando o valor dav
próxima instruçãob[u] = v;
. (talvez a pergunta tenha sido editada depois que você a leu)v = b.back()
. Você o executa em todas as iterações do loop, e não apenas no primeiro - não sabemos o queback()
faz (existem efeitos colaterais? Altera a representação interna deb
?), Portanto esse loop não é equivalente ao do a questão.v = b.back()
fosse movido para fora do loop, acima dele. (Além disso, se você está tentando responder a alguém, use@
na frente de seu nome, então temos uma notificação)é inicialização.
é a condição.
é a iteração
fonte
A condição é o resultado de
u--
, que é o valor deu
antes de ser diminuído.Em C e C ++, um
int
é convertível em booleano implicitamente fazendo uma!= 0
comparação (0 éfalse
, tudo o resto étrue
).b.back()
é o último elemento em um contêiner, ou sejab[b.size() - 1]
, quandosize() != 0
.fonte
Em C, tudo que não é zero está
true
em contextos "booleanos", como a condição final do loop ou uma instrução condicional. Em C # você tem que fazer essa verificação explícita:u-- != 0
.fonte
Conforme declarado por outros, o fato de o C ++ ter implícito a conversão para booleano significa que o condicional é
u--
, o que será verdadeiro se o valor for diferente de zero.Vale acrescentar que você tem uma falsa suposição ao perguntar "onde está o condicional". No C ++ e no C # (e em outras linguagens com sintaxe semelhante), você pode ter uma condicional vazia. Neste caso, sempre avaliada como verdadeira, então o circuito continua para sempre, ou até algumas outras saídas condicioná-lo (via
return
,break
outhrow
).De fato, qualquer parte da instrução for pode ser deixada de fora, caso em que simplesmente não é executada.
Em geral,
for(A; B; C){D}
oufor(A; B; C)D;
se torna:Qualquer um ou mais de A, B, C ou D pode ser deixado de fora.
Como resultado disso, algum favor
for(;;)
para loops infinitos. Faço isso porque, emborawhile(true)
seja mais popular, li isso como "até que a verdade acabe sendo verdadeira", o que soa um pouco apocalíptico em comparação com a minha leiturafor(;;)
como "para sempre".É uma questão de gosto, mas como não sou a única pessoa no mundo a gostar
for(;;)
, vale a pena saber o que isso significa.fonte
todas as respostas estão corretas: -
O loop for pode ser usado de várias maneiras, como a seguir:
fonte
No código acima,
u
ev
são inicializados comb.size()
eb.back()
.Toda vez que a condição é verificada, ela também executa a instrução de decremento, ou seja
u--
.O
for
loop sairá quandou
se tornar0
.fonte
O erro encontrado no próprio C # limpa a dúvida. O loop for procura um
condição para terminar. E como sabemos,
mas o C # não pode processar isso sozinho, diferentemente do C ++. Portanto, a condição que você está procurando é
mas você deve fornecer explicitamente a condição em C # como
ou
Mas ainda tente evitar esse tipo de prática de codificação. o
indicado acima em resposta é uma das versões mais simplificadas do seu
fonte
Se você está acostumado a C / C ++, esse código não é tão difícil de ler, embora seja bastante conciso e não muito bom. Então, deixe-me explicar as partes que são mais Cism do que qualquer outra coisa. Primeiro, a sintaxe geral de um loop C for assim:
O código de inicialização é executado uma vez. Em seguida, a condição é testada antes de cada loop e, por fim, o incremento é chamado após cada loop. Então, no seu exemplo, você encontrará a condição
u--
Por que
u--
funciona como uma condição em C e não em C #? Porque C converte implicitamente muitas coisas em bools e isso pode causar problemas. Para um número, qualquer coisa que não seja zero é verdadeira e zero é falso. Portanto, ele fará a contagem regressiva de b.size () - 1 a 0. Ter o efeito colateral na condição é um pouco chato e seria preferível colocá-lo na parte de incremento do loop for, embora muito C código faz isso. Se eu estivesse escrevendo, faria mais assim:A razão para isso é, pelo menos para mim, é mais claro. Cada parte do loop for faz seu trabalho e nada mais. No código original, a condição estava modificando a variável. A parte do incremento estava fazendo algo que deveria estar no bloco de código etc.
O operador de vírgula também pode estar jogando você para um loop. Em C, algo parecido
x=1,y=2
com uma declaração no que diz respeito ao compilador e se encaixa no código de inicialização. Apenas avalia cada uma das partes e retorna o valor da última. Então, por exemplo:imprimiria 2.
fonte