# lire touche sans appuyer entrée en C++



## boubacar_de_monaco (25 Mai 2007)

Bonjour,

J'ai un projet &#224; faire en C++ et le seul ordinateur que j'ai est un Mac.
Nul en informatique j'ai pris mon courage &#224; deux mains mais j'ai l'impression qu'il y a moins d'information sur le net pou ceux qui d&#233;veloppe sur mac.

Pourriez vous r&#233;pondre &#224; mes question s'il vous pla&#238;t?

- J'utilise Xcode. C'est bien C++ tools qu'il faut prendre lors du choix de projet?

- quels sont les diff&#233;rence entre d&#233;velopper sur C++ Linux et sur un mac?

- j'ai besoin de faire une lecture de touche sans appuyer sur entr&#233;e. J'ai trouv&#233; un code mais qui marche avec conio.h ce qui n'existe pas sous Unix.
J'ai aussi trouv&#233; un code qui me dit de passer le terminal en mode brut ou mode raw. J'ai mis le code mais celui ci ne marche pas.

le terminal passe en mode raw si on passe 1 en argument et 0 en cas contraire:

#include <termios.h>
#include <unistd.h>
#include "saisie_vole.h"


void mode_raw(int activer)
{
   static struct termios cooked;
   static int raw_actif = 0;

   if (raw_actif == activer)
   {
      return;
   }

   if (activer)
   {
      struct termios raw;

      tcgetattr(STDIN_FILENO, &cooked);

      raw = cooked;
      cfmakeraw(&raw);
      tcsetattr(STDIN_FILENO, TCSANOW, &raw);

   }
   else
   {
      tcsetattr(STDIN_FILENO, TCSANOW, &cooked);
   }

   raw_actif = activer;
}



Merci de votre aide


----------



## ntx (25 Mai 2007)

boubacar_de_monaco a dit:


> - J'utilise Xcode. C'est bien C++ tools qu'il faut prendre lors du choix de projet?


oui


> - quels sont les différence entre développer sur C++ Linux et sur un mac?


Pour l'apprentissage : aucune, du C++ c'est du C++ quelque soit la plate-forme, du moment que tu respectes la norme en n'utilisant que des librairies standards et que tu ne vas pas taper dans des librairies propriétaires.
C'est d'autant plus vrai entre Mac OSX et Linux si tu veux utiliser les accès au terminal Unix. Après si ton code doit aussi fonctionner sous Windows, c'est une autre affaire.


----------



## PA5CAL (25 Mai 2007)

Bonjour

Voici un petit bout de code qui montre comment proc&#233;der pour recueillir les caract&#232;res isol&#233;ment sans devoir attendre qu'une ligne enti&#232;re soit saisie.

Le programme affiche les codes des caract&#232;res d&#232;s leur arriv&#233;e.

```
#include <stdio.h>
#include <unistd.h>
#include <termios.h>

int main() {
[COLOR="Blue"]// MODIFICATION DU FONTIONNEMENT PAR DEFAUT DU TERMINAL[/COLOR]
	[COLOR="Red"]// Lit la structure "termios" de l'entr&#233;e standard[/COLOR]
	struct termios tios;
	tcgetattr(STDIN_FILENO, &tios);

	[COLOR="Red"]// Sauve l'ancien flag "c_lflag"[/COLOR]
	tcflag_t old_c_lflag = tios.c_lflag;

	[COLOR="Red"]// Passe en mode de saisie non canonique
	// (lecture d'1 caract&#232;re &#224; la fois par d&#233;faut, car MIN=1 et TIME=0) [/COLOR]
	tios.c_lflag &= ~ICANON;
	tcsetattr(STDIN_FILENO, TCSANOW, &tios);

[COLOR="Blue"]// UTILISATION DU TERMINAL[/COLOR]
	for (;;) {
		[COLOR="Red"]// Lit un caract&#232;re sur l'entr&#233;e standard[/COLOR]
		unsigned char c;
		read(STDIN_FILENO, &c, 1);

		[COLOR="Red"]// Quitte si touche "Entr&#233;e"[/COLOR]
		if (c=='\n')
			break;

		[COLOR="Red"]// Affiche le code du caract&#232;re[/COLOR]
		printf("[&#37;02X] ", c);
		fflush(stdout);
	}

[COLOR="Blue"]// FIN[/COLOR]
	[COLOR="Red"]// Restaure l'ancien flag "c_lflag"[/COLOR]
	tios.c_lflag = old_c_lflag;
	tcsetattr(STDIN_FILENO, TCSANOW, &tios);

	return 0;
}
```


