[RESOLU] Comment connaitre la longueur d'une chaine qui ne se termine pas par 0

Essaie ceci :

int len, pos;
char buf[100] = "ligne de texte";

void setup() {
  Serial.begin(115200);
  len = strlen(buf);
  pos = 4;
  Serial.print("buf["); Serial.print(strlen(buf)); Serial.print("]"); Serial.println(buf);
  Serial.print("cursor["); Serial.print(pos); Serial.print("] "); Serial.println(buf[pos]);
  backspace();
  Serial.print("buf["); Serial.print(strlen(buf)); Serial.print("] "); Serial.println(buf);
  Serial.print("cursor["); Serial.print(pos); Serial.print("] "); Serial.println(buf[pos]);
  insert('Z');
  Serial.print("buf["); Serial.print(strlen(buf)); Serial.print("]"); Serial.println(buf);
  Serial.print("cursor["); Serial.print(pos); Serial.print("] "); Serial.println(buf[pos]);
}

void backspace(void)
{
  char *dest;
  int cnt;
  memmove(buf+pos-1, buf+pos, len-pos+1);
  pos--;
  len = strlen(buf);
}

void insert(char c)
{
  char *dest;
  int cnt;
  memmove(buf+pos+1, buf+pos, len-pos+1);
  buf[pos] = c;
  pos++;
  len = strlen(buf);
}

void loop() {
  // put your main code here, to run repeatedly:
}

Au départ :

  • buffer : "ligne de texte" : 14 caractères
  • curseur en position 4, sous le 'e' de ligne
  • backspace : curseur devient 3, len devient 13
  • insertion : curseur devient 4, len devient 14

Voici le sortie (115200 baud) :

buf[14]ligne de texte
cursor[4] e
buf[13] lige de texte
cursor[3] e
buf[14]ligZe de texte
cursor[4] e

On voit bien que le curseur se déplace, mais reste sous le 'e'.

Entre nous, ce code provient d'un shell que j'avais écrit dans ma boîte il y a de nombreuses années.
Je ne peux pas te le passer en entier, pour des raisons évidentes de confidentialité.

Pour ceux que cela intéresse, le code source de memmove() :

void *
memmove (void *dest, const void *src, size_t len)
{
  char *d = dest;
  const char *s = src;
  if (d < s)
    while (len--)
      *d++ = *s++;
  else
    {
      char *lasts = s + (len-1);
      char *lastd = d + (len-1);
      while (len--)
        *lastd-- = *lasts--;
    }
  return dest;
}

On voit bien que memmove() tient compte de l'emplacement de source et destination, alors que memcpy() ne le fait pas :

void *
memcpy (void *dest, const void *src, size_t len)
{
  char *d = dest;
  const char *s = src;
  while (len--)
    *d++ = *s++;
  return dest;
}

merci pour les exemples, mon backspace ne fonctionne pas si je suis en milieu de chaine, par contre ton code fonctionnerai, c'est exactement comme ca que ca fonctionne tout comme l'insert, sur le principe, je vais tester cela.

Par expérience je sais que la difficulté dans ce genre d'exercice réside dans la gestion, en parallèle, du terminal, et de la chaîne.
Il ne faut pas hésiter à utiliser le serial monitor pour afficher les informations, chaîne, position du curseur, longueur, comme dans mon exemple.

Oui c'est ce qui est le plus difficile, déjà un terminal ansi, en plus de la gestion de chaine en direct au moment de la frappe, j'utilise le serial monitor pour afficher les informations nécessaire qui peut aider.

Exactement, c'est un bon point.

Par contre au niveau visuel du terminal, il faut que j'efface la ligne,
que j'affiche la nouvelle ligne modifiée, backspace ou insert et que je repositionne le curseur du
terminal là ou il était,.
C'est simple à faire mais c'est pour dire la difficulté de gestion visuel du terminal et du code du traitement de la chaine.

Mais tu peux aussi effacer seulement la fin de la ligne sur le terminal, ensuite afficher la fin de ligne modifiée et repositionner.
Je ne dis pas le contraire, ce n'est pas facile.

L'autre solution est d'interdire le déplacement left right du curseur, ainsi le curseur est toujours en fin de ligne, mais ce n'est pas très sexy.

Du coup @andromeda92 tu as toutes les billes pour avancer :+1:
Si tu as un problème n'hésite pas à venir sur le forum, je suis sûre que tu trouvera quelqu'un pour t'aider :slight_smile:

Tu utilise quoi pour l'affichage qui t'oblige à effacer avant d'afficher au même endroit?

Merci de votre aide et de m'avoir indiqué le cheminement.
J'utilise la carte FABGL avec ESP32, entrée clavier et souris et sortie VGA et sdcard.
C'est un peu comme la carte ESP32 VGA 1.4.

J'utilise la librairie FABGL. C'est intéressant cette carte, toutes les applis que l'on trouve sur les TFT, comme c'est en partie compatible avec la librairie GFX, GFXWrapper, je me suis amusé a transposer ce genre d'applis sur un terminal écran VGA.
Il y a longtemps j'utilisais MicroVGA, j'ai repris un peu le système de menu console ansi, un peu comme sous DOS, menu déroulant horizontal et vertical que l'on retrouve sur turbo pascal ou Edit.

Bonsoir @andromeda92
Tu pourrais mettre un lien vers ta carte
FABGL avec ESP32. Ça me fait penser au MSX des années 90.
C'est peut-être la VGA TTGO ESP32 ?

Merci.

du coup tu es en graphique pure ou tu utilise le VGATextController?

En tout cas ça à l'air rudement sympa :slight_smile:

Je m'éclate avec cette carte.
J'utilise le VGATextController, en 640x200 (80x25)

PS2Controller.begin(PS2Preset::KeyboardPort0);

  DisplayController.begin();
  DisplayController.setResolution(VGA_640x200_60HzD);

  Terminal.begin(&DisplayController, 80, 25);

Couleur de fond noir sur vert, comme les anciens terminaux

@andromeda92

Tu as un lien pour cette carte ?
Merci

Il y a la version 3.3v et 5v.
FABGL
Elle est beaucoup utilisé pour l'émulation
VIC20
Z80
C64
etc..
même un DOS ibm pc xt et bien d'autres choses
Et tous ce qui est graphique ancien PC, les anciens jeux space invaders etc ..
il gère aussi le son.

Super
Merci pour le lien
J'en commande une...
Bonne soirée à toi

Bonne soirée.

Dans ce mode tu es obligé d'effacer la zone où tu veux écrire ?

Je comprends que tu t'éclates, Ca fait remonter plein de souvenir :smiley:

oui je suis obligé car c'est un terminal ansi, il faut utiliser les code escape, ce n'est pas comme un programme console comme visual studio.

escape code

Il n'y a pas de gotoxy etc, ce sont des codes escape, un peu comme le minitel.
Par exemple pour effacer une ligne et se positionner en debut de colonne, il faut afficher le code.
soit

Terminal.print("\r\e[2K");
le \r c'est début de ligne et le \e[2K ca efface la ligne.
ou bien
Terminal.print("\e[A\r\n\e[2K");
\e[A tu remonte le curseur d'une ligne
\r\n tu passe à la ligne
\e[ tu efface la ligne

c'est assez standard, mais on peut retrouver des différences suivant les terminaux, c'est documenté

Cette séquence pourrait t'être utile :
ESC[0K : erase from cursor to end of line

Aussi :
ESC[#C : moves cursor right # columns
ESC[#D : moves cursor left # columns