Array pointers

I've written a library that will fetch setting from SD card. This is the library.

The CONFIG.TXT:

$SSID1=TESTAP1;
$KEY1=TESTAPKEY;

Configfile.h

#ifndef Configfile_h
#define Configfile_h

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

class Configfile
{
public:
	bool readConfigFile(char* filename);
	char* getValue(char* settingName);
private:
	File _cfgFile;
	uint8_t _filePosition;
	uint8_t _workingIndex = 0;
	uint8_t _settingNameValuePositions[16][3];
	uint8_t _temporaryBufferPosition = 0;
	char _temporaryBuffer[32];
	char* _filename;
	void setPosition(uint8_t mrk);
	uint8_t getPosition(uint8_t idx, uint8_t mrk);
	void addToBuffer(char inp);
	void resetBuffer();
	char* requestSetting(char *settingName);
};

#endif

Configfile.cpp

#include "Arduino.h"
#include <SPI.h>
#include <SD.h>
#include "Configfile.h"

File _cfgFile;
uint8_t _filePosition;
uint8_t _workingIndex = 0;
uint8_t _settingNameValuePositions[16][3];
uint8_t _temporaryBufferPosition = 0;
char _temporaryBuffer[32];
char* _filename;

bool Configfile::readConfigFile(char* filename)
{
	_filename = filename;
	if (!SD.begin()) {
		return false;
	}
	else {
		_cfgFile = SD.open(_filename);
		if (!_cfgFile) {
			return false;
		}
		else {
			while (_cfgFile.available()) {
				char fileChar = _cfgFile.read();
				_filePosition = _cfgFile.position();
				switch (fileChar) {
				case '

And the test sketch and question here:

#include <Configfile.h>
Configfile configfile;

char* ssid1;
char* key1;

void setup()
{
	Serial.begin(9600);
	//GET WIFI CONFIGURATION
	configfile.readConfigFile("CONFIG.TXT");
	ssid1 = configfile.getValue("SSID1");
	key1 = configfile.getValue("KEY1");
	Serial.println(ssid1); //This will print TESTAPKEY.  Why is that? It must print TESTAP1
	Serial.println(key1); //This will print TESTAPKEY.
        Serial.println(configfile.getValue("SSID1")); //This will print the correct one: TESTAP1
        Serial.println(configfile.getValue("KEY1")); //This will print TESTAPKEY
}

void loop()
{

}

Please let me know if I did something wrong with my library.

Thank you,:
setPosition(0);
break;
case '=':
setPosition(1);
break;
case ';':
setPosition(2);
_workingIndex++;
}
}
return true;
}
}
}
char* Configfile::getValue(char *settingName) {
for (int i = 0; i < _workingIndex; i++) {
uint8_t nS = getPosition(i, 0);
uint8_t eQ = getPosition(i, 1);
uint8_t vE = getPosition(i, 2);
bool isFound = false;
resetBuffer();
if (isFound == false) {
for (int g = nS; g < eQ - 1; g++) {
_cfgFile.seek(g);
addToBuffer(_cfgFile.read());
}
if (strcmp(_temporaryBuffer, settingName) == 0) {
isFound = true;
resetBuffer();
}
}
for (int g = eQ; g < vE - 1; g++) {
_cfgFile.seek(g);
addToBuffer(_cfgFile.read());
}
if (isFound) {
Serial.print("From getvalue func: ");
Serial.println(_temporaryBuffer);
return _temporaryBuffer;
}
}
return "0";
}
void Configfile::setPosition(uint8_t mrk) {
_settingNameValuePositions[_workingIndex][mrk] = _filePosition;
}

uint8_t Configfile::getPosition(uint8_t idx, uint8_t mrk) {
return _settingNameValuePositions[idx][mrk];
}

void Configfile::addToBuffer(char inp) {
_temporaryBuffer[_temporaryBufferPosition] = inp;
_temporaryBufferPosition++;
}

void Configfile::resetBuffer() {
_temporaryBufferPosition = 0;
memset(_temporaryBuffer, 0, sizeof(_temporaryBuffer));
}


