Failure to recognise an empty String within an if/else if statement

goalJJB

Member
Hello,

I have two key functions: one to select and open a folder within an SDcard one to select play an audio file.

I have both of these within:

Code:
void loop() {

  buttonInit();
  updateIO();
  displayInit();

  

  if(directoryPath == "") // -> How can I get it say that this is false?
  {
    getFolder();
  }
  
  else if(filePath == "") // *= folderNames[4]* OR give it directoryPath == "Drums"? 
  {
    getFile();
  }

  else
  {
    homeScreen();
  } 
  
}

My aim is that once the directoryPath has been found, it should proceed to grab the filePath which can then be assigned to a pad. However, it always believes that no directory has been found and so never moves onto the else if statement. My specific question is, why does it always fail to see that a directoryPath has been found?

(Here is the whole of the code)

Code:
#include <SD.h>
#include <SPI.h>
#include <Bounce2.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Audio.h>
#include <string>

#include "displayFunctions.h"

Adafruit_SSD1306 display(128, 64, &Wire, -1);

#define MOSI_PIN 11
#define SCK_PIN 13
#define CS_PIN = BUILTIN_SDCARD


void homeScreen();
void printDirectory(File dir, int numTabs);
void buttonInit();
void updateIO();
bool checkWav(String wav);

#define maxNumCharDisplay 80

int led = 28;

const char *folderNames[] = { "Drums", "Vocals", "Pads", "Misc" };

Bounce selectButton = Bounce(36, 10);
Bounce returnButton = Bounce(37, 10);


const byte pins[] = {28, 29, 30, 31, 32, 33, 34, 35};
const byte numOfPads = sizeof(pins);
Bounce padPad[numOfPads];

File root;
File currentDirectory;
File entry;

String dirArray;
String directoryPath;// = "/Presets/";
String filePath;  //-> copy this into ch array ?

bool selectedFolder;

int folderChoice;
int fileChoice;
int numTabs;

char presetFolderName[] = "/Presets/";
String fileExtension = ".wav";


int assignedPad = -1;

AudioPlaySdWav playWav;

void setup() {
  
  buttonInit();
  updateIO();
  displayInit();

  Serial.begin(9600);


 
  SPI.setMOSI(MOSI_PIN);
  SPI.setSCK(SCK_PIN);

  if (!(SD.begin(BUILTIN_SDCARD))) {
    while (1) {
      Serial.println("unable to access SD card.");
    }
  }

  homeScreen(); //  Display list of preset folders

  AudioMemory(8); //  buffer for how much memory to provide
  playWav.stop();

  
  
}


void loop() {

  buttonInit();
  updateIO();
  displayInit();

  
  //char presetFolderName[0];
  //sprintf(presetFolderName, '\0');

  //if(strlen(presetFolderName) > 0) // -> How can I get it say that this is false? -  && presetFolderName == '\0'
  if(directoryPath == "")
  {
    getFolder();
  }
  //else if(strlen(presetFolderName) < 0) // *= folderNames[4]* OR give it directoryPath == "Drums"?
  else if(filePath == "") 
  {
    getFile();
  }

  else
  {
    homeScreen();
  }


  
  
}

