Bonjour,
J'ai une chaine de caractere, par exemple.
char buffer[255];
dans mon programme je l'alimente avec un index, mais je ne termine pas par un '\0', exprès.
Je voudrais connaitre la longueur de la chaine.
strlen et les fonction strcpy ne fonctionne pas, ce qui est normal.
Comment faire ?
J'ai pensé à faire une bouche sur le tableau, mais sans le test de\0, en testant
tant que c'est un caractère >= 32 (space) et <= à 127. Est ce que ca fonctionnerai ?
ce tableau contient que des caractères ascii entre 32 et 127
Je ne comprend pas ta question.
La longueur d'un buffer de 255 caractère, c'est 255.
Pourquoi ne pas utiliser le caractère 0?
Après tu peux initialiser ton buffer avec un autre caractère de contrôle, mais j'ai du mal à voir ce que tu veux faire.
C'est un système de ligne de commande, au fur et a mesure qu'ont tape un caractère dans le terminal, je met le caractère dans le tableaux, avec un système d'index que j'incrémente.
En temps normal, j'aurais mis à la fin un '\0', d'ailleurs sa fonctionne mais je me suis aperçu que je devait faire un traitement particuliers pour prendre en compte la touche Home et End par exemple , pour mettre l'index a zero et mettre le caractère entrer par la personne, mais je fait cela, le texte à droite de l'index n'est plus pris en compte, comme je met un zero au moment ou l'on entre la touche enter.
J'avais pensé à utilisé les String juste pour cette fonctionne de lecture du caractère ce qui aurait fonctionné, mais je n'ai pas réussi.
entre les String.c_str(), String.toCharArary, String.setCharAt, strcpy et tout cela, ca ne fonctionnait pas, la chaine contenait toujours blanc, c'est dommage, ca aurait résolu mon problème.
Dans tous les cas il faut mettre un \0 pour terminer la chaîne.
Si tu fais des manipulations sur cette chaîne par la suite rien ne t'empêche de mettre un \0 en amont si tu raccourcis la chaîne ou un plus loin si tu la rallonges.
Tu peux très bien avoir un pointeur qui pointe toujours sur la fin de la chaîne et un autre que tu balades dans la chaîne pour tes manipulations
De toutes façons c'est clair que la chaine doit se terminé par zéro,
J'ai fait a peu près cela sauf que c'est un index qui pointe sur la fin de la chaine et sa fonctionne
int getLenInput(const char* s)
{
if (s == nullptr) return 0;
int cpt = 0 ;
while ((s[cpt] >= 32) && (s[cpt] <= 127))
{
cpt++;
s++;
}
return cpt+1;
}
Premier point : je ne vois pas dans ton code de pointeur sur la fin de chaîne.
Deuxio : tu estimes que la fin se situe au premier caractère supérieur à ESPACE et inférieur à 127.
Mis à part un coup de bol ou le fait que ton buffer soit plein de ZÉROS au départ, je ne vois pas comment tu peux t'en sortir.
Une chaîne C se termine par ZÉRO, et tu auras beau inventer ta propre façon de faire, c'est une règle immuable.
Grossière erreur. Tu incrémentes un index cpt, et en même temps tu incrémentes le pointeur s.
Autant dire que tu examines un caractère sur deux. Ouille ...
en effet il y a une grosse erreur concernant le pointeur qui ne sert à rien, le tableaux est initialisé à zero au départ.
le tableaux ne contient que des caractère ascii incluant le code esc,
une fois récupéré la longueur sans le zero de fin de chaine, plus loin dans mon code, une fois mon traitement effectué, j'ajoute le zéro de fin de chaine qui est obligatoire.
pour donner un exemple avec une chaine qui contient le mot maison:
lorsque la touche entrée est appuyée, je récupère bien maison
si on se déplace avec la touche du clavier gauche et que je me positionne sur la lettre i de maison
si je ne fait pas ce que je fait, lorsque je valide avec la touche entrée, je récupère mai alors que je veux récupérer maison, car l'index est positionnée sur la lettre i.
avec ma modif, si on se déplace sur le caractère i et que je tape r au lieu de i, je récupère marson, c'est ce que je veux,
car auparavant, avec ma routine j'ai récupéré l'index de fin de chaine sans le zéro, là je ne parle pas de zéro de fin de chaine.
et plus loin dans le code, une fois la touche entrée appuyée, j'ajoute à index + 1 '\0'.
En tous cas ça fonctionne.
Voici la partie du code que je fait lorsque la touche entrée est appuyée:
Si je valide une commande je fait le else, dans le cas contraire lorsque le cursor (flèche gauche du clavier) a bougé vers la gauche, dans le cas si une lettre a été remplacée, je prend toute la chaine avec la lettre remplacée. Mais au final j'ai toujours le caractère de fin de chaine zéro, c'est obligatoire.
...
if (cursorMove) {
int index = getLenInput(receivedChars);
receivedChars[index + 1] = '\r';
receivedChars[index + 2] = '\0';
SERDEBUG.printf("%d %s\r\n", index, receivedChars);
} else {
receivedChars[ndx++] = '\r';
receivedChars[ndx] = '\0'; // terminate the string
SERDEBUG.println(receivedChars);
}
Je vais peut être dire des bêtises car je n'ai pas éplucher ton code.
Pourquoi voulais tu mettre un zéro après la saisie d'un caractère.
Si j'ai bien compris, tu as un tableau de char qui contient ta commande.
Le tableau est initialement remplis de 0.
Lorsque tu reçois un caractère de ton terminal, tu le stock dans l'index de ton curseur.
De ce fait ton tableau contient une chaine C fini par un 0 que tu peux utiliser tel quel dans une autre fonction qui attends un char*
Après tu voudrais gérer les touches du claviers HOME et END, pour HOME c'est très simple, puisque cela correspond à l'index 0.
Pour END tu as deux choix, faire un strlen sur ton tableau, ou stocker max d el'index dans une variable.
Si tu tombe sur la touche SUPPR, là il faudra faire un traitement pour décaler les caractères suivant et mettre un 0 sur l'ancien dernier caractère ou simplement mettre un espace si tu n'es pas sur le dernier caractère sinon un 0
Le 0 est obligatoire pour toutes chaines en langage C, une fois récupérer, je peux utiliser cette chaine pour faire n'importe quel traitement.
Pour le END, j'ai l'index de fin de chaine, je ne peut pas utilisé strlen, au moment ou l'on tape un caractère pendant la saisie, ce caractère je le stock sur un tableaux qui n'a pas encore de zero fin de chaine, le zéro fin de chaine c'est une fois que l'ont tape sur la touche entrée.
Je n'ai pas encore effectué le traitement de la fonction HOME et END.
Lorsque je fais la saisie, je peut circuler avec la touche fléchée de gauche, donc il n'y a pas de zéro de fin de chaine.
La touche SUPPR ou DEL ou BACKSPACE est bien gérée, ca fonctionne, je précise que c'est un terminal ansi, il suffit de enlever 1 à l'index et d'envoyer la commande ansi suivante "\b\e[K".
Bon je pense que l'on ne se comprend pas , après si tu as résolu ton problème c'est le principal
Je détaille ce que je comprends pas
Le 0 est obligatoire si tu veux utiliser les fonctions de manipulation de string C.
après tu peux très bien gérer toi même une chaine de caractère(char*) sans 0 de terminaison, mais c'est plus compliqué .
Ce que j'ai du loupé, si tu as un tableau de char, remplis initialement avec des 0.
Je ne vois pas pourquoi tu ne peux pas faire un strlen dessus.
En gros j'ai peut être mal lu ton code, mais ton index, c'est bien ndx qui te sert à naviguer dans receivedChars?
j'ai fait un programme d'exemple pour illustrer ce que je veux dire.
la saisie de caractères normaux dans une ligne de texte
le positionnement du curseur
Comme le buffer est plein de ZÉROS au départ, le dernier caractère saisi est toujours suivi d'un ZÉRO. Sauf dans certains cas.
Exemple : CTRLH
ndx-- ne suffit pas, il faut mettre à ZÉRO le caractère supprimé. Ainsi strlen() et autres fonctions c-string seront toujours utilisables. De plus si l'index ndx n'est pas au bout de la ligne, il faut décaler les caractères qui suivent vers la gauche.
Autre exemple : Left
Si le curseur bouge vers la gauche, les caractères entrés doivent être soit insérés devant le caractère courant, soit remplacer le caractère courant, en fonction du mode (insert ou overwrite)
En mode insert, les caractères devant le curseur doivent être décalés vers la droite.
Il y a probablement d'autres cas.
A mon sens, il n'y a pas de cas où la ligne de texte ne soit pas terminée par ZÉRO.
Pour prendre un exemple simple :
le buffer contient "coucou"
l'appui sur la touche backspace fait reculer le curseur d'une case en remplaçant le caractère sur le terminal par un espace.
l'index est décrémenté.
le buffer contient toujours "coucou"
strlen() renverra 6
si tu remplaces le dernier u par '\0', tout rentre dans l'ordre.
Dans un premier temps je me suis contenté du remplacement, car au niveau des décalage ca à l'air d'être compliqué, je n'ai pas trouvé d'exemple de code sur internet.
En effet pour le backspace, je devrais mettre un \0, je testerais cela.
Merci pour votre aide, je vais approfondir la chose.
Tu parle bien du décalage dans ton tableau de référence ?
Dans ce cas le plus simple est de faire du memcpy et de positionné un \0 sur l'ancien dernier caractère.
Pour cela le mieux est du coup d'avoir un pointeur sur le dernier caractère ou simplement la taille de ta chaine.
Au pire si tu coince, on devrait pouvoir faire un wowki qui reproduit ce que tu veux faire, pour pouvoir échanger sur un code commun.
Oui c'est bien dans le tableau de référence receivedChars.
c'est surement un memcpy mais je ne vois pas comment.
Si dans le tableaux j'ai maison et que je me déplace sur la lettre i et que je veux insérer la lettre t, je dois me retrouver avec matison, il faudrait que je déplace "ison" d'un caractère vers la droite, c'est bien ca ?
J'ai le nombre total de caractère de la chaine et l'index donc je doit pouvoir trouvé la partie droite de la chaine
Pour l'insertion tu peux te permettre de passer par des strcpy, car tu ne peux pas faire de memcpy sans passer par une copy de ta chaine.
j'ai modifier mon exemple pour faire ce que tu veux avec deux strcpy, qui sont du coup plus couteux en cycle processeur et mémoire.
Mon exemple ne peux être directement appliqué a un cas général, puisque je ne gère pas les borne.
Dans ce cas là, il serait plus efficace de passer par une boucle partant de la fin, qui décale de la fin + 1, jusqu'à ton index +1
Non, memcpy() marchera dans un sens (décalage vers la gauche), mais pas dans l'autre (décalage vers la droite).
Par contre memmove() accepte que les deux zones se chevauchent. Cette fonction va effectuer la copie en partant du début, ou en partant de la fin, suivant le cas.
Il n'y a aucune raison de passer par une chaîne intermédiaire.