I read from a text file consisting of 24 lines from a SD card. Characters are read one by one into a char string. If a line feed is detected the char string is finished and should be added to line i of char array position i. I use a for loop to file the char array. However as I empty the line i afterwards char array position i looses it's contens. I don't understand why.
#include <SD.h>
#include <PString.h>
const int chipSelect = 10;
File dataFile;
char x;
char line[60]; // char string of 60 characters
char* myLines[24]; // char array of 24 char strings
int i = 0;
PString myPstring(line, sizeof(line));
void setup(){
Serial.begin(9600);
pinMode(10, OUTPUT);
SD.begin(chipSelect);
dataFile = SD.open("SAVONDS.TXT");
if (dataFile) { // if text file is found
while (dataFile.available()) {
x = dataFile.read(); // read next char 'x' from SD card
if (x != 10){
myPstring.print(x);} //add 'x' to line
else{ //if line feed detected line is complete
myLines[i] = line; // char array i = line
Serial.println(myLines[i]); // this prints line i correctly
myPstring = "";
Serial.println(myLines[i]); // prints only a line feed
i++;}}
dataFile.close();
for(int n=0; n<24; n++){
Serial.println(myLines[n]); // prints only a series of line feeds
delay(200);
} } }
void loop(){}
I also tried this using the String function (line = line + x) to no avail.
I also tried String* myLines[24] instead of char* myLines[24] to no avail.
Definining a char array with pre defined strings is easy, but building a char array out of strings using a for loop eludes me. Please help!
you are always using the first address of line every time you run the cycle. If you want to do it this way, you'd need to do something like:
myLines[i] = &line[y]; //y is the index at which you found the carriage return
Sadly, from what I found on the internet, you can't get that index from PString (I may be wrong). So I guess you'll either use a heavier class, or use a char array with an index.
You haven't allocated any memory to put the lines in. Your array myLines is an array of pointers, and each execution of this:
myLines[i] = line
sets one of those pointers to point to line. Line is just a single array and in the end, all of your pointers point to it, so all of them will give the same result when printed, i.e. they will all point to line, which will contain the last thing you read from the file. If you want to store this data, you need to predefine some space to put it in or use malloc to allocate it on the fly. Be careful though - Arduino has very little RAM and on most of them, 1440 bytes will consume much of it.
You want to make a copy of what is in the line array, and store the pointer to that copy in your myLines array. The easiest way to do that is to use the strdup() function.
Thanks for responding. The text file on the SD card contains a list of artists and albums. One line for each album. If the lines could be turned into a array of strings I could read the lines to a LCD-shield. Using "up" and "down" buttons selecting the next array member I could find and select an album and use it to start this album on iTunes. This would work as media player.
At this point I am able to read the lines one by one. I don't know how to build the array of strings by reading from the SD card. I will look into Malloc. But I would prefer a ledd complicated solution.
Maybe I should not try to read it all into memory in setup fase and select from memory during loop fase. Maybe I should read and select directly from the SD card in the loop.
You've got the data in one array, in pre-allocated memory. You could use strlen() to determine how much space to allocate, then use malloc() to allocate that space, then use strcpy() to copy the existing array to the space pointed to by the pointer returned by mallow.