void getFolder()  //  this should return/input a String (folder name) -> Although, the folderNames are const chars? if a const char
{

  dirArray = directoryPath;
  //strcat(dirArray, PresetFolderName);         //  concatenate /Presets/ with directory path -> should this happen later?
  for (uint8_t i = 0; i < directoryPath.length(); i++)  //  for the whole length of the String
  { 
    //Serial.println("line 142"); 
    //Serial.println(dirArray[i]);                //   
  }
  
 
  if (directoryPath == "") {  //  if no directory has been selected 

    while (!selectButton.update()) {}

    if (selectButton.fallingEdge()) {
      //int folderChoice = readInt(1, 4); // -> do the same as^ by changing int into a ch Array

      //int folderChoice; //  keeps track of which folder has been selected -> should this be -1? -> could just say -1 here instead of further down
      char folderChoiceChar[maxNumCharDisplay + sizeof(char)];
      sprintf(folderChoiceChar, "%d", folderChoice);  //  But how do I get it to read from 1-4? -> for loop
      for (int i = 0; i < 3; i++) {
        folderChoice = folderChoiceChar[i];  //should the folderChoiceChar be tracked with an index? -> yes
      }

   
      dirArray = presetFolderName;
      
     
 
      dirArray += folderNames[folderChoice];

      File folder;
      folder = SD.open(dirArray.c_str());
           
     
      //folder = SD.open(directoryPath.c_str()); //  Does this open straight to ...^ "directoryPath = "/Presets + folderName;"

      
      if(folder.isDirectory()){  //  
       
    
        while (true) //Does this loop & print twice?
        {
          File entry = folder.openNextFile(); //  I think, because it's just 'openNextFile' whilst Drums is a directory -> it will keep looping on the drums directory until all files are printed. 
      

          if (!entry) 
          {
            break;
          }
          display.clearDisplay();
          display.setTextColor(SSD1306_WHITE);  // Draw white text
          display.setCursor(0, 0);
          
          Serial.println("---LOOP START---");
          display.println(folder.name()); //  this prints: e.g. "Drums" - How to print multiple??
          Serial.println(folder.name());
          display.setCursor(12, 0);
          display.println(":");          
          

         
          for(uint8_t i = 0; i < numTabs; i++)
          {
            
            display.println('\t');  //  This line should print vertically
            
          }
          display.println(entry.name());  //  And this prints the audio - but only 1 file - how can we print multiple?
          Serial.println(entry.name());

          if(entry.isDirectory()) //  This is if it is a folder not a file -> not necessary?
          {
            display.println("/");

          }
          else
          {
            Serial.println("");
          }
           
          entry.close();
          
          Serial.println("---LOOP END^--");

          break; // -> this work in only printing 1 audio file - now how multiple?

        }
        
        

        Serial.println(sizeof(directoryPath), DEC); //  prints the no. of bytes directoryPath takes up
        Serial.println(" bytes");
        
      }
      folder.close();
      display.display();
    
      
    }
     //WRITE OUT OF BOUNDS IF PRESETFOLDERNAME IS LONGER THAN 0 CHARS. - HOW?




   
  
  } 

 


}

void getFile()
{

  //char samplesArr[filePath.length() + 1];  //  change path from string to Char arry -> think the +1 is becuase of the NULL character at the end
  //strcpy(samplesArr, filePath.c_str());    //  copy String directoryPath into destination dirArray
  
  String samplesArr = filePath;
  
  
  for (uint8_t i = 0; i < filePath.length(); i++)  //  
  {                                                // 
   
  }

  if (filePath == "") //  if directory has been selected but no audio file, proceed. I think filePath has to be more defined before^
                            //  Currently just saying, if String filePath is nothing -> must make it so that filePath = charArray 
  {  

    while (!selectButton.update()) {}

    if (selectButton.fallingEdge() && checkWav(filePath)) //  -> AND if .wav?
    {


   
      char fileChoiceChar[maxNumCharDisplay + sizeof(char)];
      sprintf(fileChoiceChar, "%d", fileChoice);  //  But how do I get it to read from 1-4? -> for loop
      for (int i = 0; i < 3; i++) {
        fileChoice = fileChoiceChar[i];  //should the folderChoiceChar be tracked with an index? -> yes
      }

      samplesArr = dirArray; // -> ???

      samplesArr += dirArray[fileChoice];  //  -> what should I change folderNames to?

   
      

      display.clearDisplay();
      display.setCursor(0, 0);
      display.println("Assign to pad:");

      for (int i = 0; i < numOfPads; i++) {
        display.print(i + 1);
        display.print(". Pad ");
        display.print(i);
      }
      display.display();
    }
  } else if (assignedPad == -1) {                         // Definitley have to do some joining of assignedPad = filePath?
    for (int i = 0; i < numOfPads; i++) {
      if (padPad[i].update() && padPad[i].fallingEdge()) {
        assignedPad = -1;  // should this be -1?
        display.clearDisplay();
        display.setCursor(0, 0);
        display.print("Assigned to pad: ");
        display.println(assignedPad + 1);
        display.display();
      }
    }
  }

  else {
    for (int i = 0; i < numOfPads; i++) {
      if (padPad[i].update() && padPad[i].fallingEdge() && i == assignedPad) {
        playWav.play(filePath.c_str());
        break;
      }
    }
  }
 
  
}

