les string me rendent fou ! :)

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

#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

  }
}

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...

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

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

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

    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

    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
    }

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...

"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...

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

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.

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

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

les string me rendent fou ! :slight_smile:

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

Bonjour, déjà evite d utiliser des String

"je vois pour virer ce truc..."

Franchement.. BRAVO !

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

Je sors ---> []

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 Ecouter le Port Série ou un keypad (applicable à 1 flux de données asynchrone ) - Tutoriels et cours - Arduino Forum
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 ;

: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 :wink:

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 !

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;

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

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 ?

Hello

pour répondre à dbrion06.

merci beaucoup de ton aide et de m'éclairer ! j'avais utilisé 12 car lorsque j'utilisais la fonction length sur le string qui contenait le numéro de telephone, il me retournait 12.. donc j'ai pas cherché plus loin :slight_smile:

effectivement je ne rajoute pas un 0 à la fin... mais pourquoi le faire ?? mon numéro de telephone aura un 0 en plus à la fin et quand j'appelle numero0 ou numero1, je vais me retrouver avec un 0 a la fin qui sert à rien ??
ou alors je dois utiliser à la fin un string du genre ...
numerofinal = numero0[1]+numero0[2]....jusque + numero0[12]

ou alors il y a une solution pour lorsque j'appelle numero0 il me donne tout sauf le 0 de la fin ? concact ?

pour répondre à hbachetti,

merci de ton aide également, en fait le seek me sert à positionner le début de la chaîne que je veux lire, car je ne cherche pas à l'afficher, je cherche à le lire et à le stocker pour l'utiliser ensuite comme numéro de téléphone.

le fichier lu est un fichier on ne peut plus basique créé avec note de Windows ou les numéros sont les uns en dessous des autres....

cela dit... maintenant que tu le dis... s'ils sont les un en dessous des autres.... il y aurait bien un caractère caché qui le dit quelque part... sinon ils seraient les uns a la suite des autres....

numero.txt

+33796000000
+33900000000
etc...

vraiment désolé de vous embêter avec ca.. mais je débute et comme j'apprends tout seul... bref... heureusement que vous êtes la à m'aider !

"effectivement je ne rajoute pas un 0 à la fin... mais pourquoi le faire ??"
Parce que que les tableaux de caractères c DOIVENT se terminer par le charactère de valeur entière 0 (\0), sinon, les fonctions de manipulation -calcul de la longueur, affichage, conversion en string- donnent des résultats bizarres... Comme, à l'initialisation, un tableau de chars peut être rempli de caractères nuls, cette nécessité peut être cachée, donnant l'illusion qu'un bout de code marche... mais il vaut mieux le faire explicitement.
En passant, il ne faut pas confondre un caractère et son équivalent entier; exemple, le caractère 'a' a pour valeur, en entier 97 -en decimal- ou 0x61 -en hexa-; le caractère '9' a pour representation entière 57, 0x39 et le carctère '0' est codé en 48 -0x30-

sh-4.1$ python
ordPython 2.7.3 (default, Dec 18 2012, 13:50:09) 
[GCC 4.5.3] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
(>>> ord('a')
97
>>> ord('9')
57
>>> ord('0')
48
>>> chr(0x39)
'9'
>>> chr(0x30)
'0'

HBachetti vous indique une piste bien plus prometteuse que le fait de sauter des caractères cachés (et on ne sait pas comment faire, sans bricoler, pour lire , disons, les 3 derniers numéros de téléphone; avec une lecture plus standard de votre fichier, c'est plus facile.
A noter que si votre fichier a été créé sous windows, il y a 2 caractères cachés pour le changement de ligne : \n -10 - et \r -13 (on les montre généralement comme ça...). Sous linux, il n'y en a qu'un (donc, les fichiers texte crées sous GNUlinux peuvent parfois sembler bizarres à des applications d'un autre système).
Il est vraisemblable (mais encore une fois, sans le fichier, on doit faire des paris) que l'on saute les fins de ligne -qui sont des caractères cachés-. A noter enfin que le filtrage que j'utilise fait un pari sur la liste des caractères valides pour les numéros de téléphone (la démarche de HBachetti est plus rationnelle, même si elle "marche" peut être un peu moins vite au début)

Si les Nos sont sur 2 lignes, Idéalement on devrait lire (avec read) jusqu’au ‘\n’ en ignorant un éventuel ‘\r’ et en filtrant peut-être les caractères non voulus, et ne pas faire d’hypothese Sur la longueur exacte du numéro, juste sur sa taille Max. S’ils sont sur la même ligne il doit y avoir un séparateur et faut lire jusqu’à tomber sur ce séparateur

merci de ton aide également, en fait le seek me sert à positionner le début de la chaîne que je veux lire, car je ne cherche pas à l'afficher, je cherche à le lire et à le stocker pour l'utiliser ensuite comme numéro de téléphone.

1ère chose avant d'apprendre à coder : apprendre à lire

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.

il y aurait bien un caractère caché qui le dit quelque part... sinon ils seraient les uns a la suite des autres....

Oui, ces caractères sont des retours à la ligne et des retours chariot comme dans un traitement de texte.
Lire exactement 12 caractères dans le fichier, 2 fois de suite, n'est pas la bonne méthode.

Pourquoi ?
Parce que le caractère que tu vas lire en 13è position est un retour à la ligne '\n'.
En 14è position tu auras probablement un retour chariot '\r'.

Il faut lire le fichier jusqu'à la fin :
si tu rencontres '\n' tu mets un '\0' en bout de chaîne
si tu rencontres '\r' tu ignores

Quand on lit dans un fichier on vérifie en permanence que l'on n'a pas atteint la fin :

    while (myFile.available()) {
      char c = myFile.read();

Re,
J'ai beau chercher.. J'ai même fait afficher caractère par caractère... Y a jamais un / suivi d'un N ??!?....

Ensuite j'ai bien compris le read qui avance pas à pas... Donc au pire étant donné que je connais le format des numéros.... Des que je tombe sur un +c'est le début de mon numéro et il est suivi de 11 chiffres.. Et ça ne sera toujours que 11 chiffres ! Ils vont quand mm pas me rajouter des fintes dans mes numéros... Après le reste je l'ignore... Je fais des read dans le vide et j'attends de tomber sur le prochain +...

Je rajouterai un / et un O pour voir... (Mais j'ai bien peur de galèrer à les retirer) avec ça à la fin de mes numéros.. Mais j'avance.. C'est bien ça le principal.. Et ça c'est grâce à vous !. Merciiiiiiii