I am reading data from an SD card for an STM32 embedded application. This data is written in a text file.
char resultFormat[100] = "%s\n%s\n%s\n%lf\n%lf\n%lf\n%i\n%i\n%i\n";
void readResult(int indexNumber)
{
FRESULT fr;
FIL MyFile; /* File object */
size_t read;
UINT bytesRead;
FATFS SDFatFs; /* File system object for SD disk logical drive */
fr = f_mount(&SDFatFs, (TCHAR const *)SDPath, 0); //Mounts the file
char fileName[20];
char directory[10] = "RESULTS";
sprintf(fileName, "%s/%i.TXT", directory, indexNumber);
fr = f_open(&MyFile, fileName, FA_READ); //Opens the file
read = f_read(&MyFile, resultBuffer, sizeof resultBuffer, &bytesRead); //Writes the txt from the txt file to a string.
vTaskDelay(200);
f_close(&MyFile); //Closes the file
sscanf(resultBuffer, resultFormat, resultDate, resultTime, presetName,
&correctedFlash, &observedFlash, &pressure, &flashedStatus,
&resultStartTemp, &status);
sendResultInfo(); //Processes the variables. Not relevant.
fr = f_mount(NULL, "", 0); //Unmounts the file.
}
My main question is this:
char resultFormat[100] = "%s\n%s\n%s\n%lf\n%lf\n%lf\n%i\n%i\n%i\n";
sscanf(resultBuffer, resultFormat, resultDate, resultTime, presetName,
&correctedFlash, &observedFlash, &pressure, &flashedStatus,
&resultStartTemp, &status);
I have quite a few variables that need to be read from the string, and if I change anything, I'll also have to change the resultFormat
which can lead to bugs.
Right now, the number of variables is manageable, but I was wondering how such data should be read if I have more data to be read from the text file, like if I had 100 variables of different types to be read. sscanf
seems a bit too prone to human error for reliable use in such cases, and I was wondering if there are alternatives to reading data from a string. A previous question provided here offers a solution to long sscanf
reads, but I am wondering whether there's another solution.
My secondary question (unsure if appropriate for this stack, but I get the impression that it would be brought up) is storing this data without using a text file, and not storing it as a string.
Not much of the data I have is a string, some of them are ints and doubles but are stored as a string.
While my current system works (and is good for debugging since I can easily read the data stored, from outside), I was wondering how the non-string data should be formatted and stored in the SD card.
Please let me know if more information or elaboration is required.
\n
is almost never needed in a scanf
format. If you get rid of those you will get a string that is easier to read.scanf
and friends with a format string that is not a string literal. Compiler writers invested a lot of work in catching format errors, but you are throwing it all away by making the actual format string invisible at the call site.A call like
sscanf(resultBuffer,
"%s" "%s" "%s" "%lf" "%lf" "%lf" "%i" "%i" "%i",
resultDate, resultTime, presetName, &correctedFlash, &observedFlash, &pressure, &flashedStatus, &resultStartTemp, &status);
is almost maintainable. You will get compiler warnings if your mess up the format string so that it no longer corresponds to the actual arguments. You know which part of the format corresponds to which variable by just looking at it. The only problem with it is that it is too long and you cannot split it in several lines without losing visual alignment. If you encounter this problem, split buffer the call into several smaller ones, or move away from scanf
completely.