void homeScreen()
{

  while (!returnButton.update()){}
  if(returnButton.fallingEdge())
  {
    
  
    display.clearDisplay();
    display.setCursor(0, 0);
    display.println("Select a directory:");
    for (int i = 0; i < 4; i++) {
      display.print(i + 1);
      display.print(". ");
      display.println(folderNames[i]);
    }
    display.display();
  }
}

void printDirectory(File dir, int numTabs) {

  while (true) {

    File entry =  dir.openNextFile();

    if (! entry) {

      // no more files

      break;

    }

    for (uint8_t i = 0; i < numTabs; i++) 
    {

      display.print('\t');

    }

    display.print(entry.name());

    if (entry.isDirectory()) 
    {

      display.println("/");

      printDirectory(entry, numTabs + 1);

    } else 
    {

    }
    entry.close();
  }
}

bool checkWav(String wav)
{
  if (wav.endsWith(fileExtension))
  {
    return true; // Return true if file ends with wav
  }
  else
  {
    return false; // Return false if file does not
  }
}

void displayInit() {
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
  display.clearDisplay();
  display.setTextSize(1);               // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);  // Draw white text
  display.setCursor(0, 0);
}

void buttonInit() {

  pinMode(36, INPUT_PULLUP);  // select button
  pinMode(37, INPUT_PULLUP);  // return button

  for(byte i = 0; i < numOfPads; i++)
  {
    padPad[i].attach(pins[i], INPUT_PULLUP);
    padPad[i].interval(5); //  debounce time    
  }


  pinMode(led, OUTPUT);
}

void updateIO()
{
  selectButton.update();
  returnButton.update();

  for(byte i = 0; i < numOfPads; i++)
  padPad[i].update();
   
}

I have tried stating (!(directoryPath == "")) as well as if directoryPath = one of the folderNames. as well as providing the void directoryPath(with a const char) to represent one of the folder names as this is what will be returned. I have also tried stating within void loop that if(strlen(presetFolderNames) > 0) { getFolder()}.
 
Cannot really see on my phone what string class you use, but stren is for char arrays that build a string. I’m am quite sure there are functions like empty() len() or size() on it.
 
Sorry, I don't use Strings so unclear to me best way to use them here.

But you might try something like:
if (directoryPath.length() == 0)

or != 0 for other case...

I did not see anywhere where the directoryPath was assigned a value.
 
Try "if (!*directoryPath)" or "if (directoryPath[0] == '\0')". But this won't really solve the bigger issue. Instead of testing for string completeness in the main loop(), instead, check for a raised flag that's been set elsewhere from where the string (path contents) originated.
 
New assigned value

Sorry, I don't use Strings so unclear to me best way to use them here.

But you might try something like:
if (directoryPath.length() == 0)

or != 0 for other case...

I did not see anywhere where the directoryPath was assigned a value.

Yes, I realised this after posting, I therefore updated it so that directoryPath = dirArray; at the end of the getFolder() function.

Thank you for your suggestion. I have tried a number of methods stating that `if (directoryPath.length() == 0)` & `if(directoryPath[0] == '\0')`. But neither seem to progress to the getFile() function which should then print "assign to pad".

Even after I put Serial.println(directoryPath); after the `directoryPath = dirArray;` which outputs /Presets/Drums. This is the correct output and so proves that all of the attempted if statements above should be false but still it doesn't proceed. I can't see where I have gone wrong later in code?

Thanks
 
Sorry hard to know what you have in there now.

In cases like this, I would put in some Serial.print(... like statements before each part like:
Code:
  Serial.println(directoryPath);
  Serial.println(directoryPath.length());
  Serial.println(filePath);
  ..
  if(directoryPath == "") // -> How can I get it say that this is false?
  {
    getFolder();
    Serial.println("getFolder Called");
  }
  
  else if(filePath == "") // *= folderNames[4]* OR give it directoryPath == "Drums"? 
  {
    getFile();
    Serial.println("getFile called");    
  }

  else
  {
    homeScreen();
    Serial.println("homeScreen called");
  } 
  
}

