Relire une ligne .csv

Bonjour. Je suis un peu touche à tout, et aujourd’hui je voudrais relire une donnée d’un fichier .csv. Les séparateurs sont des “;” Je voudrais la 5e donnée( MaData) donc après 4 “;” .

Est ce que dans la ligne extraite du .csv qui s’appelle SLine:

  for(int i=0,i<sizeof(SLine),i++){
    byte pos[i] = SLine.indexOf(";");
  }
  String STpInt =SLine.subString(0,pos[0]);
  String STpExt =SLine.subString(pos[0],pos[1]);
...
  String MaData =SLine.subString(pos[3],pos[4]); 

c’est propre, ou y a t-il une solution autre ? Je signale que je n’ai pas encore le lecteur…. Donc j’ai fait ça au pif.

  • indexOf(val), commence toujours sa recherche à partir du début de la chaîne.
    Donc tu auras toujours l'index du premier ";"
  • byte pos[i] crée une variable locale à la boucle qui sera inconnue hors de celle-ci, donc inexploitable dans le reste de la fonction.

Pour continuer la recherche il faut utiliser la forme indexOf(val, from)
from étant l'index à partir duquel la recherche commence.

Il faudrait faire quelque chose dans ce genre

curPos = 0; // la recherche commence au premier caractère de la chaîne
byte pos[MAX_CHAMPS]; // on déclare un tableau de MAX_CHAMPS valeurs

  for(int i=0,i<MAX_CHAMPS,i++){
    curPos = SLine.indexOf(";", curPos); // la recherche commence à curPos
    pos[i] = curPos;
    curPos++; // la prochaine recherche commencera au caractère suivant.
  }

MAX_CHAMPS c'est le nombre maximal de champs dans ton fichier csv à définir par ailleurs.
Ceci dit, comme tu ne veux que la cinquième valeur tu pourrais te contenter d'un tableau de taille 5.

Edit: correction du test de fin dans le if

En fait la déclaration byte pos[i] à l’intérieur de la boucle recrée un nouveau tableau à chaque itération, ce qui n’a pas de sens.

A noter aussi sizeof(SLine) n’est pas la longueur de la chaîne, mais la taille de l’objet String, sans rapport avec le nombre de caractères…

Idem

Il ne faut pas sizeof…

Ah oui, je n'ai pas réfléchi j'ai juste changé l'argument.
C'est corrigé.

Bonjour thierryr51

Pour ce faire, il y a la bibliothèque StringSplitter:
image
.

Cordialement
jpbbricole

Merci les gars. C’est super sympa. Je vous dois bien une bière, mais j’ai peur des distances…
Je ne connaissais pas la bibliothèque indiquée par jpb. Elle mérite de l’intérêt. Comme mon soft commence tout doucement à saturer mon arduino, je vais agir au mieux.

Encore une petite question:

SD.read renvoie quoi ?

J’ai essayé String Sline=monFichier.read(); mais le compilateur me dit

conversion from “int” to “String” is ambiguous.

Les exemples donnés sur le net sont du style

Serial.write(monFichier.read()) Avec ça on galère un peu.

Ce n’est pas un problème de contenu car le fichier n’existe pas encore. On est au stade de la compilation.

Cela ne lit qu'un octet.
Pour lire une chaîne, essaies:
monFichier.readStringUntil('\n');

Effectivement. C’est beaucoup mieux. Merci jpb

Pour ordonner mes données je voulais mettre un repère basé sur une pseudo date. Je voulais concaténer l’annee et je jourAnnee

int annee = 2025;
int jourAnnee = 300;

void setup() {

Serial.begin(9600);
unsigned long periode = (annee*1000)+ jourAnnee ;
String Speriode= String(periode);
Serial.print(" periode ");Serial.print( Speriode);
}

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

}

Ben là mon arduino ne sais plus compter. La réponse est

periode 4294960980

Ça y est j’ai trouvé: annee doit être egalement en “unsigned long”

Pas forcément mais ça résout le problème effectivement.

Avez vous compris pourquoi ? Tout se passe dans

Oui, pour 2 raisons. La première est les zero a gauche de la 2e variable: Comment mettre un zero devant une variable? - #5 by amic
La 2e est la limitation des integers https://arduino-france.site/variables-arduino/ à 32767.

J’ai réduis mon code à 1 ligne

String Speriode= String(annee*1000 + jourAnnee);

en fait c’est dû à une règle qui dit que un nombre écrit littéralement comme 1000 va être du plus petit type pouvant le contenir, signé si possible. Donc 1000 était un int.

Comme année était aussi un int, la multiplication 1000*annee se faisait en type entier int et ça débordait

En mettant année en unsigned long, vous avez alors une multiplication entre un int et un unsigned long, la règle de compilation dit que le type le plus petit est implicitement promu vers le rang du plus grand type avant l’opération et en unsigned si celui ci est non signé. Donc 1000 est promu en unsigned long et la multiplication se fait en unsigned long et il n’y a plus de débordement.

Vous auriez pu écrire aussi 1000ul * annee et le suffix ul (unsigned long) disait au compilateur de passer le nombre en type unsigne long. La règle s’applique alors dans l’autre sens et c’est annee qui aurait été promue vers unsigned long avant de faire la multiplication.

La meilleur façon de faire sans doute aurait été de déclarer une constante typée pour votre facteur multiplicateur

Notez que vous n’avez pas besoin de passer par une String qui consomme de la mémoire pour imprimer

constexpr unsigned long facteurMultiplicateur = 1000;
int annee = 2025;
int jourAnnee = 300;

void setup() {
  Serial.begin(9600);
  unsigned long periode = (annee* facteurMultiplicateur)+ jourAnnee ;
  Serial.print(" periode ");
  Serial.println(periode); // print sait imprimer un nombre, println rajoute un passage à la ligne ensuite 
}

void loop() {}