Issue when populating string array

Hello. I have a function for read this file from an SD card:

-56.08443260000001;-34.890648;VELOCIDAD
-56.1727631;-34.8601494;VELOCIDAD
-56.1537409;-34.8747532;VELOCIDAD
-56.1499214;-34.8560557;VELOCIDAD
-56.0450363;-34.8761087;VELOCIDAD
-56.12125400000001;-34.8869694;VELOCIDAD
-56.0626316;-34.8973888;VELOCIDAD
-56.177339;-34.9143394;VELOCIDAD
-56.1802089;-34.9145901;LUZ_ROJA
-56.1591107;-34.9228155;LUZ_ROJA
-56.1444497;-34.88751510000001;LUZ_ROJA
-56.0782099;-34.881108;LUZ_ROJA
-56.1740828;-34.8698063;LUZ_ROJA
-56.1602426;-34.889328;LUZ_ROJA
-56.1429477;-34.8763023;LUZ_ROJA
-56.1613369;-34.9027563;LUZ_ROJA
-56.1246657;-34.8973888;LUZ_ROJA
-56.1515951;-34.9112557;LUZ_ROJA
-56.1879873;-34.9055367;LUZ_ROJA
-56.1902404;-34.8712499;LUZ_ROJA

The "radares.txt" file contains latitude;longitude;radar_type
The idea is read line by line, and populate ever line in an array position (the array is called lineas[]).

Here is the code i'm running:

// open the file for reading:
     myFile = SD.open("radares.txt", FILE_READ);

        int index = 0;


        int caracterInt;
        char caracter;
        String linea;
        String lineas[50];

         while (myFile.available()) {
            caracterInt = myFile.read();
            caracter = caracterInt;
            if (caracter != '\n')
            {
              linea += caracter;
            }
            else
            {
              [b]lineas[index] = linea;
              Serial.print("Indice: ");
              Serial.print(index);
              Serial.print(" - Valor: ");
              Serial.print(linea);
              Serial.print(" - Array: ");
              Serial.println(lineas[index]);[/b]
              index++;
              linea = "";
            }
            
            
          }


//          for (int i=0; i<=50; i++)
//          {
//            Serial.print(i);
//            Serial.println(lineas[i]);
//          }



        
      if (myFile)
      {

          // close the file:
          myFile.close();


      }
      else
      {
          // if the file didn't open, print an error:
          Serial.println("error opening radares");
    }

When i do that, i see the array is not populating correctly. There are some missing radars that are not in the array. Why?

Here is the serial monitor output:

Indice: 0 - Valor: -56.08443260000001;-34.890648;VELOCIDAD - Array: -56.08443260000001;-34.890648;VELOCIDAD
Indice: 1 - Valor: -56.1727631;-34.8601494;VELOCIDAD - Array: -56.1727631;-34.8601494;VELOCIDAD
Indice: 2 - Valor: -56.1537409;-34.8747532;VELOCIDAD - Array: -56.1537409;-34.8747532;VELOCIDAD
Indice: 3 - Valor: -56.1499214;-34.8560557;VELOCIDAD - Array: -56.1499214;-34.8560557;VELOCIDAD
Indice: 4 - Valor: -56.0450363;-34.8761087;VELOCIDAD - Array: -56.0450363;-34.8761087;VELOCIDAD
Indice: 5 - Valor: -56.12125400000001;-34.8869694;VELOCIDAD - Array: -56.12125400000001;-34.8869694;VELOCIDAD
Indice: 6 - Valor: -56.0626316;-34.8973888;VELOCIDAD - Array: -56.0626316;-34.8973888;VELOCIDAD
Indice: 7 - Valor: -56.177339;-34.9143394;VELOCIDAD - Array: 
Indice: 8 - Valor: -56.1802089;-34.9145901;LUZ_ROJA - Array: -56.1802089;-34.9145901;LUZ_ROJA
Indice: 9 - Valor: -56.1591107;-34.9228155;LUZ_ROJA - Array: 
Indice: 10 - Valor: -56.1444497;-34.88751510000001;LUZ_ROJA - Array: 
Indice: 11 - Valor: -56.0782099;-34.881108;LUZ_ROJA - Array: 
Indice: 12 - Valor: -56.1740828;-34.8698063;LUZ_ROJA - Array: 
Indice: 13 - Valor: -56.1602426;-34.889328;LUZ_ROJA - Array: 
Indice: 14 - Valor: -56.1429477;-34.8763023;LUZ_ROJA - Array: 
Indice: 15 - Valor: -56.1613369;-34.9027563;LUZ_ROJA - Array: 
Indice: 16 - Valor: -56.1246657;-34.8973888;LUZ_ROJA - Array: 
Indice: 17 - Valor: -56.1515951;-34.9112557;LUZ_ROJA - Array: -56.1515951;-34.9112557;LUZ_ROJA
Indice: 18 - Valor: -56.1879873;-34.9055367;LUZ_ROJA - Array: 
Indice: 19 - Valor: -56.1902404;-34.8712499;LUZ_ROJA - Array:

