strlen() compte le nombre de caractères jusqu'au caractère null (que vous ne voyez pas) qui marque la fin de la c-string. Ici "maison\r\n" c'est 8 caractères mais le tableau chaîne en comporte 9, celui en plus c'est justement ce marqueur de fin de chaîne.
la soustraction de 2 pointeurs est OK donc si q est un pointeur sur caractère qui pointe quelque part dans la chaine, q - chaine c'est la distance entre les deux (donc + 1 pour le compte de caractères)
merci pour l'information,
Pour la demonstation j'ai mis '\r\n' mais dans mon cas présent ma chaine ne contient que des '\n' et pas de 0 final, c'est une chaine qui contient un fichier chargé dans un buffer en psram.
je lit le fichier caractère par caractères que je met dans le buffer, je n'ai pas ajouté exprès le 0 à la fin.
mais ma question était de savoir si le résultat de la longueur prenait en compte le '\n' ou pas ?
si vous n'avez pas de nul final vous ne pouvez pas utiliser strchr() car il ne sait pas où s'arrêter en mémoire...
faut coder cela à la main
si vous avez des caractères UTF8 (éàçè§ôö..) il faut peut-être aussi en tenir compte car ils peuvent être codés sur plusieurs octets, tout dépend exactement de votre objectif
c'est un caractère comme un autre donc il est compté avec strlen() mais pour utiliser strlen() il faut avoir une c-string, donc le nul terminal
strlen() compte le nombre d'octets depuis le pointeur que vous donnez jusqu'à rencontrer un caractère nul.
comme c'est un programme console je n'ai pas de caractère utf8, il y a un caractere '\n' pour chaque fin de ligne, mais en effet pour la dernière ligne je règlerai cela, là je suppose que la chaine est au milieu .
C'est juste pour savoir si q - p me retourne 6 ou 7 (je n'utilise pas strlen)
S'ils pointent sur le même caractère, leur distance est 0 donc la soustraction est bien 0
si vous considérez que les caractères entre les 2 pointeurs (y compris) sont à prendre et que q est après p en mémoire alors q-p+1 c'est le nombre de caractères
vous prenez un risque d'appeler strchr() si vous n'avez pas mis de nul à la fin car la fonction va potentiellement aller lire de la mémoire qui ne lui appartient pas ➜ en C++ c'est undefined behavior.
mettez le nul à la fin et ne vous ennuyez pas... ce sera super simple pour compter ou extraire chacun des mots
oui je suis d'accord avec vous , j'ai eu des problèmes de dépassement, je vais ajouter le 0 final
par contre pour le strrchr, donc l'inverse de strchr, arrivé au premier mot de la chaine je vais avoir un problème, car il n'y a pas de '\n' au début du fichier, à moins que j'en ajoute un
oui je n'ai pas expliquer car je m'était concentrer sur ma question mais en fait:
j'ai fait un éditeur hexa mode console (escape ansi) avec gestion des touches Up, Dn, PgUp, PgDn qui fonctionne très bien et maintenant je voulais faire un éditeur de texte mais vraiment minimal, juste l'afficher sur 22 ligne et déplacer le texte avec les touches flèche bas, haut, page up, page down.
tout cela avec des pointeurs, d'ou le strchr pour récupérer la prochaine ligne, qui fonctionne dans ce sens mais l'inverse (strrchr) je n'ai pas réussià le faire fonctionner, soit j'ai des caractère bizarre ou soit ca ne fonctionne pas.
J'ai un pointeur de debut de chaine, un de fin (la taille du fichier), et le pointeur courant sur une ligne trouvé grace au strchr.
Le fichier fait 721 lignes
Je n'ai pas encore gérer le dépassement écran pour l'instant, mon fichier ne dépasse pas 75 caractèeres, j'arrive juste à faire fonctionner la touche du bas, après je ferai la touche du haut, le PgDn, le PgUp et après je m'occupe des dépassement fin écran, début de ligne, fin de fichier etc ...
Le code flèche bas fonctionne.
else if (next2 == 66) { //key down
int linelen = nextLine(mem); //+1 is \n
SERDEBUG.printf("dn linelen: %ld\r\n", linelen);
if (mem + linelen < fin ) {
mem += linelen + 1;
--Lig;
if (Lig < 1) Lig = 1;
drawtext(mem, sizearray, pdraw, Lig);
}
}
la fonction nextLine c'est là ou il y a le strchr pour aller trouvé le pointeur de la prochaine ligne.
J'augmente donc le pointeur du début de fichier à la longueur trouvée grace à next line et j'ajoute 1
car je suppose que le pointeur est caler sur le '\n', donc je place le pointeur mem + 1 pour le prochain strchr.
mais pour pour la touche up rien ne fonctionne.
if (next2 == 65) { //key up
//linelen = prevLine(mem - 2) + 1;
SERDEBUG.printf("up linelen: %ld\r\n", linelen);
mem -= linelen+1;
if (mem >= debut ) {
SERDEBUG.println("mem > debut");
Lig++;
if (Lig > totalLig) Lig = totalLig;
drawtext(mem, sizearray, pdraw, Lig);
linelen = prevLine(mem - 2);
} else {
SERDEBUG.println("mem <= debut");
mem = debut;
Lig = totalLig;
}
}
si vous travaillez avec tout en mémoire, je suppose que les fichiers sont petits et donc la parcourir est rapide.. perso donc je prendrai l'approche qui est de maintenir juste le N° de la première ligne affichée et le code recherche où se placer en fonction du N° de ligne.
par exemple essayez cela
u c'est UP U c'est PAGE UP d c'est DOWN D c'est PAGE DOWN
const char fichier[] = R"--(.0|The quick brown fox jumps over the lazy dog
.1|The quick brown fox jumps over the lazy dog
.2|The quick brown fox jumps over the lazy dog
.3|The quick brown fox jumps over the lazy dog
.4|The quick brown fox jumps over the lazy dog
.5|The quick brown fox jumps over the lazy dog
.6|The quick brown fox jumps over the lazy dog
.7|The quick brown fox jumps over the lazy dog
.8|The quick brown fox jumps over the lazy dog
.9|The quick brown fox jumps over the lazy dog
10|The quick brown fox jumps over the lazy dog
11|The quick brown fox jumps over the lazy dog
12|The quick brown fox jumps over the lazy dog
13|The quick brown fox jumps over the lazy dog
14|The quick brown fox jumps over the lazy dog
15|The quick brown fox jumps over the lazy dog
16|The quick brown fox jumps over the lazy dog
17|The quick brown fox jumps over the lazy dog
18|The quick brown fox jumps over the lazy dog
19|The quick brown fox jumps over the lazy dog
20|The quick brown fox jumps over the lazy dog
21|The quick brown fox jumps over the lazy dog
22|The quick brown fox jumps over the lazy dog
23|The quick brown fox jumps over the lazy dog
24|The quick brown fox jumps over the lazy dog
25|The quick brown fox jumps over the lazy dog
26|The quick brown fox jumps over the lazy dog
27|The quick brown fox jumps over the lazy dog
28|The quick brown fox jumps over the lazy dog
29|The quick brown fox jumps over the lazy dog)--";
const size_t hauteurEcran = 5;
size_t ligneDebut = 0;
const char * debut = nullptr;
size_t nombreDeLignes = 0;
size_t compteLignes(const char * s) {
size_t n = *s == '\0' ? 0 : 1;
while (*s)
if ((*s++ == '\n') && (*s != '\0')) n++;
return n;
}
const char * pointeurDebutLigne(size_t numeroLigne) {
const char * ptr = debut;
for (size_t i = 0; i < numeroLigne; i++) {
while (*ptr && *ptr++ != '\n');
}
return ptr;
}
void imprime(size_t numeroLigne) {
char * ptr = pointeurDebutLigne(numeroLigne);
for (size_t i = 0; i < hauteurEcran; i++) {
while (*ptr && *ptr != '\n') Serial.write(*ptr++);
Serial.write('\n');
if (*ptr) ptr++;
}
Serial.println("----------");
}
void setup() {
Serial.begin(115200); Serial.println();
debut = fichier;
nombreDeLignes = compteLignes(debut);
if (nombreDeLignes == 0) {
Serial.println("erreur, fichier vide");
while (true) yield();
}
imprime(ligneDebut);
}
void loop() {
switch (Serial.read()) {
case 'u': // up
if (ligneDebut > 0) ligneDebut -= 1;;
imprime(ligneDebut);
break;
case 'U': // page up
if (ligneDebut >= hauteurEcran) ligneDebut -= hauteurEcran;
else ligneDebut = 0;
imprime(ligneDebut);
break;
case 'd': // down
if (ligneDebut < nombreDeLignes - 1) ligneDebut += 1;;
imprime(ligneDebut);
break;
case 'D': // page down
if (ligneDebut < nombreDeLignes - hauteurEcran) ligneDebut += hauteurEcran;
else ligneDebut = nombreDeLignes - 1;
imprime(ligneDebut);
break;
}
delay(1);
}
Merci , je vais m'inspirer de ton code, et du coup aussi, les u U d D c'est mieux , plutôt que de tester le code escape, le code 91 et les touches 65 et 66.
Comme tu dit, je suis obligé de me limiter sur l'ESP32
la taille max c'est 1MB, il y a 16MB, mais arduino prend en compte seulement 4MB et les 4MB sont partager en deux pour la PSRAM, ce qui fait 2MB, je prend la moitié.
Déjà sur un fichier de 36k il y a 721 lignes, je me limiterai peut être à 64ko.
si vous voulez travailler hors mémoire et dans un fichier sans que ça rame, vous pouvez créer un fichier binaire parallèle à celui que vous voulez afficher et vous codez sur un uint32_t la position du début de de chacune des lignes lors d'une première passe. Comme chaque position fait le même nombre d'octets, trouver le début de la ligne N (en commençant à 0) revient à lire 4 octets dans ce fichier à la position 4.N et ça vous donne la position à laquelle vous placer (seek()) dans le ficher texte.
Oui c'est une solution aussi, je n'y avait pas pensé, mais au départ je vais étudier ton code pour la mise en oeuvre, car je cherche juste à afficher un fichier texte, parfois j'ai besoin de voir le contenu d'in fichier texte de la sdcard et ca permet de naviguer avec les touches. Merci.