[java] while sans instruction

Bonjour,
dans le code suivant, je reste bloqué dans le while. Je dois rajouter une instruction quelconque pour passer. Bizarre ?

while (!(line = rd.readLine()).contains("id=\"tdValiditeCV\"")); ig.valid.setText(line.substring(18, 28));

par exemple :

Je subodore que la condition n’est évaluée qu’une fois : puisqu’on lui demande de ne rien faire, il considère que la condition ne peut pas avoir changé d’état et qu’il est inutile de la réévaluer.
Est-ce exact ?

[quote=“blaisoth”]Bonjour,
dans le code suivant, je reste bloqué dans le while. Je dois rajouter une instruction quelconque pour passer. Bizarre ?

while (!(line = rd.readLine()).contains("id=\"tdValiditeCV\"")); ig.valid.setText(line.substring(18, 28));

par exemple :

Tu joues avec le feu je pense à rajouter des parenthèses de partout sans trop savoir ce qui se passe vraiment.
Si (line = rd.readLine()) est évalué à true, et non pas comme un objet line, tu obtiens une boucle infinie en lui appliquant un contain() derrière.
Idem pour le ! devant, est il évalué avant contain() ?
Soit tu te plonges dans ton bouquin qui énonce l’ordre de priorité de chaque opérateur et tu testes une à une les expressions que tu évalues pour voir comment elles sont réellement évaluées, soit tu découpes ton expression en deux :

  1. Tant qu’il y a des lignes à lire.
  2. Est-ce que cette ligne contient la chaine que tu veux.

[quote]Je subodore que la condition n’est évaluée qu’une fois : puisqu’on lui demande de ne rien faire, il considère que la condition ne peut pas avoir changé d’état et qu’il est inutile de la réévaluer.
Est-ce exact ?[/quote]
Il n’y a aucun rapport entre la condition de ta boucle et l’instruction à répéter dans ta boucle.
La condition sert juste à savoir s’il faut exécuter le contenu de la boucle.
Effectivement si dans une expression tu as des constantes VRAI && VRAI && VRAI && VRAI && FAUX je suppose qu’il ne va pas réinterpréter à chaque fois l’intégralité de la condition puisqu’elle ne variera jamais : il va peut etre la stocker en mémoire ?
Je fais pas trop de java, mais en C++ une instruction du type :
while (true) ;
Est évalué comme Tant que que c’est vrai j’exécute l’instruction vide.
Si tu demandes une boucle infinie, qui ne fais rien, ben c’est une boucle infinie qui s’exécute sans rien faire, point, la boucle n’est pas annulée pour autant.
Tu remarques que la seule chose qui peut changer de valeur dans ton contexte c’est readline.
As tu vérifié le nombre de lignes que tu avais ? S’il y en a qu’une seule, c’est normal que ça ne s’exécute qu’une seule fois (si la condition est bien formulée…).

Merci pour ta réponse SmallFitz, j’ai décomposé mais le problème persiste. Dans la boucle suivante, ig.getMontant() renvoie la chaîne correcte si celle-ci a été renseignée avant de rentrer dans la boucle ou si je décommente (et je ne vois tjs pas le rapport)
ig est une JFrame implémentée dans une autre fichier et instanciée dans le main.