----------



## BeNBiBiFoKe (25 Mai 2007)

```
for (;;)
```


BBEEUURRKK !!!


----------



## PA5CAL (25 Mai 2007)

BeNBiBiFoKe a dit:


> ```
> for (;;)
> ```
> 
> ...


Qu'est-ce que tu trouves &#224; y redire ?

Bon, pour les puristes, habituellement on fait :

```
#define forever for(;;)

...


forever {
...
}
```
ou bien :

```
#define loop for(;;)

...


loop {
...
}
```


Il n'emp&#234;che que &#231;a vaut mieux qu'un :
	
	



```
while(true) {
...
}
```


----------



## boubacar_de_monaco (25 Mai 2007)

Je n'ai pas encore testé mais je te remercie pour tes réponse


----------



## PA5CAL (26 Mai 2007)

Attention. Je ne sais pas ce que &#231;a rend chez vous, mais le ~ passe tr&#232;s mal &#224; l'affichage chez moi. Pour la ligne:

```
tios.c_lflag &= ~ICANON;
```
il faut bien lire " *tios.c_lflag &= ~ICANON;* ", avec un tilde, et non un signe moins !


----------



## boubacar_de_monaco (26 Mai 2007)

Merci.

J'ai une autre question:
Pouvez vous me donner des pistes(code ou sites) pour comprendre la lecture/ecriture sur fichier en C++.

Merci d'avance


----------



## ntx (26 Mai 2007)

Librairie IOStream. Voir le lien donné plus haut.


----------



## boubacar_de_monaco (27 Mai 2007)

Merci pour la documentation mais ca m'a l'air un peu compliqué :rose: 

Vous pourriez me dire ce que signifie cette sortie de programme?
" 
ZeroLink: unknown symbol '__ZN7AdresseC1Ev'

location_voiture has exited due to signal 6 (SIGABRT). "

Mon programme ne renvoie pas zéro mais ceci.


----------



## ntx (27 Mai 2007)

> Merci pour la documentation mais ca m'a l'air un peu compliqué


Le problème c'est que dans ton premier post, tu soulignes que tu es nul en informatique. Désolé, mais "C++" et "nul en informatique", ce n'est pas compatible. :rateau: 

Clic droit sur ta cible : Get Info > Build, décoche l'option ZeroLink

PS : tu as le droit de faire une recherche avant de venir poser tes questions, on en a déjà parlé mille fois de ce zerolink.


----------



## boubacar_de_monaco (27 Mai 2007)

Merci  Je regarderai d'abord la fonction rechercher à l'avenir


----------



## boubacar_de_monaco (27 Mai 2007)

PA5CAL a dit:


> Bonjour
> 
> Voici un petit bout de code qui montre comment procéder pour recueillir les caractères isolément sans devoir attendre qu'une ligne entière soit saisie.
> 
> ...



Bonjour,

J'ai essayé ton code mais, ca ne marche pas :rose: 
Quand je tape "entrée" je quitte effectivement la boucle mais lorsque je presse une lettre quelconque je dois absolument valider par "entrée" sinon ça ne fonctionne pas...

Voici ce que j'ai changé dans le code

// UTILISATION DU TERMINAL

	for (; {
		// Lit un caractère sur l'entrée standard
		unsigned char c;
		read(STDIN_FILENO, &c, 1);

		// Quitte si touche "Entrée"
		if (c=='a') cout<<" vous avez tape a \n";
		if (c=='b') cout<<" vous avez tape b \n";
		if (c=='c') cout<<" vous avez tape c \n";
		if (c=='\n')
			break;

		// Affiche le code du caractère
		printf("[%02X] ", c);
		fflush(stdout);
	}


// FIN


Merci


----------



## PA5CAL (27 Mai 2007)

Pourtant chez moi &#231;a fonctionne bien...

J'utilise _gcc 4.0.1_ pour Darwin8/PowerPC et la librairie _stdc++_.

Le probl&#232;me peut venir de l'affichage (_printf_), qui attend qu'un caract&#232;re '_\n_' soit envoy&#233; pour afficher une ligne enti&#232;re (c'&#233;tait la raison de mon _fflush(stdout)_, mais peut-&#234;tre n'est-ce pas efficace dans ton cas).

Une autre possibilit&#233; est que tes options par d&#233;faut du Terminal ont &#233;t&#233; modifi&#233;es. Il faut s'assurer qu'on a toujours MIN=1 (retour apr&#232;s un caract&#232;re saisi) et TIME=0 (pas de timeout).


----------



## boubacar_de_monaco (27 Mai 2007)

J'ai mis le printf en commentaire et &#231;a n'a rien chang&#233;... :rose:  :rose:  :rose: 

Comment on regarde les options du terminal?
je ne sais pas quel version de gcc j'utilise (j'ai acheter mon mac en novembre dernier)