**And the test sketch and question here:**

§DISCOURSE_HOISTED_CODE_3§


Please let me know if I did something wrong with my library.

Thank you,

Depending on the use case, there might be a bug. Your "getValue" function returns a pointer to _temporaryBuffer and not the contents of the buffer. Subsequent calls to "getValue" will modify _temporaryBuffer and all pointers which point to _temporaryBuffer will then point to the last value retreived with "getValue". A pointer is the address of a value and not a value.

If you read values one by one, this may be a feature. If you want to read out multiple values, then it is a bug :slight_smile:

int a = 1;
int b = 2;

int *ptr = &a;

//*ptr == 1

a = b;

//*ptr == 2

Not quite.sure if return "0"; will work reliably. You return a pointer to a string that goes out of scope at the moment that the function ends. Returning NULL might be a better option.

Danois90:
Depending on the use case, there might be a bug. Your "getValue" function returns a pointer to _temporaryBuffer and not the contents of the buffer. Subsequent calls to "getValue" will modify _temporaryBuffer and all pointers which point to _temporaryBuffer will then point to the last value retreived with "getValue". A pointer is the address of a value and not a value.

If you read values one by one, this may be a feature. If you want to read out multiple values, then it is a bug :slight_smile:

int a = 1;

int b = 2;

int *ptr = &a;

//*ptr == 1

a = b;

//*ptr == 2

What would be the best solution?

   if (isFound == false) {
      for (int g = nS; g < eQ - 1; g++) {
        _cfgFile.seek(g);
        addToBuffer(_cfgFile.read());
      }
      if (strcmp(_temporaryBuffer, settingName) == 0) {
        isFound = true;
        resetBuffer();
        /////  SHOULDN'T THE LOOP BELOW BE UP HERE INSTEAD?
      }
    }
    ///// SHOULDN'T THIS LOOP BE UP WHERE "isFound" IS SET TO true?
    for (int g = eQ; g < vE - 1; g++) {
      _cfgFile.seek(g);
      addToBuffer(_cfgFile.read());
    }

The best sollution depends of what you want. If you want to store multiple values in memory, then you may want to change your getValue to something like this:

byte getValue(char *name, char *buf, byte buflen) {
  //Here you find the config value named "name" and copy
  //value of it into "buf", minding that the buffer will
  //only hold "buflen" chars - including null termination

  //return value should be the number of chars retreived
  //or 0 if none / error
}

Now you can read out multiple values like so:

char value1[10];
char value2[10];

if (getValue("hello", value1, 10) == 0) {
  //Handle error
}

if (getValue("world", value2, 10) == 0) {
  //Handle error
}

johnwasser:

   if (isFound == false) {

for (int g = nS; g < eQ - 1; g++) {
        _cfgFile.seek(g);
        addToBuffer(_cfgFile.read());
      }
      if (strcmp(_temporaryBuffer, settingName) == 0) {
        isFound = true;
        resetBuffer();
        /////  SHOULDN'T THE LOOP BELOW BE UP HERE INSTEAD?
      }
    }
    ///// SHOULDN'T THIS LOOP BE UP WHERE "isFound" IS SET TO true?
    for (int g = eQ; g < vE - 1; g++) {
      _cfgFile.seek(g);
      addToBuffer(_cfgFile.read());
    }

Oh.. right, I don't need that if statement since I already found the value at strcmp

Danois90:
The best sollution depends of what you want. If you want to store multiple values in memory, then you may want to change your getValue to something like this:

byte getValue(char *name, char *buf, byte buflen) {

//Here you find the config value named "name" and copy
  //value of it into "buf", minding that the buffer will
  //only hold "buflen" chars - including null termination

//return value should be the number of chars retreived
  //or 0 if none / error
}




Now you can read out multiple values like so:



char value1[10];
char value2[10];

if (getValue("hello", value1, 10) == 0) {
  //Handle error
}

if (getValue("world", value2, 10) == 0) {
  //Handle error
}

Great!, I'll add this as separate function.
And perhaps memcpy would do the trick.
Thank you,