Go Down

Topic: les string me rendent fou ! :) (Read 519 times) previous topic - next topic

fredo5962

bonjour j'ai besoin de vos lumieres car la.... je deviens dingue !

je vous explique, sur un arduino uno, j'ai branché un shield carte sd afin de lire, un petit fichier texte qui contient des numéros de telephone.

numero0 est un string

je recupere le numéro via ce code

myFile = SD.open("numero.txt");
 
     for (int i=0; i<13; i++ )
  {
           myFile.seek(i); // se positionne à la position i
           numero0=numero0+char(myFile.peek()); // affiche le caractère courant
         }

je fais le test, numero0 est donc +33781000000


je veux utliser ce numero pour envoyer un sms
j'utilise donc ce code


    sim808.print("AT+CMGS=\"");
    sim808.print(numero0);
    sim808.print("\"");
    sim808.println("");
    delay(300);
    sim808.print("petit coucou de l'arduino :)");
    delay(200);
    sim808.println((char)26); // End AT command with a ^Z, ASCII code 26
    delay(200);
    sim808.println();
    delay(20000);
    sim808.flush();



et bin... ca ne fonctionne pas ! ca ne s'envoie pas !

pire ! si je déclare un autre string message1

et que je l'appelle "+33700000000"  bah lui il fonctionne !?!
si compare message0 et message 1.. ils sont identiques ! l'un part pas l'autre !!!

je vous donne le programme complet si vous pourriez m'indiquer ou ca plante.... merciiiiiii

Code: [Select]

#include <SD.h>
#include <SoftwareSerial.h>
const int chipSelect = 10;  //pin de l'Arduino reliee au CS du module SD
SoftwareSerial sim808(5, 6); // RX,TX
Sd2Card card;
SdVolume volume;
SdFile root;
File myFile;
int val = 0;
String numero0;
String numero1;

void setup()
{
  sim808.begin(9600);
  Serial.begin(9600);
  lecture();
}


void loop() {
  demo();

}

void demo() {
  Serial.println("Envoie du message...");
  Serial.println(numero0);
  numero1 = "+33786000000";
  Serial.println(numero1);
// ICI j'affiche numero0 et numero1.... ils sont identiques ! à l'écran...

  sim808.print("AT+CMGS=\"");
  sim808.print(numero1);  // si j'envoie le numero0 ca passe pas,  le numero1..ca passe ?!?
  sim808.print("\"");
  sim808.println("");
  delay(300);
  sim808.print("petit coucou de l'arduino :)");
  delay(200);
  sim808.println((char)26); // End AT command with a ^Z, ASCII code 26
  delay(200);
  sim808.println();
  delay(20000);
  sim808.flush();
  Serial.println("Message envoyé");

}

void lecture() {

  Serial.print("\nRecherche de la carte SD...");
  pinMode(10, OUTPUT);
  if (!card.init(SPI_HALF_SPEED, chipSelect)) // Pas de carte ?
  {
    Serial.println("pas de carte?");
    return;
  }

  if (!volume.init(card)) // Carte formatée ?
  {
    Serial.println("La carte n'est pas formatee?");
    return;
  }
  if (!SD.begin(chipSelect)) // Défaut initialisation ?
  {
    Serial.println("Echec de l'initialisation");
    return;
  }
  Serial.println("Initialisation OK.");
  myFile = SD.open("numero.txt");
  if (myFile) {
    Serial.println("Contenu du fichier:");

    for (int i = 0; i < 13; i++ )
    {
      myFile.seek(i); // se positionne à la position i
      numero0 = numero0 + char(myFile.peek()); // affiche le caractère courant
    }
    for (int i = 13; i < 27; i++ )
    {
      myFile.seek(i); // se positionne à la position i
      numero1 = numero1 + char(myFile.peek()); // affiche le caractère courant
    }
   

    myFile.close(); // ON FERME
  }
  else {
    Serial.println("impossible d'ouvrir le fichier pour la lecture"); // Défaut de fichier

  }
}








   



fredo5962

l'horreur .... incomprenhensible....

je rajoute un petit test .

