Remplacer concaténation String en C

Bonjour,
J'ai une fonction qui utilise les String mais j'aimerais remplacer les String par du C.

String Maclasse::getString(unsigned long code) {
  String str = "";
 
  if (isVisualisable(code)) {
    if (code < 0x80) { // U+0000 à U+007F
      str += char(code);
    } else if (code < 0x800) { // U+0080 à U+07FF
      str += char((0b110 << 5) | (code >> 6));
      str += char((0b10 << 6) | (code & 0x3F));
    } else if(code < 0x10000) { // U+0800 à U+FFFF
      str += char((0b1110 << 4) | (code >> 12));
      str += char((0b10 << 6) | ((code >> 6) & 0x3F));
      str += char((0b10 << 6) | (code & 0x3F));
    }
  }
  return str;
}

comment remplacer le str += en C ?
avec des strcat ?
pour le retour de la fonction ce serait j'imagine char * au lien de String.
Avez vous une idée ?

Attention à correctement dimensionner la chaîne destination afin qu'elle puisse contenir la chaîne complète après concaténation.
Il vaut mieux travailler avec strncat() qui empêche le débordement si la chaîne destination est mal dimensionnée.

Merci, je vais tester cela.

mais si je fais cela ca ne fonctionne pas
char str[10];
strncat(str, char(code), 1);

je dois peut etre faire ceci
strncat(str, &(char(code)), 1);

car le 2eme parametre est de type const char *

ou peut etre ceci

char str[10]
char buffer[0]
buffer[0] = char(code);
strncat(str, &buffer[0], 1);

ou bien

buffer[0] = char((0b110 << 5) | (code >> 6));
buffer[1] = char((0b10 << 6) | (code & 0x3F));
strncat(str, buffer, 2);

les arguments de strcat sont des c-string donc ce sont des tableaux de char terminés par un 0.

buffer a 0 élément donc aucune longueur en conséquence de quoi aucune réservation d'espace en mémoire. Donc potentiellement des problèmes de variables écrasées.

Si tu veux juste ajouter des char un par un à la fin d'une c-string, tu as aussi vite fait de faire une petite fonction qui récupère la longueur de la chaîne destination avec strlen() place le char en question à la fin du tableau et ajoute un 0 derrière pour terminer la chaîne.

désolé je me suis trompé, la déclaration c'était
char buffer[10];
strncat termine la c string par un 0

Bonjour,

Attention, cela dépend de la version du compilateur
Cf. la discussion: Does strncat() always null terminate?

NB: Le mieux est de faire un essai aux limites pour s'en assurer :wink:

A suivre...

Je parlais de quelque chose comme ça

// test straddchar

char myString[40] = "This is a string ending with a dot";
char c = '.';

// a function to append a char at the end of a c-string
char* straddchar(char * dest, char car){
  int len = strlen(dest);
  dest[len] = car;
  dest[len+1] = '\0';
  return dest;
}

void setup() {
  Serial.begin(115200);
  Serial.print("myString length is "); Serial.print(strlen(myString)); Serial.println(" characters.");
  Serial.println(myString);
  Serial.println();
  Serial.println("Adding the dot");
  Serial.println();
  straddchar(myString, c);
  Serial.print("myString length is "); Serial.print(strlen(myString)); Serial.println(" characters.");
  Serial.println(myString);
}

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

Bonsoir @fdufnews
En fait il veut extraire les 1, 2 ou 3 octets d’un encodage de caractères au format UTF-8 et les combiner de sorte qu’il soit possible de les afficher :wink:
Apparemment sa fonction est une méthode d’une classe.

Bonne soirée

un truc comme cela peut être ?

// attention str doit avoir au moins 4 octets de dispos.
bool Maclasse::getString(unsigned long code, char* str) {
  if (! isVisualisable(code)) return false;

  str[0] = '\0'; // Initialiser la cString à une chaîne vide

  if (code < 0x80) {           // U+0000 à U+007F
    str[0] = char(code);
    str[1] = '\0';
  } else if (code < 0x800) {   // U+0080 à U+07FF
    str[0] = char((0b110 << 5) | (code >> 6));
    str[1] = char((0b10 << 6) | (code & 0x3F));
    str[2] = '\0';
  } else if (code < 0x10000) {  // U+0800 à U+FFFF
    str[0] = char((0b1110 << 4) | (code >> 12));
    str[1] = char((0b10 << 6) | ((code >> 6) & 0x3F));
    str[2] = char((0b10 << 6) | (code & 0x3F));
    str[3] = '\0';
  }
  return true;
}