And see what the values are...

I don't know your needs here, but for example does filePath change if getFolder() is called if so you probably don't want the test under an else if....
 
Yes, when
if(directoryPath == "")
{
getFolder();
}

With the current code being:
Code:
void loop() {

  updateIO();
  displayInit();


  if(directoryPath.length() == 0) 
  {
    getFolder();
  }
  
  else
  {
    getFile();
  }
  

  while (!returnButton.update()){}
  if(returnButton.fallingEdge())
  {
    homeScreen();
  }
  
}

void getFolder()  //  this should return/input a String (folder name) -> Although, the folderNames are const chars? if a const char
{

  dirArray = directoryPath;
  

 
  for (uint8_t i = 0; i < directoryPath.length(); i++)  //  for the whole length of the String
  { 
    
  }


  if (directoryPath.length() == 0) {  //  if no directory has been selected 

    while (!selectButton.update()) {}

    if (selectButton.fallingEdge()) {
    
     
      char folderChoiceChar[maxNumCharDisplay + sizeof(char)];
      sprintf(folderChoiceChar, "%d", folderChoice);  //  But how do I get it to read from 1-4? -> for loop
      for (int i = 0; i < 3; i++) {
        folderChoice = folderChoiceChar[i];  //should the folderChoiceChar be tracked with an index? -> yes
      }

    
      dirArray = presetFolderName;
      
      String folderName = folderNames[folderChoice - 1];  //  does this actually do anything? -> could be used for proceeding
      

      dirArray += folderNames[folderChoice];

      File folder;
      folder = SD.open(dirArray.c_str());


      
      if(folder.isDirectory()){  //  
      

        while (true) //Does this loop & print twice?
        {
          File entry = folder.openNextFile(); //  I think, because it's just 'openNextFile' whilst Drums is a directory -> it will keep looping on the drums directory until all files are printed. 
         

          if (!entry) 
          {
            break;
          }
          display.clearDisplay();
          display.setTextColor(SSD1306_WHITE);  // Draw white text
          display.setCursor(0, 0);
          
        
          Serial.println("---LOOP START---");
          display.println(folder.name()); //  this prints: e.g. "Drums" - How to print multiple??
          Serial.println(folder.name());
          display.setCursor(12, 0);
          display.println(":");          
          
         
          for(uint8_t i = 0; i < numTabs; i++)
          {
           
            display.println('\t');  //  This line should print vertically
            
          }
          display.println(entry.name());  //  And this prints the audio - but only 1 file - how can we print multiple?
          Serial.println(entry.name());

          if(entry.isDirectory()) //  This is if it is a folder not a file -> not necessary?
          {
            display.println("/");

          }
          else
          {
            Serial.println("");
          }
           
          entry.close();
          
          Serial.println("---LOOP END^--");

          break; // -> this work in only printing 1 audio file - now how multiple?

        }
        
        
     
        
      }
            
      folder.close();
      display.display();
    
      
    }
   
  } 

    directoryPath = dirArray; // -> this output /Presets/Drums -> which is correct
    Serial.println(directoryPath);
    Serial.print("is ");
    Serial.print(directoryPath.length());
    Serial.print(" characters\n");
}

The output is:
Drums
DrumLoop1.wav
/Presets/Drums
is 14 characters

getFolder() should grab the folder which stores the audio files, the getFile() should grab a specific audio file which is stored in filePath. Which is then assigned to 1 of 8 pads, which can then play back the audio file.

What would you advise on if not an else if?
 
If you don't follow the forum rule we don't know what type directoryPath was declared as.

If it's type is char *, then be aware that == is not a string comparison operator, its a pointer comparison operator. Use strlen() or strcmp(). There's no reason to suppose that "" == "", if they are represented in different parts of memory.

In general expect == to report if the representations are identical, not that the values represented are the same. In many situations the same value can have multiple representations, unless the value itself fits in a register. Sometimes == is overloaded to work for value equality, but you are at the mercy of the implementer of the class in question.
 
Back
Top