if (numero0!=numero1){
Serial.println("numero différent...");}

if (numero0==numero1){
Serial.println("numero identique...");}


et il m'affiche sans la moindre honte...


+33786000000

+33786000000
numero différent...

CelticLord

Bonjour, déjà evite d utiliser des String, utilise plutôt des tableaux de char numero0 char[13]

fdufnews

#3
Mar 27, 2019, 02:57 pm Last Edit: Mar 27, 2019, 02:58 pm by fdufnews
Le problème de print c'est qu'il n'affiche que les caractères imprimable. S'il y a des caractères de contrôle ils ne sont pas visibles.Il vaut mieux faire
Code: [Select]
Serial.print("**");
[Serial.print(numero0);
Serial.print("**");
comme ça tu verras s'il y a des caractères cachés.
Ou bien faire imprimer la chaîne caractère par caractère en hexa pour voir s'il n'y aurais pas un code non imprimable

dbrion06

Code: [Select]
    for (int i = 0; i < 13; i++ )
    {
      myFile.seek(i); // se positionne à la position i
      numero0 = numero0 + char(myFile.peek()); // affiche le caractère courant
    }


deviendrait, pour censurer les caractères non imprimables

Code: [Select]
    for (int i = 0; i < 13; i++ )
    {
      myFile.seek(i); // se positionne à la position i
      char c = myFile.peek();
      if (((c <= '9') && (c>= '0') ) || (c == '+')) {
      numero0 = numero0 + c; // affiche le caractère courant
    } else {
     Serial.print("<"); Serial.print(c);Serial.println(">"); // pour voir si le test est suffisant
    }

fredo5962

hey hey hey... ouiiiiiiii vous avez raison !

j'ai rajouté
 Serial.println(numero0.length());

Serial.println(numero1.length());


+33786000000

longueur de numéro 0... : 13
+33786000000
longueur de numéro 1... : 12

on dirait qu'il y a un 'enter' .. invisible !
je vois pour virer ce truc...

dbrion06

"je vois pour virer ce truc..."
ne concaténez que des caractères lisibles, ou mieux, faisant partie des caractères admissibles pour les téléphones : '0' à '9' et '+', manifestement...

fredo5962

Franchement.. BRAVO !
vous êtes genial ...
j'ai utilisé votre filtre de caracteres lors du chargement du fichier... et ca fonctionne parfaitement !

genial genial genial !!!!

merciiiiiiii


CelticLord

C est tjs le problème avec la déclaration String elle n est pas fiable.
C est la notion de pointeurs en langage C qu il faut bien intégrer et utiliser les char array a la place de String.
Ta différente dans la longueur de ta chaine vient du fait que numero0 contient certainement la caractère \0 au 13eme byte et pas l autre.
De plus ta comparaison de chaine avec un = ne donnera pas de bon résultat car tu compare des pointeurs pas des chaines, approfondi tout ca pour tes futurs codes.

fredo5962

oh que oui tu as raison, je reve de m'en passer !!

mais la concretement dans ce programme, comment je peux les remplacer ?

-Standby

Quote
les string me rendent fou ! :)
Quote
l'horreur .... incomprenhensible....
Quote
Bonjour, déjà evite d utiliser des String
Quote
"je vois pour virer ce truc..."
Quote
Franchement.. BRAVO !
Quote
oh que oui tu as raison, je reve de m'en passer !!
Je sors ---> []
The Mind is like a parachute it works best when opened.

dbrion06

Quote
mais la concretement dans ce programme, comment je peux les remplacer
Une saine et sensée critique des strings et des solutions pour les remplacer (lire char aptès char un fichier ou une ligne série est équivalent) est dans https://forum.arduino.cc/index.php?topic=500683.0
les charactères arrivent l'un après l'autre, sont mis dans un tableau de caractères s'ils sont valides, et à la fin (matérialisée par une fin de ligne dans un fichier ou sur une ligne série), on les exploite. La théorie sous jacente est exposée avec talent et des liens judicieux.

la réponse courte est donc : un tableau de 13 ou 14 charactères, terminés par \0 ;

fredo5962

#12
Mar 27, 2019, 06:47 pm Last Edit: Mar 27, 2019, 06:52 pm by fredo5962
 :o après une lecture reposée... j'ai RIEN compris du tout... sauf que char prend la moitié de place que string... mais ca... au final je m'en doutais déjà!

bref, j'ai essayé de modifier les strings en char
comme ceci .

string numero0; est devenu char numero0[12];
12 caracteres pour +33786000000
jusque la ... ca va ;)