Hello,

And what is the result of this?

for (int i=0; i<=50; i++)
{
  Serial.print(i);
  Serial.println(lineas[i]);
}

Try use char arrays instead of Strings.

What are you trying to do exactly with those strings? Why do you need to store them in a giant array? Can't you process (extract values and do something with them) as soon as possible?

0-56.08443260000001;-34.890648;VELOCIDAD
1-56.1727631;-34.8601494;VELOCIDAD
2-56.1537409;-34.8747532;VELOCIDAD
3-56.1499214;-34.8560557;VELOCIDAD
4-56.0450363;-34.8761087;VELOCIDAD
5-56.12125400000001;-34.8869694;VELOCIDAD
6-56.0626316;-34.8973888;VELOCIDAD
7
8-56.1802089;-34.9145901;LUZ_ROJA
9
10
11
12
13
14
15
16
17-56.1515951;-34.9112557;LUZ_ROJA
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50

Thanks for your answer! That was the result.

How should it be done with char arrays? Sorry, i never did that.

Thanks a lot!

guix:
What are you trying to do exactly with those strings? Why do you need to store them in a giant array? Can't you process (extract values and do something with them) as soon as possible?

The idea is compare each GPS location with my actual GPS location provided by a GPS shield.
The list of pre-defined GPS locations is in a txt file inside SD card, and i want in the setup load each GPS location in an array, to compare in the loop my GPS location with each array register.
The next step is split the comma-separated string I'm getting each line, to load into the array that would be two-dimensional.

First step: Get rid of the String class. While a String object is easy to use, it's a crutch for programmers who don't want to spend the time learning the str*() and mem*() family of C function for char array processing. Check:

for details. You will save a considerable amount of memory by learning about these functions versus those in the String class.

Second, learn how to use the strtok() function. It is an extremely powerful function for breaking out substrings in char arrays that are separated by a set of delimiters (like a CSV file from Excel).

The idea is compare each GPS location with my actual GPS location provided by a GPS shield.

You realize, I hope, that getting an exact match, to 9 decimal places is extremely unlikely.

You need to convert the string information to degrees, minutes, and seconds, for latitude and longitude, for both the current location, and the list of locations, and see if you are close enough (for whatever definition of close suits you) to any of the locations.

Storing the degrees (int), minutes (int), and seconds (float) will take far less space than storing the strings.

Sorry, its my first arduino program, and i don't know very well C.
Can you do me a favor and write me how the code should be with char instead of string data type? Thanks a lot!

Can you do me a favor and write me how the code should be with char instead of string data type?

char record[80];
byte index;

void loop()
{
   while(myFile.available() > 0)
   {
       char c = myFile.read();
       if(c != '\n' && c != '\r')
       {
           record[index++] = c;
           record[index] = '\0';
       }
       else
       {
           // End of record found
           // Use the data in record

           index = 0;
           record[index] = '\0';
       }
   }
}

Your code didn't work, but i've modified it.

char record[80];
      char records[100][80];
      byte index = 0;
      byte index2 = 0;


      while(myFile.available() > 0)
       {
           char c = myFile.read();
           if(c != '\n')
           {
               record[index] = c;
               record[index+1] = '\0';
               index++;
           }
           else
           {
               // End of record found
               // Use the data in record
               index = 0;
               records[index2] = record;
               index2++;            
           }
       }

Now, the line

records[index2] = record;

is giving me an error. How can i assign all characters in the record to record array?

i've tried that, but i don't know if is ok

while(myFile.available() > 0)
       {
           char c = myFile.read();
           if(c != '\n')
           {
               records[index][index2] = c;
               records[index][index2 + 1] = '\0';
               index2++;
           }
           else
           {
               // End of record found
               // Use the data in record
               index2 = 0;
               index++;            
           }
       }
      char records[100][80];

Which Arduino has enough SRAM for an 8000 byte array?

How can i assign all characters in the record to record array?

strcpy().

jerearaujo03:
Sorry, its my first arduino program, and i don't know very well C.

Let me see if I understand this: The code Paul gave you "didn't work", but you're not going to tell us why. So, the guy with over 66 thousand posts and a bazillion karma points was wrong, but you, with all the experience gained in writing one program modified his code, but you're surprised that your modification didn't work. Do I have this right?

PaulS:

char record[80];

byte index;