int comp = 0; String sd; while (comp == 0) { sd = ig.getMontant(); comp = sd.compareTo("0"); //System.out.flush(); }

Tu veux dire que si tu décommentes cette ligne le comportement de ta boucle est bon mais si tu la commentes ça va plus ?  :open_mouth: 
Il y a quelque chose quelque part qui ne doit pas fonctionner comme tu le penses.
Dans ce cas mettre en place un petit affichage de debug peut t'aider à le trouver.
Par exemple :
[code]int comp = 0; String sd;
while (comp == 0) {
   // Afficher le retour de ig.getMontant();
   sd = ig.getMontant();
   // Afficher le contenu de sd
   // Afficher le retour de sd.compareTo("0");
   comp = sd.compareTo("0");
   // Afficher le contenu de comp
}[/code]
En faisant ça un peu de partout à partir de la zone où tu rencontres ton problème et en "remontant" en amont de ton code tu finiras certainement par trouver le "bug".

Tu veux dire que si tu décommentes cette ligne le comportement de ta boucle est bon mais si tu la commentes ça va plus ? :open_mouth:
Il y a quelque chose quelque part qui ne doit pas fonctionner comme tu le penses.
Dans ce cas mettre en place un petit affichage de debug peut t’aider à le trouver.
Par exemple :

int comp = 0; String sd; while (comp == 0) { // Afficher le retour de ig.getMontant(); sd = ig.getMontant(); // Afficher le contenu de sd // Afficher le retour de sd.compareTo("0"); comp = sd.compareTo("0"); // Afficher le contenu de comp }
En faisant ça un peu de partout à partir de la zone où tu rencontres ton problème et en “remontant” en amont de ton code tu finiras certainement par trouver le “bug”.

Le problème, c’est effectivement qu’un System.out.println donne un comportement normal de la boucle. (je ne peux donc pas m’en servir pour débugger …)

[code]import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class InterfaceGraphique extends JFrame implements ActionListener{
InterfaceGraphique(){

	montantVoulu = new JTextField(10);
	montantVoulu.setText("montant ?");
	montantVoulu.addActionListener(this);

	
	status = new JTextArea("go\n",6,25);
	status.setLineWrap(true);
	

	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	this.getContentPane().add(montantVoulu,BorderLayout.NORTH);
	this.getContentPane().add(status,BorderLayout.SOUTH);

	
	this.pack();
	this.setVisible(true);
	
}


public void actionPerformed(ActionEvent ap) {

	if (ap.getSource()== montantVoulu) {
		valeurMontant = montantVoulu.getText();
		status.append("montant entré : "+ valeurMontant + "\n");
		//montantVoulu.setEnabled(false);
	}

	
}

public String getMontant () {
	return valeurMontant;
}


private String valeurMontant = "0";

JTextField montantVoulu;

JTextArea status;

}[/code]

et le main :

[code]public class ClientFormLogin {

public static void main(String[] args) throws ClientProtocolException, IOException, SQLException {
	
   
    InterfaceGraphique ig;


    try {
        ig = new InterfaceGraphique();
        int comp = 0; String sd = "";
        while (comp == 0) {
        	sd = ig.getMontant();
        	comp = sd.compareTo("0");
        }
        System.out.println(ig.getMontant());
    } 
    finally {httpclient.close();}
}

}
[/code]

Je réalise à quel point je suis nul en Java, j’en ai pas assez fait et ça date trop pour que je sois capable de tout comprendre à ce code.
Genre quand j’ai vu ça :

InterfaceGraphique ig; try { ig = new InterfaceGraphique(); // ...
J’ai failli hurler :slightly_smiling: , parce qu’en C++ InterfaceGraphique ig; suffit à instancier un objet, ça sert à faire une allocation statique, alors faire une allocation dynamique par dessus avec ig = new InterfaceGraphique(); n’a pas de sens. ^^
[Bref tu t’en fous :smiley:]

Mais même en y connaissant rien en java, je sais qu’un bête saut de ligne sur l’entrée standard n’a aucun pouvoir sur le comportement d’une boucle.
C’est valable dans tout les langages.
C’est juste pas possible.
T’es d’accord ?

Donc ce qui te pousses à affirmer le contraire est juste faux.

Quand un code marche pas, ben faut le debuguer, si tu veux pas afficher du texte, débrouille toi de faire autrement (utilisation de l’exécution pas à pas ?), mais de manière à t’assurer que toutes les étapes de ton code ont le comportement que tu attends.
C’est comme ça que tu trouveras le truc bizarre à l’origine de touts tes soucis.

Désolé de pas pouvoir t’aider plus sur une bête boucle while… :confused:

On dirait que ig a un fonctionnement modal (qqchose comme ça)

En java une affectation n’est pas un booléen.

Comme dans l’écrasante majorité des langages (C et C++ compris) le . a la priorité sur les opérateurs booléens.

[quote=“SmallFitz”]Je fais pas trop de java, mais en C++ une instruction du type :
while (true) ;
Est évalué comme Tant que que c’est vrai j’exécute l’instruction vide.
Si tu demandes une boucle infinie, qui ne fais rien, ben c’est une boucle infinie qui s’exécute sans rien faire, point, la boucle n’est pas annulée pour autant.
Tu remarques que la seule chose qui peut changer de valeur dans ton contexte c’est readline.[/quote]
Dans certaines conditions ton compilateur va retirer la boucle pour optimisation.

[quote=“SmallFitz”]Mais même en y connaissant rien en java, je sais qu’un bête saut de ligne sur l’entrée standard n’a aucun pouvoir sur le comportement d’une boucle.
C’est valable dans tout les langages.
C’est juste pas possible.
T’es d’accord ?[/quote]
Pas moi, il y a 1000 et une raison qui peuvent donner des effets de bords bizarre à cette instruction (et ce dans tous les langages).

@blaisoth > Je ne vois pas le lien entre ta boucle et le code que tu nous as donné. D’où viennent les données qui sont lues via readline() ? C’est un fichier ?

Merci pour ces précisions / corrections qui me sont aussi utiles MisterFreeze ! :023

Effet de bord, moi qui croyais avoir affaire à une science exacte :frowning:

J’ai deux while qui posent problème dans ce programme. Les deux se règlent par un System.out.println mais dois-je m’en satisfaire ?

Dans le premier exemple, rd est un flux provenant d’une réponse HttpClient

réponse = httpclient.execute(post); entity = réponse.getEntity(); rd = new BufferedReader(new InputStreamReader(entity.getContent()));

J’ai contourné mon problème avec un wait() / notify() (ce que j’aurais d’ailleurs dû faire d’emblée) pour l’échange avec 'ig’
et tout simplement (comme j’avais implémenté plus tôt dans le programme) :

line =""; while (!line.contains("id=\"tdCV\"")) line = rd.readLine();
pour la lecture du flux

Je ne cocherai cependant ‘résolu’ que lorsque j’aurai compris pourquoi le while était bloqué …