Par contre si &#231;a peut aider voici ce que fais le terminal programme (ne tiens pas compte de l'affichage au dessus)

au moment ou il doit lire mon caract&#232;re j'ai entr&#233;
"kfqhslkdfhqkuefhlqkjsdhflqskhdflkqhsfkqhsfkhqskfdjhksjfhs" et puis "entr&#233;e"

Il lit bien caract&#232;re par caract&#232;re parce que au niveau du printf il me ressort les valeurs entre crochets
Le code est le m&#234;me que j'ai post&#233; 2 post plus haut:


*****************************************
**         ____________________                     **
**         LOCATION DE VOITURES                    **
**                                                                 **
*****************************************






 e: Nouvel Emprunteur
 l: Liste des Emprunteurs (chargement)

 d: Edition des devis
    Factures

 v: Nouveau Vehicules

 i: Liste des Vehicules

 o: Nouvelle Location
 r: Retour Location
 c: Consultation des locations en cours

 s: statistiques sur les v&#233;hicules les plus empruntes



 q: quitter le programme 
kfqhslkdfhqkuefhlqkjsdhflqskhdflkqhsfkqhsfkhqskfdjhksjfhs
[6B] [66] [71] [68] [73] [6C] [6B] [64] [66] [68] [71] [6B] [75] [65] [66] [68] [6C] [71] [6B] [6A] [73] [64] [68] [66] [6C] [71] [73] [6B] [68] [64] [66] [6C] [6B] [71] [68] [73] [66] [6B] [71] [68] [73] [66] [6B] [68] [71] [73] [6B] [66] [64] [6A] [68] [6B] [73] [6A] [66] [68] [73]

location_voiture has exited with status 0.


Cordialement


----------



## PA5CAL (27 Mai 2007)

Si tu as un Mac r&#233;cent, tu dois &#234;tre sur processeur Intel.

Je pense qu'il y a une autre raison possible pour que &#231;a ne fonctionne pas: le flag ICANON n'a peut-&#234;tre pas &#233;t&#233; correctement d&#233;sactiv&#233;. Le terminal ne serait alors pas pass&#233; en mode non canonique.


Au fait, as-tu fait un copier-coller de mon code, ou bien l'as-tu recopi&#233; &#224; la main ?


----------



## PA5CAL (27 Mai 2007)

Voici un extrait de l'aide concernant _termios_ :
	
	