ensuite, j'ai modifié logiquement la facon de recupérer les données.

j'ai donc fait ceci :

for (int i=0; i<13; i++ )
  {
           myFile.seek(i); // se positionne à la position i
           char c = myFile.peek();
      if (((c <= '9') && (c>= '0') ) || (c == '+')) {
     
      numero0 [ i ] = c;
     
      }
         }

si ca fonctionne comme un tableau..
numero0[0] = premier caractère
numero0[1] = deuxième caractère

je dirai que jusque la... ca va !

confiant, je fais la mm chose pour la suite !


en rajoutant juste une variable pour toujours remplir à partir de 0;

voici ce que ca donne .

count=0;
 for (int i=13; i<27; i++ )
  {
           myFile.seek(i); // se positionne à la position i
           char c = myFile.peek();
      if (((c <= '9') && (c>= '0') ) || (c == '+')) {
      count=i-13;
      numero1[count] = c;
     
      }
         }

et je vous laisse deviner le résultat...
numero1.... grave à l'ouest !!

résultat affiché :


dans la boucle de lecture, numero 0 : +33700000000
dans la boucle de lecture, numero 1 :


bref.... char ou string.... c'est une galère !



dbrion06

Déjà, vous devriez donner un peu plus de place que 12 à vos tableaux de caractères, qui doivent avoir, tout à la fin, le caractère \0 ou 0;

Code: [Select]

char numero0[14], numero1[14];// très légèerment surdimensionnés
int indicenum = 0;
for (int i = 0; i<13; i++ ) {
      myFile.seek(i); // se positionne à la position i
      char c = myFile.peek();
// filtrage et remplissage  si possible
      if (((c <= '9') && (c>= '0') ) || (c == '+')) {
             numero0[indicenum] = c;
             indicenum ++; // prêt à écrire dans le suivant
      }
   }
 numero0[indicenum]  = 0; // est terminé effectivement
indicenum = 0;
 for (int i=13; i<27; i++ )  {
    myFile.seek(i); // se positionne à la position i
    char c = myFile.peek();
     if (((c <= '9') && (c>= '0') ) || (c == '+')) {
      numero1[indicenum ] = c;
      indicenum ++;
      }
    }
 numero1[indicenum]  = 0;

(non testé) devrait marcher -en tous cas, serait plus voisin de la gestion des caractères classique

hbachetti

#14
Mar 27, 2019, 07:21 pm Last Edit: Mar 27, 2019, 07:22 pm by hbachetti
1ère remarque : seek ne sert à rien

Quand tu ouvres un fichier, l'index vaut zéro.
Ensuite tu utilises read(), à chaque caractère lu, l'index s'incrémente, donc au prochain read() tu liras le caractère suivant, automatiquement.

Exemple ici : https://github.com/greiman/SdFat/blob/master/examples/ReadWrite/ReadWrite.ino

Ligne 61 : ouverture d'un fichier, lecture et affichage.

Un petit myFile.available() avant de lire ne fait pas de mal non plus, pour savoir si le fichier contient encore des données.

2ème remarque : on termine toujours une chaîne de caractères par un caractère NULL (zéro binaire), ce que tu ne fais pas.

3ème remarque : tu lis deux numéros
- index 0 à 12
- index 13 à 26

Si les numéros sont sur deux lignes distinctes dans le fichier, il y a forcément un séparateur entre les deux ('\n' ou "\r\n")

Si tu commençais par poster le contenu du fichier, tu ne crois pas que ce serait une bonne idée ?

Linux is like a wigwam: no Windows, no Gates, and an Apache inside ...

Go Up