Salutations,

Je suis actuellement en train de tester une fonction qui aurait pour but de pouvoir récupérer en mode console (oui je sais ça craint) un certain nombre de caractères entrés au clavier et dont la saisie s'achève soit lorsque le nombre de caractères maximum spécifié est atteint, soit lorsqu'on appuye sur entrée.

Cette fonction permet de faire le fameux getch() de conio.h, mais ici je travaille dans l'environnement Linux.

Voici la fonction getch() pour Linux:

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
#ifdef LINUX
int getch() 
{
    struct termios oldt, newt;
		struct sigaction Detournement;
 
		Detournement.sa_handler=SIG_IGN;
		// On ne peut pas interrompre le getch...
		sigaction(SIGINT,&Detournement,NULL);
 
    int ch;
    tcgetattr(STDIN_FILENO, &oldt);
    newt = oldt;
    newt.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
    ch = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
 
		// On va rétablir le comportement par défaut du CTRL-C
		Detournement.sa_handler=SIG_DFL;
		sigaction(SIGINT,&Detournement,NULL);
 
		return ch;
}
#endif
J'avais lu quelque part que la libraire ncurses (que je n'ai toujours pas pris la peine de survoler) proposait quelque chose de similaire et de portable.

Pour que cela fonctionne aussi sur Windows je ne sais pas comment faire, car les fonctions sigaction() sont liées aux unix-likes (unistd.h, termios.h et signal.h).

Bon ce problème mis à part voici le code sur lequel je travaille:

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
char *getncharAt(int posx,int posy,int maximum)
{
        int    index=0;	
        int	nbreCar=0;
	int	adaptedsize=maximum;
	char	*pTmp;
	char	*pReturnPointer;
 
	printf("\x1b[%d;%dH",posy,posx);
	if(maximum>0)
	{
		pReturnPointer=(char*)malloc(sizeof(char)*maximum);
		pTmp=(char*)malloc(sizeof(char)*maximum);				
// nous utilisons un espace mémoire temporaire...  sinon nous ne pourrions pas changer la taille de notre chaine de caractères avec realloc()...
		memset((void*)pTmp,0,maximum);
	}
	else
		return NULL;
 
	while(nbreCar<maximum)
	{
		*pTmp=getch();						// c'est complexe je sais...
		if(maximum>1)
			printf("%c",*pTmp);				
// sous Windows getch ne fait pas l'écho du caractère non plus...
		if(*pTmp==10 || *pTmp==27) break;	
// on ignore les touches de direction du clavier... et cela permet de quitter aussi avec  ESC...
		if(*pTmp>0)
		{
			if(*pTmp!=127) // Si pas backspace (effacer)
			{
				pTmp++;					
				index++;	
				nbreCar++;					
// incrémentation du compteur pour pouvoir sortir...	
			}
			else
			{
				printf("\x1b[1D"); 	// on retourne en arrière
				printf(" ");		// on efface le caractère
				printf("\x1b[1D");	// on retourne en arrière
 
				//printf("\b");
 
				pTmp--;						
// idem pour le pointeur il faut revenir une position "en arrière"
				index--;					
// il ne faut pas comptabiliser cette entrée comme étant un caractère
				if(*pTmp<0)					
// si c'est un caractère UTF8 
				{
					pTmp--;					
// il faut effacer le code -61 
					index--;				
// il ne faut pas comptabiliser le caractère
				}
				nbreCar--;					
// il ne faut pas compter cette entrée comme un caractère
			}
		}
		else
		{
			if(maximum==1)															// cas particulier où on demande un seul caractère et que celui-ci est utf8
			{
				pReturnPointer=(char*)realloc(pReturnPointer,sizeof(char)*3);		// le code -61, le code du caractère et \0...
				pReturnPointer[0]=-61;
				pReturnPointer[1]=getch();
				pReturnPointer[2]='\0';
				return pReturnPointer;
			}
			if(*pTmp!=-61) nbreCar++;												
// bypass le code indiquant qu'on a affaire à des caractères accentués UTF8
			if(maximum%2!=0) adaptedsize+=2;										
// si maximum n'est pas pair alors on ajoute deux caractères pour la réallocation de mémoire
			else adaptedsize++;														// sinon on ajoute un seul caractère
			pReturnPointer=(char*)realloc(pReturnPointer,sizeof(char)*adaptedsize);	// pour que realloc() puisse fonctionner il ne faut pas que pReturnPointer ait été modifié...
			pReturnPointer=pTmp-index;
			index++;
			pTmp++;
			if(nbreCar==maximum && (maximum%2)!=0) maximum++;						
// empêche de tronquer la chaine si le dernier caractère est codé en UTF8...
		}
	}
	*pTmp='\0';					
// on insère le caractère de fin de chaine pour que cela soit propre...
	pReturnPointer=pTmp-index;	// on retourne au début de la phrase...
	return pReturnPointer;
}
pfouh ! c'est galère l'introduction de code...

char *getncharAt(int,int,int); --> colonne (x),ligne (y),nombre de caractères maximum

Voici les tests effectués:

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
char 	*strtest;
strtest=getncharAt(1,1,20);
printf("\nLa fonction a retourné [%s]",strtest);
printf("\n ...et elle contient %d caractères selon strlen()...\n",strlen(strtest)); 
strtest=getnchar(1,2,1);
printf("\nLa fonction a retourné [%s]",strtest);
printf("\n ...et elle contient %d caractères selon strlen()...\n",strlen(strtest));
pour le Test 1: chaine terminée par entrée et chaine de plus de vingt caractères (avec plein de caractères accentués dedans et notamment comme dernier caractère)
pour le Test 2: un seul caractère non accentué et un caractère accentué

Qu'en pensez-vous ?