IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Récursivité et saisie clavier


Sujet :

Java

  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut Récursivité et saisie clavier
    Je cherche à simuler en java le comportement suivant où inkey serait une fonction qui renvoie les saisies au clavier lettre par lettre
    Je veux créer la fonction récursive obtenirFormule dont la définition serait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    String obtenirFormule()
    {
        while (true)
        {
            char x = inkey();
            if (x == 'v') return "v";
            if (x == 'n') return "n" + obtenirFormule();
            if (x == 'o') return "o" + obtenirFormule() + "c" + obtenirFormule() + "f";
        }
    }
    Mais je ne vois vraiment pas comment implémenter cela en java.
    C'est en respectant les autres que l'on se fait respecter.

  2. #2
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Ben, à part le fait que le while(true) n'a rien à faire là, tu viens de le faire en Java, non ?
    C'est quoi qui ne te convient pas ?
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  3. #3
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Ben, à part le fait que le while(true) n'a rien à faire là, tu viens de le faire en Java, non ?
    C'est quoi qui ne te convient pas ?
    tout d'abord je ne sais pas simuler le inkey en java: créer une fonction qui renvoie l'entrée standard caractère par caractère sans appui sur "entrée".
    Ensuite le while (true) permet de n'accepter comme caractères valides que les caractères o,n,v et e boucler sur l'appel au clavier tant qu'on n'a pas taper sur l'une de ces touches.
    C'est en respectant les autres que l'on se fait respecter.

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Citation Envoyé par Patrice Henrio Voir le message
    tout d'abord je ne sais pas simuler le inkey en java: créer une fonction qui renvoie l'entrée standard caractère par caractère sans appui sur "entrée".
    Oh, c'est impossible sans bibliothèque tierce. Le terminal n'enverra rien au programme Java tant que tu n'as pas appuyé sur "entrée." Rien ne t'empêche de traiter ces appuis en lisant les lettres une par une par contre.

    Citation Envoyé par Patrice Henrio Voir le message
    Ensuite le while (true) permet de n'accepter comme caractères valides que les caractères o,n,v et e boucler sur l'appel au clavier tant qu'on n'a pas taper sur l'une de ces touches.
    Ah, effectivement je n'avais pas vu.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  5. #5
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Oh, c'est impossible sans bibliothèque tierce. Le terminal n'enverra rien au programme Java tant que tu n'as pas appuyé sur "entrée." Rien ne t'empêche de traiter ces appuis en lisant les lettres une par une par contre.
    Si j'ai déjà une chaine complète, la fonction obtenirFormule permettra seulement de déterminer si la chaine que l'on récupère est valide (et la traiter dans ce cas), pas de la construire de proche en proche comme je voulais le faire.
    C'est en respectant les autres que l'on se fait respecter.

  6. #6
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Je ne comprends pas trop de quoi tu parles mais tu pourrais par exemple exiger qu'une seule lettre soit tapée par ligne et refuser le reste, ce qui évite "d'avoir l'impression" d'avoir tapé une chaîne entière.
    Côté Java c'est un ordinateur, il a aucune idée qu'il existe une différence entre lettres tapées une à une et lettres tapées ensemble. Il les lit dans l'ordre, point barre.

    Et si vraiment c'est pas possible comme ça, il va falloir songer à faire ton programme en mode graphique ou avec une bibliothèque tierce du genre javacurses.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  7. #7
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    En fait mon problème est comment intégrer une méthode évènementielle dans une fonction récursive.
    Même si je passe en mode graphique avec un composant lambda (par exemple un JLabel) et que je l'abonne à un écouteur de clavier (addKeyListener), comment intégrer la méthode keyTyped dans une fonction récursive ?
    Ou alors créer mon propre listener ?
    Je ne vois vraiment pas.
    C'est en respectant les autres que l'on se fait respecter.

  8. #8
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 547
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 547
    Points : 21 602
    Points
    21 602
    Par défaut
    Ce ne sont pas les façons de faire qui manquent. Mais pour rester au plus proche de ta façon de faire : il suffit que inkey() soit bloquante tant que l'évènement n'est pas reçu. (Exactement ce qui se passe quand on lit l'entrée standard donc.)

    L'idée serait d'avoir une LinkedBlockingQueue partagée entre le listener d'évènements, et la classe qui a inkey().
    Le listener ajoute les évènement reçus dans la queue, et inkey() appelle take() sur la queue pour prendre le prochain évènement disponible, et s'il n'y en a pas, attendre qu'il en arrive un.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  9. #9
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Je pense que j'ai réussi la partie console. Je voudrai maintenant intégrer cela dans un composant et je me retrouve avec la même question que dans le message précédent.
    Mais au moins le code suivant répond à la question d'une construction pas à pas d'une formule valide.
    Chaque frappe au clavier est ponctuée d'un retour charriot pour voir au fur et à mesure la construction de la formule.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
     
    public class SaisieClavier 
    {
    	static String formule = "";
     
    	public static void main(String[] args) 
    	{
    		String formule = obtenirFormule();
    		System.out.println(formule);
    	}
     
    	private static String obtenirFormule() 
    	{
    		while(true)
    		{
    			try 
    			{
    				int ch = System.in.read();
    				char c = (char) ch;
    				if (c == 'v')
    				{
    					formule += "v";
    					System.out.println(formule);
    					return "v";
    				}
    				if (c == '!')
    				{
    					formule += "!";
    					System.out.println(formule);
    					String f1 = obtenirFormule();
    					return "!" + f1;
    				}
    				if (c == '(')
    				{
    					formule += "(";
    					System.out.println(formule);
    					String f1 = obtenirFormule();
    					formule += "&";
    					System.out.println(formule);
    					String f2 = obtenirFormule();
    					formule += ")";
    					System.out.println(formule);
    					return "(" + f1 + "&" + f2 + ")";
    				};
    			}
    			catch (IOException e) 
    			{
    				e.printStackTrace();
    			}
    		}
    	}
    }
    Chacun l'aura compris, il s'agit de construire une formule logique "bien écrites". L'alphabet utilisé est {"(",")","!","&","v"} v représentant une variable propositionnelle. Le fait d'utiliser un seul "v" pour toutes les variables n'est pas grave car ce qui compte ici c'est que la formule soit licite.
    J'utilise la définition de l'ensemble des formules propositionnelles
    Toute variable propositionnelle est une formule
    Si F est une formule, !F est une formule
    Si F et G sont des formules (F&G) est une formule
    La fonction obtenirFormule est donc une simple écriture de cette définition.
    C'est en respectant les autres que l'on se fait respecter.

  10. #10
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par thelvin Voir le message
    Ce ne sont pas les façons de faire qui manquent. Mais pour rester au plus proche de ta façon de faire : il suffit que inkey() soit bloquante tant que l'évènement n'est pas reçu. (Exactement ce qui se passe quand on lit l'entrée standard donc.)

    L'idée serait d'avoir une LinkedBlockingQueue partagée entre le listener d'évènements, et la classe qui a inkey().
    Le listener ajoute les évènement reçus dans la queue, et inkey() appelle take() sur la queue pour prendre le prochain évènement disponible, et s'il n'y en a pas, attendre qu'il en arrive un.
    Je vais regarder de ce côté là. Ca me parait prometteur.
    Donc en résumant : je crée une classe étendant un composant (je verrai le type nécessaire), implémentant KeyListener, je l'abonne à lui-même en tant que keyListener, je lui ajoute une LinkedBlockingQueue, j'ajoute les évènements du KeyListener dans la liste bloquée, je peux même sans doute filtrer les évènements pour n'accepter que les valeurs souhaitées (il y en a 3), la fonction inkey() prend les évènements dans la liste au fur et à mesure (attendant éventuellement qu'il y en ait un). Je ne touche pas à ma fonction obtenirFormule initiale (sauf que j'utilise maintenant "(", "!" et "v").
    C'est en respectant les autres que l'on se fait respecter.

  11. #11
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Citation Envoyé par Patrice Henrio Voir le message
    Je vais regarder de ce côté là. Ca me parait prometteur.
    Donc en résumant : je crée une classe étendant un composant (je verrai le type nécessaire), implémentant KeyListener, je l'abonne à lui-même en tant que keyListener, je lui ajoute une LinkedBlockingQueue, j'ajoute les évènements du KeyListener dans la liste bloquée, je peux même sans doute filtrer les évènements pour n'accepter que les valeurs souhaitées (il y en a 3), la fonction inkey() prend les évènements dans la liste au fur et à mesure (attendant éventuellement qu'il y en ait un). Je ne touche pas à ma fonction obtenirFormule initiale (sauf que j'utilise maintenant "(", "!" et "v").
    Malgré tous mes efforts et divers essais, je n'arrive à rien.
    Voici mes classes :
    La classe Inkey qui partage une LinkedBlockingQueue que j'ai sans doute mal im^planté car elle ne bloque pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    public class Inkey 
    {
    	LinkedBlockingQueue<KeyEvent> liste = new LinkedBlockingQueue<KeyEvent>();
     
    	public Inkey(LinkedBlockingQueue<KeyEvent> liste2)
    	{
    		liste = liste2;
    	}
     
    	public char inkey() 
    	{
    		char c = 0;
    		try 
    		{
    			KeyEvent e = liste.take();
    			c = e.getKeyChar();
    		} 
    		catch (InterruptedException e) 
    		{
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return c;
    	}
    }
    et ma classe principale avec plein de System.out.println pour essayer de comprendre. je suis revenu à "onv" pour simplifier (je commençais à confondre le texte Java et mes formules). L'indice 3 témoigne de mes multiples essais.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
     
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.util.concurrent.LinkedBlockingQueue;
     
    import javax.swing.JFrame;
     
    public class Saisie3 extends JFrame
    {
    		private KeyListener keyListener;
    	private LinkedBlockingQueue<KeyEvent> liste = new LinkedBlockingQueue<KeyEvent>();
    	private Inkey inkey;
    	private String formule = "";
    	private boolean fini;
    	private int o,f,c;
     
    	   public Saisie3() 
    	   {
    		   super("Saisie de formule");
    		   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		   inkey = new Inkey(liste);
    		   setSize(1200,600);
    		      KeyListener keyListener = new KeyListener()
    		      {
     
    				@Override
    				public void keyTyped(KeyEvent e) 
    				{
    					if ("onv".contains(""+e.getKeyChar()))
    					{
    						try 
    						{
    							liste.put(e);
    						} 
    						catch (InterruptedException e1) 
    						{
    							// TODO Auto-generated catch block
    							e1.printStackTrace();
    						}
    					}
    				}
     
    				@Override
    				public void keyPressed(KeyEvent e) {
    					// TODO Auto-generated method stub
     
    				}
     
    				@Override
    				public void keyReleased(KeyEvent e) {
    					// TODO Auto-generated method stub
     
    				}
     
    		      };
    		   addKeyListener(keyListener);   
    		   setVisible(true);
    		   obtenirFormule(0);
    		   System.out.println(formule);
    	   }
     
    	private void obtenirFormule(int i) 
    	{
    		System.out.println("obtenirFormule (" + i + ") : " + formule);
    		while(!fini)
    		{
    				char c = inkey.inkey();
    				if (c == 'v')
    				{
    					formule += "v";
    				}
    				if (c == 'n')
    				{
    					formule += "n";
    					i++;
    					obtenirFormule(i);
    					i--;
    				}
    				if (c == 'o')
    				{
    					o++;
    					formule += "o";
     
    					System.out.println("obtenirFormule (" + i + ") : " + formule);
    					i++;
    					obtenirFormule(i);
    					formule += "c";
    					System.out.println("obtenirFormule (" + i + ") : " + formule);
     
    					obtenirFormule(i++);
    					formule += "f";
    					i--;
    					System.out.println("obtenirFormule (" + i + ") : " + formule);
    					o--;
    				};
    				fini = ((o == 0));
    		}
    	}
    	public static void main(String[] args)
    	{
    		new Saisie3(); 
     
    	}
     
    }
    Lorsque je tape "v" ou "nv" ça fonctionne mais avec "o" ça ne marche pas : après avaoir tapé o, il n'accepte plus rien.

    Il y a sûrement quelque chose que je n'ai pas compris
    C'est en respectant les autres que l'on se fait respecter.

  12. #12
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2004
    Messages : 464
    Points : 332
    Points
    332
    Par défaut
    Bon je crois que j'ai réussi ... mais n'hésitez pas à critiquer/améliorer ma solution

    La classe de saisie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.util.concurrent.LinkedBlockingQueue;
     
    import javax.swing.JFrame;
     
     
     
    public class Saisie3 extends JFrame
    {
    	private LinkedBlockingQueue<KeyEvent> liste = new LinkedBlockingQueue<KeyEvent>();
    	private Inkey inkey;
     
    	public Saisie3() 
    	{
    		super("Saisie de formule");
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		inkey = new Inkey(liste);
    		setSize(1200,600);
    		KeyListener keyListener = new KeyListener()
    		{
    			@Override
    			public void keyTyped(KeyEvent e) 
    			{
    				if ("onv".contains(""+e.getKeyChar()))
    				{
    					try 
    					{
    						liste.put(e);
    					} 
    					catch (InterruptedException e1) 
    					{
    						e1.printStackTrace();
    					}
    				}
    			}
     
    			@Override
    			public void keyPressed(KeyEvent e) {}
     
    			@Override
    			public void keyReleased(KeyEvent e) {}
     
    		};
    		addKeyListener(keyListener);   
    		setVisible(true);
    		System.out.println(new Formule(inkey,0,"").getFormule());
    	}
     
    	public static void main(String[] args)
    	{
    		new Saisie3(); 
     
    	}
     
    }
    La classe Inkey
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    import java.awt.event.KeyEvent;
    import java.util.concurrent.LinkedBlockingQueue;
     
    public class Inkey 
    {
    	LinkedBlockingQueue<KeyEvent> liste = new LinkedBlockingQueue<KeyEvent>();
     
    	public Inkey(LinkedBlockingQueue<KeyEvent> liste2)
    	{
    		liste = liste2;
    	}
     
    	public char inkey() 
    	{
    		char c = 0;
    		try 
    		{
    			KeyEvent e = liste.take();
    			c = e.getKeyChar();
    		} 
    		catch (InterruptedException e) 
    		{
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    		return c;
    	}
    }
    La classe qui valide la saisie
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
     
    public class Formule 
    {
    	private String formule="";
     
    	Formule(Inkey inkey, int i, String s)
    	{
    		i++;
    		System.out.println("obtenirFormule (" + i + "): debut " + s);
    		formule = s;
    		char c = inkey.inkey();
    		switch (c)
    		{
    			case 'v' :
    				formule += "v";
    				break;
     
    			case 'n' : 
    				formule += "n";
    				formule = new Formule(inkey,i, formule).formule;
    				break;
     
    			case 'o' : 
    				formule += "o";
    				formule = new Formule(inkey,i, formule).formule;
    				formule += "c";
    				formule = new Formule(inkey,i,formule).formule;
    				formule += "f";					
    				break;
    		}
    		System.out.println("obtenirFormule (" + i + "): fin " + formule);
    	}
     
     
    	public String getFormule() 
    	{
    		return formule;
    	}
    }
    Ce qui me gène : la récursivité dans le constructeur.
    C'est en respectant les autres que l'on se fait respecter.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Récupérer une saisie clavier de l'utilisateur
    Par le y@m's dans le forum Scripts/Batch
    Réponses: 5
    Dernier message: 23/09/2019, 20h25
  2. Richeditctrl - problème de saisie clavier
    Par KO-Tek dans le forum MFC
    Réponses: 5
    Dernier message: 20/12/2005, 12h15
  3. [PL/SQL] saisie clavier
    Par seal dans le forum Langage SQL
    Réponses: 3
    Dernier message: 16/08/2005, 12h54
  4. Simuler saisie clavier SendMessage et WM_KEYDOWN
    Par VoLc0m dans le forum Windows
    Réponses: 8
    Dernier message: 11/05/2005, 16h31
  5. Saisie clavier marche pas
    Par Dokho1000 dans le forum Entrée/Sortie
    Réponses: 8
    Dernier message: 11/03/2004, 13h16

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo