I've been working on a mp3 player and have been trying to index the files on the micro sd card. I have pretty much got everything working except printing the name of each folder at folderIndex[0][folderNum]. The correct value is printed directly after it is declared, but when I move to the next folder it is no longer able to print. All of the file names print, just not the folder name. I believe they print when the value is folderIndex[1][folderNum], but I would rather use 0 to maintain readability. I'm using a Waveshare pi2040 zero.
CODE:
// sd card pins
const int _MISO = 0; // AKA SPI RX
const int _MOSI = 3; // AKA SPI TX
const int _CS = 1;
const int _SCK = 2;
#include <SPI.h>
#include <SD.h>
int fileNum = 1;
const int folderLim = 31;
int externalFolderNum;
char* folderIndex[/*file names*/][/*folder number*/folderLim] = {};
int folderIndexSize[/*how many files*/] = {0};
bool sdInitialized = false;
File root;
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(1); // wait for serial port to connect
}
Serial.println();
Serial.println("PROGRAM IS STARTING/////////////////////////////////////////");
// setting up sd card reader
SPI.setRX(_MISO);
SPI.setTX(_MOSI);
SPI.setSCK(_SCK);
sdInitialized = SD.begin(_CS);
if (sdInitialized) {
Serial.println("SD card installed and working");
root = SD.open("/");
} else {
Serial.println("SD card not installed or wired incorrectly");
}
indexFiles(root, 0);
Serial.println();
Serial.print("Folder 1 = "); Serial.println(folderIndex[0][1]);
Serial.print("Folder 2 = "); Serial.println(folderIndex[0][2]);
// for (int folders = 0; folders <= (externalFolderNum); folders++)
// {
// for (int files = 0; files <= (folderIndexSize[folders]); files++)
// {
// Serial.println(strdup(folderIndex[files][folders]));
// }
// }
}
void loop() {
}
void indexFiles(File directory, int folderNum)
{
char* tempFileName;
char* tempFolderName;
while (true)
{
File currentFile = directory.openNextFile(); //moves to the next file from the starting directory
if (!currentFile) // if there are no more files, break
{
break;
}
if (currentFile.isDirectory()) //checks if the selected file is a directory
{
if (String(currentFile.name()) != "System Volume Information") //ignores stupid windows files
{
folderNum++;
folderIndex[0][folderNum] = strdup(currentFile.name()); /*sets first entry of new column to folder name */
fileNum = 1;
Serial.print("folderNum = " + String(folderNum) + "\t/" ); Serial.println(currentFile.name());
// Serial.println(folderIndex[0][1]);
indexFiles(currentFile, folderNum); //runs method again with directory at the current file
}
}
else
{
if (folderNum != 0)
{
folderIndexSize[folderNum] = fileNum;
externalFolderNum = fileNum;
Serial.print("fileNum = " + String(fileNum) + "\t\t" ); Serial.println(currentFile.name());
folderIndex[fileNum][folderNum] = strdup(currentFile.name());
fileNum++;
}
}
currentFile.close();
}
}
OUTPUT:
PROGRAM IS STARTING/////////////////////////////////////////
SD card installed and working
folderNum = 1 /SOUNDTRACK
fileNum = 1 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 01 Overworld Day.mp3
fileNum = 2 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 02 Eerie.mp3
fileNum = 3 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 03 Overworld Night.mp3
fileNum = 4 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 04 Title Screen.mp3
fileNum = 5 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 05 Underground.mp3
fileNum = 6 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 06 Boss 1.mp3
fileNum = 7 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 07 Jungle.mp3
fileNum = 8 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 08 Corruption.mp3
fileNum = 9 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 09 Underground Corruption.mp3
fileNum = 10 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 10 The Hallow.mp3
fileNum = 11 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 11 Boss 2.mp3
fileNum = 12 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 12 Underground Hallow.mp3
fileNum = 13 Scott Lloyd Shelly - Terraria Soundtrack Volume 1 - 13 Boss 3.mp3
folderNum = 2 /folder 2
fileNum = 1 text tuah.txt
fileNum = 2 01 - Once Upon a Time.mp3
Folder 1 =
Folder 2 = �
Your definition below describes a zero-length array.
It's no surprise that you can't put anything into such an array or read anything from it.
No, the zero index isn't anything special. The problem stems from how you declared the array—with such a declaration, accessing any index would be an error.
What is the mistake? In C/С++, the array size can be specified in two ways. The first is to explicitly specify the size, using a number in square brackets:
int arr[4]; // an array with four elements
The second is to leave the brackets empty and specify the number of elements to initialize:
int arr[] = {1,2,3,4}; // also an array with four elements
Leaving both brackets empty means the array has zero size, and the compiler will simply ignore this definition.
int arr[] = {}; // zero-length array
For a two-dimensional array, things are a little more complicated, but the result is the same: the memory allocated for storing elements of zero-row array is zero. This means that when writing to such an array in any row, you're writing beyond the bounds.
I've just done a deep dive on why you can even define an array what allocates no storage and is at a glance sorta essentially useless.
I am not competent to report on this here, but if you are curious, looking into it is satisfying.
This compiles (C) : "int arr[] = {};", but allocates no storage. Why would this not be an error? How could the identifier arr even be used in the code it is so defined in?
Well that's the thing, I can assign values and print them. The only value I cannot print is folderIndex[0][x]. I can print every other value I assigned that is greater than zero
Your data are probably written to memory in a place that is not reserved for your variable....
Next time you read it, it may still be there or it may be overwritten by something else...
Writing outside reserved area may overwrite data reserved for other varables...
This may cause crashes and unpredictable results...
So: never do this!
Probably luck. Swap a sequence around and the behaviour might be different. Add something else to or remove something from the code and the behaviour might be different.
This is a quick demo what is were in memory.
#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
const int folderLim = 31;
char* folderIndex[/*file names*/][/*folder number*/ folderLim] = {};
int folderIndexSize[/*how many files*/] = { 0 };
void setup()
{
char buffer[64];
Serial.begin(115200);
Serial.print("folderIndex has ");
Serial.print(NUMELEMENTS(folderIndex));
Serial.println(" element(s)");
sprintf(buffer, " address of folderIndex[0] = %p", folderIndex);
Serial.println(buffer);
sprintf(buffer, " address of folderIndex[1] = %p", &folderIndex[1]);
Serial.println(buffer);
Serial.print("folderIndexSize has ");
Serial.print(NUMELEMENTS(folderIndexSize));
Serial.println(" element(s)");
sprintf(buffer, " address of folderIndexSize[0] = %p", folderIndexSize);
Serial.println(buffer);
sprintf(buffer, " address of folderIndexSize[1] = %p", &folderIndexSize[1]);
Serial.println(buffer);
}
void loop()
{
// put your main code here, to run repeatedly:
}
The output for an AVR processor is
```text
folderIndex has 0 element(s)
address of folderIndex[0] = 0x1d6
address of folderIndex[1] = 0x214
folderIndexSize has 1 element(s)
address of folderIndexSize[0] = 0x1d4
address of folderIndexSize[1] = 0x1d6
For your processor it will be different.
folderIndexSize[folderNum] = fileNum; where folderNum equals 1 overwrites whatever was in folderIndex[0]; folderIndex has no elements so I can't tell you what exactly will be overwritten. If it had one element you would have overwritten the first element (index 0).