```
[B]TERMIOS(4)               BSD Kernel Interfaces Manual               TERMIOS(4)[/B]

[B]NAME[/B]
     [B]termios[/B] -- general terminal line discipline

[B]SYNOPSIS[/B]
     #include <termios.h>

  ...

[B]Noncanonical Mode Input Processing[/B]
  In noncanonical mode input processing, input bytes are not assembled into
  lines, and erase and kill processing does not occur.  The values of the
  MIN and TIME members of the [B]c_cc[/B] array are used to determine how to
  process the bytes received.

  MIN represents the minimum number of bytes that should be received when
  the read function successfully returns.  TIME is a timer of 0.1 second
  granularity that is used to time out bursty and short term data transmis-
  sions.  If MIN is greater than { MAX_INPUT}, the response to the request
  is undefined.  The four possible values for MIN and TIME and their inter-
  actions are described below.

[B]Case A: MIN > 0, TIME > 0[/B]
  ...

[B]Case B: MIN > 0, TIME = 0[/B]
  In this case, since the value of TIME is zero, the timer plays no role
  and only MIN is significant.  A pending read is not satisfied until MIN
  bytes are received (i.e., the pending read blocks until MIN bytes are
  received), or a signal is received.  A program that uses this case to
  read record-based terminal I/O may block indefinitely in the read opera-
  tion.

  ...

[B]Special Control Characters[/B]
  The special control characters values are defined by the array [B]c_cc[/B].
  This table lists the array index, the corresponding special character,
  and the system default value.  For an accurate list of the system
  defaults, consult the header file <ttydefaults.h>.

       [U] Index Name    Special Character    Default Value[/U]
        VEOF          EOF                  ^D
        VEOL          EOL                  _POSIX_VDISABLE
        VEOL2         EOL2                 _POSIX_VDISABLE
        VERASE        ERASE                ^? `\177'
        VWERASE       WERASE               ^W
        VKILL         KILL                 ^U
        VREPRINT      REPRINT              ^R
        VINTR         INTR                 ^C
        VQUIT         QUIT                 ^\\ `\34'
        VSUSP         SUSP                 ^Z
        VDSUSP        DSUSP                ^Y
        VSTART        START                ^Q
        VSTOP         STOP                 ^S
        VLNEXT        LNEXT                ^V
        VDISCARD      DISCARD              ^O
        [B]VMIN          ---                  1[/B]
        [B]VTIME         ---                  0[/B]
        VSTATUS       STATUS               ^T

  If the value of one of the changeable special control characters (see
  Special Characters) is {_POSIX_VDISABLE}, that function is disabled; that
  is, no input data is recognized as the disabled special character.  If
  ICANON is not set, the value of {_POSIX_VDISABLE} has no special meaning
  for the VMIN and VTIME entries of the [B]c_cc[/B] array.

  The initial values of the flags and control characters after open() is
  set according to the values in the header <sys/ttydefaults.h>.
```
Peut-&#234;tre n'avons-nous pas le m&#234;me _ttydefaults.h_ ?


----------



## boubacar_de_monaco (27 Mai 2007)

J'ai fait un copier_coller et j'ai juste modier le traitement de ta variable c;
oui j'ai un mac-intel;


----------



## PA5CAL (27 Mai 2007)

Ach !!! J'entrevois le probl&#232;me...

J'ai compil&#233; et lanc&#233; mon programme depuis l'environnement int&#233;gr&#233; de XCode... et &#231;a ne marche pas ! &#199;a me donne &#231;a:





> [Session started at 2007-05-27 23:31:55 +0200.]
> azerty
> [61] [7A] [65] [72] [74] [79]
> test has exited with status 0.



Mais en lan&#231;ant le m&#234;me programme (m&#234;me pas recompil&#233;, donc) depuis Terminal, &#231;a fonctionne bien ! &#199;a me donne &#231;a:





> monmac:~ me$ cd /Users/me/test/build/Debug/
> monmac:~/test/build/Debug me$ ./test
> a[61] z[7A] e[65] r[72] t[74]
> monmac:~/test/build/Debug me$



Bref, ce qui doit se passer, c'est que la console pr&#233;sent&#233;e par XCode n'est pas exactement &#233;quivalente au terminal !

Tu devrais r&#233;essayer ton programme depuis l'ext&#233;rieur de XCode, avec le vrai Terminal...


----------



## boubacar_de_monaco (28 Mai 2007)

un grand Merci à toi PA5CAL!

Ca marche, c'est vraiment bien. Il ne me reste plus qu'à fabriquer une fonction qui range tout ce langage barbare et que je pourrais appeler parce que c'est assez gros.

Je ne savais pas que ça pouvait etre different de lancer le terminal Xcode du Terminal Finder...   :mouais: 

Voila en tout cas pour ca merci beaucoup 

Sans vouloir abuser du forum si quelqu'un peut m'expliquer ce qui ne va pas avec ce warning:

#ifdef __DEPRECATED
#warning This file includes at least one deprecated or antiquated header. \
Please consider using one of the 32 headers found in section 17.4.1.2 of the \
C++ standard. Examples include substituting the <X> header for the <X.h> \
header for C++ includes, or <iostream> instead of the deprecated header \
<iostream.h>. To disable this warning use -Wno-deprecated.
#endif


Merci encore


----------



## ntx (28 Mai 2007)

boubacar_de_monaco a dit:


> #ifdef __DEPRECATED
> #warning This file includes at least one deprecated or antiquated header. \
> Please consider using one of the 32 headers found in section 17.4.1.2 of the \
> C++ standard. Examples include substituting the <X> header for the <X.h> \
> ...


En C++, les headers standard n'ont plus le suffixe ".h".  Tout est dans le warning même le chapitre de référence dans la norme.


----------



## boubacar_de_monaco (28 Mai 2007)

Tout marche bien 

Merci :love:  :love:


----------

