Include variable value in other variable name, with for loop

Hi all,

I basically need to create Y charr arrays named char_1 to char_Y and containing filenames depending on other variables (the latter being irrelevant). These char arrays will be used to open the respective filenames in order to write on them.

My initial (ridiculous) solution was repeating the code Y times. So it would look like something like this, with Y=4: (incomplete code)

//within loop function

       char filename_1[30];                       
       char filename_2[30]; 
       char filename_3[30]; 
       char filename_4[30]; 
       sprintf (filename_1, "S%02iC01.CSV", NN);
       sprintf (filename_2, "S%02iC02.CSV", NN);
       sprintf (filename_3, "S%02iC03.CSV", NN);
       sprintf (filename_4, "S%02iC04.CSV", NN);
       char completefilename_1[40];
       char completefilename_2[40];
       char completefilename_3[40];
       char completefilename_4[40];
       sprintf (completefilename_1, "%s/%s", foldername,filename_1);
       sprintf (completefilename_2, "%s/%s", foldername,filename_2);
       sprintf (completefilename_3, "%s/%s", foldername,filename_3;
       sprintf (completefilename_4, "%s/%s", foldername,filename_4);

       if (! SD.exists(completefilename_1)) {                 
           logfile = SD.open(completefilename_1, FILE_WRITE); 
       //.....
       //and doing some other stuff before closing the file. 
       //...
       if (! SD.exists(completefilename_2)) {                  
           logfile = SD.open(completefilename_2, FILE_WRITE); 
       //.....
       //and doing some other stuff before closing the file.
       //...

       //etc, also with files 3 and 4.

Now I would like to create a for loop from 1 to Y (4 in this example), in which the variable names are create, and in which these variables are called. So basically I need to include a variable in the variable name when creating it and when calling it. Is this possible? I did some research and it seems that an array is also possible (or maybe the only solution) for this purpose. Is this correct? So the char array should have 2 dimensions, one of them having size Y and the other size 30 (char length)? Something like filename[Y,30]? And then I could create it and call it more easily with a for function?

Thanks for clarifying this to me! Cheers

What you are describing is an array of arrays, otherwise known as a 2D array.

It is not obvious why one file name array, with changing contents is not sufficient. You do not have all that much memory to store data in.

FILE *filePointers[N];

for (int i=1; i<N; i++)
{
    char filename[32];
    sprintf (filename, "MyFile%02d.CSV", i);
    filePointers[i-1] = fopen(filename, "r");
    // do whatever here
    fclose(fp);
}

Regards,
Ray L.

Thank you.
So from what I understand, this stores the content of the file “filename” in a stream which can be accessed and controlled through the FILE object. So, if i want to do operations on the file itself (such as printing on it), how do I do this? something like “filePointers[i-1].print”? If I weren’t using the FILE object I would do something like logfile.print if I declared file logfile before.

Nongsai: Thank you. So from what I understand, this stores the content of the file "filename" in a stream which can be accessed and controlled through the FILE object. So, if i want to do operations on the file itself (such as printing on it), how do I do this? something like "filePointers[i-1].print"? If I weren't using the FILE object I would do something like logfile.print if I declared file logfile before.

The big trick there is using sprintf() to construct each file name using the index i.

Yes but if I want to write on the file i want to call the variable which represents the file (sorry for the unprecise terms), the filename itself is irrelevant, it just helps me to identify it in my SDcard later on. So my question is: how do I manipulate the file such as I would do it if I had written

File logfile;
char filename[30]; 
sprintf (filename, "File%02d.CSV", i);
logfile = SD.open(filename, FILE_WRITE);
logfile.print("Whatever");
logfile.close();

Would it be something like this? (My question refers to the line filePointers.print)

FILE *filePointers[N];

for (int i=1; i<N; i++)
{
    char filename[32];
    sprintf (filename, "MyFile%02d.CSV", i);
    filePointers[i-1] = fopen(filename, "r");
    filePointers[i-1].print("Whatever");
    fclose(filePointers[i-1]);
}

Arduino SD library uses DOS files.

FILE *filePointers[N];

FILE is a Class Object initialized by the SD open() command that you access the file with. filePointers (above) is the name given to an array of FILE objects, each can point to a file. N is the number of FILE objects to allocate. Which one accessed is the index, i-1 below;

filePointers[i-1] = fopen(filename, "r"); filePointers[i-1].print("Whatever"); fclose(filePointers[i-1]);

The FILE object gets the file name and mode from a successful open(). Be aware that FILE objects are not just a few bytes large, Arduino has limited RAM.

https://www.arduino.cc/en/Reference/SD

Hi all,

I'm wondering why I can't use

filePointers[i-1] = SD.open(filename, FILE_WRITE); filePointers[i-1].close();

Instead of

filePointers[i-1] = fopen(filename, "r"); fclose(filePointers[i-1]);

What is the difference?

Also, can I use function such as SD.exists(filePointers[i-1])?

I don't see fopen() or fclose() anywhere in Arduino or AVR-LibC.

The difference is ... try to compile using fopen() vs SD.open().

SD is a class and unless you write your own SD code or find alternates, that class is what you use.

filePointers[i-1] = SD.open(filename, FILE_WRITE);

if ( ! filePointers[i-1] ) { // error code goes here, the file did not open properly, the pointer is NULL }

filePointers[i-1].close();

BTW, the name SD there can be whatever you name your SD object.

Ok so that's what I used before. I didn't know either about fopen of fclose, it was suggested by @RayLivingston in post 3 and repeated by @GoForSmoke in post 7. I will thus use the SD library which I know how to use, and use "filePointer[i-1]" as if it were "logfile". Thanks!

BTW, what is the difference between FILE and file? I would have written the array as such:

file fileArray[N];

and I guess I could also have used char filename[N][32] for the filenames in the loop, right? Is the purpose for not doing so the savings in memory by overwriting the variable "filename" in every loop?

I’m wrong about one thing, AVR-LibC (Arduino uses) does have FILE defined as well as fopen(), etc.
I had to dig dig dig to find it. It is used by the Stream class and others but… SD still uses it own open(). etc, derived from Stream class

AVR=LibC stdio.h doc:
AVR=LibC stdio.h doc:

Typedef Documentation
typedef struct __file FILE

FILE is the opaque structure that is passed around between the various standard IO functions.

I guess that Opaque there means don’t mess with it.

Hi again,

So I’ve tried to use the SD library with the FILE pointer array. Something’s wrong, and probably that’s why @RayLivingston suggested to use fopen and fclose. I get these error messages:

  • for calling filePointers[thisCell].print(“Whatever”): “request for member ‘print’ in ‘filePointers[thisCell]’, which is of pointer type ‘FILE* {aka __file*}’ (maybe you meant to use ‘->’ ?)

  • for calling filePointers[thisCell] = SD.open(completefilename_cell, “r”): “cannot convert ‘SDLib::File’ to ‘FILE* {aka __file*}’ in assignment”

Since I didn’t solve these problems yet, I didn’t see the error message for calling filePointers[thisCell] = .close() yet.

So, again, could I simply use file fileArray[N] instead of FILE filePointers[N] and why wasn’t this suggested in the first place? If not, how can I manipulate the files (I mean, SD.open would be replaced by fopen(), .close() by fclose(), but what about other commands such as print?)

Thank you!

Maybe because it’s been changed (kicks the car door).

Look in your IDE under File->Examples->SD for ReadWrite to see what your IDE uses, mine has

File myFile;

instead of the FILE the site doc has.

/*
  SD card read/write

 This example shows how to read and write data to and from an SD card file
 The circuit:
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11
 ** MISO - pin 12
 ** CLK - pin 13
 ** CS - pin 4

 created   Nov 2010
 by David A. Mellis
 modified 9 Apr 2012
 by Tom Igoe

 This example code is in the public domain.

 */

#include <SPI.h>
#include <SD.h>

File myFile;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }


  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  myFile = SD.open("test.txt", FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    Serial.print("Writing to test.txt...");
    myFile.println("testing 1, 2, 3.");
    // close the file:
    myFile.close();
    Serial.println("done.");
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }

  // re-open the file for reading:
  myFile = SD.open("test.txt");
  if (myFile) {
    Serial.println("test.txt:");

    // read from the file until there's nothing else in it:
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    // close the file:
    myFile.close();
  } else {
    // if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
}

void loop() {
  // nothing happens after setup
}

… sometimes the IDE gets worth closer to the price (nothing) than other times.

OK - I got back to my original File object, and simply created an array of File objects: File fileArry[N]. No pointers involved. Seems easier to me - but maybe I didn't really get the purpose of using pointers - as suggested by @RayLivingston.

Anyway this works fine! Thanks!

The spelling changed from FILE to File.

The name fileArry is a pointer to type File data objects. The index you use is an expression of pointer + index that users of other computer languages are familiar with, brackets. One is better for absolute address work and the other for relative address work but you can do both with either and do start pointers on known addresses.