oui c'est exactement ca, la fonction originel est ceci:

String Minitel::getString(unsigned long code) {
  // Fonction proposée par iodeo sur GitHub en février 2023
  // Convertit un caractère Unicode en String UTF-8
  // Renvoie "" si le code ne correspond pas à un caractère visualisable
  String str = "";
  // Pour test
  /*
  Serial.print("isVisual ");
  Serial.print(code);
  Serial.print("\t : ");
  Serial.println(isVisualisable(code));
  */
  if (isVisualisable(code)) {
    if (code < 0x80) { // U+0000 à U+007F
      str += char(code);
    } else if (code < 0x800) { // U+0080 à U+07FF
      str += char((0b110 << 5) | (code >> 6));
      str += char((0b10 << 6) | (code & 0x3F));
    } else if(code < 0x10000) { // U+0800 à U+FFFF
      str += char((0b1110 << 4) | (code >> 12));
      str += char((0b10 << 6) | ((code >> 6) & 0x3F));
      str += char((0b10 << 6) | (code & 0x3F));
    }
  }
  return str;
}

sauf que quand j'ai voulu modifier cette fonction le fait de retourner la chaine,
char * Minitel::getString(unsigned long code) {
...
j'avais une erreur car je retournais un pointeur local, il faut faire comme tu viens de faire, passer str en parametre ou faire:
char * str = (char *)malloc(10);
a ce momment la je peux faire
return str
évidement faut libérer la mémoire après.

elle doit retourner une chaine pour la suite des opérations, si elle est utilisé dans une autre fonction ou bien la passer en paramètre, et elle
sera modifiée par getString

Bonsoir @J-M-L
Je pense qu’il souhaite retourner les 1 (ASCII), 2 ou 3 octets dans une chaîne en lieu et place de sa String : str.

Bonne soirée

Salut

le pointeur sur le début de chaîne est passé en paramètre de ma fonction
(j'ai choisi de retourner un bool pour dire si oui où non ça avait fonctionné mais on pourrait aussi toujours juste retourner la chaîne vide)

// attention str doit avoir au moins 4 octets de dispos.
char* Maclasse::getString(unsigned long code, char* str) {
  str[0] = '\0'; // Initialiser la cString à une chaîne vide
  if (! isVisualisable(code)) return str;


  if (code < 0x80) {           // U+0000 à U+007F
    str[0] = char(code);
    str[1] = '\0';
  } else if (code < 0x800) {   // U+0080 à U+07FF
    str[0] = char((0b110 << 5) | (code >> 6));
    str[1] = char((0b10 << 6) | (code & 0x3F));
    str[2] = '\0';
  } else if (code < 0x10000) {  // U+0800 à U+FFFF
    str[0] = char((0b1110 << 4) | (code >> 12));
    str[1] = char((0b10 << 6) | ((code >> 6) & 0x3F));
    str[2] = char((0b10 << 6) | (code & 0x3F));
    str[3] = '\0';
  }
  return str;
}

on passe le buffer lors de l'appel et la fonction retourne aussi le pointeur sur le début du buffer

Désolé @J-M-L
J’ai été trop vite, sincèrement je ne l’avais pas vu :wink:
PS : je suis avec le petit écran de mon iPhone XR et si je ne vais pas vers la droite, je ne vois pas tout :wink:
@J-M-L , Il me faudra acheter un pro max ( je ne sais pas lequel vous avez)

Merci.
je vais utiliser ta fonction, je préfère plutot que les String, j'aime pas ça lol

assurez vous cependant qu'il y a toujours assez d'espace dans le buffer....
la version avec la String faisait de l'allocation dynamique

ok, je m'assurerai de cela. Merci.

vous savez qu'au plus il faut 4 octets donc vous pouvez faire

// maClasse et code existent par ailleurs
char utf8[4];
maClasse. getString(code, utf8);

et comme l'appel retourne aussi le pointeur vous pouvez faire directement un strncat() avec l'appel de la fonction si vous voulez rajouter les octets à une autre chaîne.