void loop()
{
  while(myFile.available() > 0)
  {
      char c = myFile.read();
      if(c != '\n' && c != '\r')
      {
          record[index++] = c;
          record[index] = '\0';
      }
      else
      {
          // End of record found
          // Use the data in record

index = 0;
          record[index] = '\0';
      }
  }
}

I've re-tried this, and it works!
But i cant copy record to records.

char records[50][50];
byte index2 = 0;

...

strcpy(records[index2],record);
index2++;

I created a index2 variable to handle the first position of the two-dimensional array.
I tried copy the actual record to records in the index2 position, but i get a looping output

initialization done.
-56.08443260000001;-34.890648;VELOCIDAD
-56.1727631;-34.8601494;VELOCIDAD
-56.1537409;-34.8747532;VELOCIDAD
-56.1499214;-34.8560557;VELOCIDAD
-56.0450363;-3initialization done.
-56.08443260000001;-34.890648;VELOCIDAD
-56.1727631;-34.8601494;VELOCIDAD
-56.1537409;-34.8747532;VELOCIDAD
-56.1499214;-34.8560557;VELOCIDAD
-56.0450363;-3initialization done.
-56.08443260000001;-34.890648;VELOCIDAD
-56.1727631;-34.8601494;VELOCIDAD
-56.1537409;-34.8747532;VELOCIDAD
-56.1499214;-34.8560557;VELOCIDAD
-56.0450363;-3initialization done.
-56.08443260000001;-34.890648;VELOCIDAD
-56.1727631;-34.8601494;VELOCIDAD
-56.1537409;-34.8747532;VELOCIDAD
-56.1499214;-34.8560557;VELOCIDAD
-56.0450363;-3initialization done.
-56.08443260000001;-34.890648;VELOCIDAD
-56.1727631;-34.8601494;VELOCIDAD
-56.1537409;-34.8747532;VELOCIDAD
-56.1499214;-34.8560557;VELOCIDAD
-56.0450363;-3initialization done.
-56.08443260000001;-34.890648;VELOCIDAD
-56.1727631;-34.8601494;VELOCIDAD
-56.1537409;-34.8747532;VELOCIDAD
-56.1499214;-34.8560557;VELOCIDAD

but, all this code is in the setup function.

How can i do to assign each record (in the else) to a new position in the records array?

char records[50][50];

Grab your calculator. How many bytes of storage does this array need?

How many bytes of memory does your Arduino have?

What happens when you use more memory than you have?

Can progmem help me? How can I do?

Don't try to read all your records in one go.

Read one record from SD and compare. If match, stop. Else read next record and compare. If match, stop. Else ... till end of file.

Now this can get slow if there are a lot of records and if the matching record in the file is near the end or there is no matching record at all. There are some tricks that can be applied; but that will be a later exercise.

-56.08443260000001;-34.890648;VELOCIDAD

This makes it quite clear why anonymous printing sucks. There is no way to tell what this mess means.

But, it seems that the values MIGHT be lat and lon. As shown, the textual representation of lat and lon takes 29 bytes. As two doubles, they would take 8 bytes. You can do the math to see what the reduction in storage space requirements.

Finally i did it!
Do you think my code is well done?

Thanks all of you for helping me!

void leer_radares()
{
    // open the file for reading:
     myFile = SD.open("radares.txt", FILE_READ);

      char record[25];
      char records[20][3][12];   //[radar][0-lat;1-long;2-tipo][value]
          //tipos: 1-velocidad 2-luz roja
      byte index = 0;
      byte index2 = 0;

      if (myFile)
      {
          while(myFile.available() > 0)
           {
               char c = myFile.read();
               if(c != '\n' && c != '\r')
               {
                   record[index++] = c;
                   //record[index] = '\0';
               }
               else
               {
                   // End of record found
                   // Use the data in record


                   char *latitude, *longitude, *type;

                   latitude = strtok(record, ";");
                   longitude = strtok(NULL, ";");
                   type = strtok(NULL, ";");

                   
                   
                   strcpy(records[index2][0],latitude);
                   strcpy(records[index2][1],longitude);
                   strcpy(records[index2][2],type);
                   index2++;
                   index = 0;
                   
               }
           }

           
          // close the file:
          myFile.close();


           for(int i=0;i<index2;i++)
           {
                Serial.println(i);
                Serial.print("Latitude: ");
                Serial.print(records[i][0]);
                Serial.println();
                Serial.print("Longitude: ");
                Serial.print(records[i][1]);
                Serial.println();
                Serial.print("Type: ");
                Serial.print(records[i][2]);
                Serial.println();
                Serial.println();
            }
            
      }

      else
      {
          // if the file didn't open, print an error:
          Serial.println("error opening radares");
      }  
}

We have great moderators here!

Do you think my code is well done?

No.