Remove a certain item from a string array, for a temporary display list

I'm trying to remove an item from a string array, added based on an input.
The array begins empty as as:
String roomList[12];
When populated it may look like:
String roomList[12] = {"Bath", "Bed", "Closet"};

I want to delete one value like "Bed" and leave the rest.

Would it be removed based on index number or text match?
Iterate through all possible indexes of the array searching for matching text?

As you mentioned, this is "removing" it on a text match, for one example.

char *roomList[] = {"Bath", "Bed", "Beyond", "Closet"};
void setup()
{
  Serial.begin(9600);
  for (int i = 0; i < 4; i++)
  {
    if (roomList[i] != "Bed")
      Serial.println(roomList[i]);
    delay(500);
  }
}
void loop() {}

Thanks xfpd.
That's perfect

Yes, what was shown does work to "ignore" the matching word, but it is still in your array. The only way to eliminate it forever during this execution of the code it to copy the whole roomlist[12] to a new array, newroomlist[11] and not copying the entry that is to be removed.

That is not a text match, and I'm surprised that it works as a pointer match. The compiler is smarter than I thought!

A text match is done with strcmp(), for example.

@jremington - What is it that happened? String of char match? Is match even the right thing? I was not looking for a (if "yes" or "no")... or was I (due to what I tried)? (p.s. It also work with & address-of)

When you "delete" a file from your storage medium, the OS sets or resets a "this space available for use" flag... that is why data recovery works. Maybe @Ashton wants the data, but not "right now?"

Besides... I like breaking rules and doing things that can't be done. : )

The comparison was between two pointers, which happened to work because "Bed" is assigned to an arbitrary memory location, with a pointer stored in the array element roomList[1], and that pointer is then used again in the comparison.

Okay. That follows the srtcmp() on cplusplus.com

int strcmp ( const char * str1, const char * str2 );

@Ashton

you have accepted post #2 as solution but just to inform you, that code causes several compiler warnings. One:

C:\Daten\myrepository\Arduino\Forum no SVN\sketch_mar30a\sketch_mar30a.ino: In function 'void setup()':
C:\Daten\myrepository\Arduino\Forum no SVN\sketch_mar30a\sketch_mar30a.ino:5:24: warning: comparison with string literal results in unspecified behavior [-Waddress]
     if (roomList[i] != "Bed")
                        ^~~~~

the code might brake if you use it with another microcontroller or different compiler settings.

if you use use c-strings (small s) use strcmp to compare

const char *roomList[] = { "Bath", "Bed", "Beyond", "Closet" };  // make the c-string array const
void setup() {
  Serial.begin(9600);
  for (int i = 0; i < 4; i++) {
    if (!strcmp(roomList[i], "Bed"))        
      Serial.println(roomList[i]);
    delay(500);
  }
}
void loop() {}

Okay, this is the non-pointer/literal to "Bed" (compiler saves and uses un-controlled memory locations). Is that because you used const char? Was this warning from the Arduino IDE out-of-box, or in "strict" mode?

I have compiled on 1.8.19 for an UNO without any fancy tweaks.
Only activated "Compiler Warnings: all" in the Preferences Menu.
if you remove const you get even more warnings.

C:\Daten\myrepository\Arduino\Forum no SVN\sketch_mar30a\sketch_mar30a.ino:1:54: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
 char *roomList[] = {"Bath", "Bed", "Beyond", "Closet"};
                                                      ^
C:\Daten\myrepository\Arduino\Forum no SVN\sketch_mar30a\sketch_mar30a.ino:1:54: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
C:\Daten\myrepository\Arduino\Forum no SVN\sketch_mar30a\sketch_mar30a.ino:1:54: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
C:\Daten\myrepository\Arduino\Forum no SVN\sketch_mar30a\sketch_mar30a.ino:1:54: warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
C:\Daten\myrepository\Arduino\Forum no SVN\sketch_mar30a\sketch_mar30a.ino: In function 'void setup()':
C:\Daten\myrepository\Arduino\Forum no SVN\sketch_mar30a\sketch_mar30a.ino:7:24: warning: comparison with string literal results in unspecified behavior [-Waddress]
     if (roomList[i] != "Bed")
                        ^~~~~

I'm coming from using MySQLite3 in C++ on a Windows platform, where I was reading, appending, and writing to tables with SQL, to Arduino. I'm merely trying to read and temporarily log a few (3-8) 1-2 word strings, while being displayed, until the input goes off. Then remove the items from the display list. Hopefully without an array filling up with unseen items and failing. My small farm project is going not so fast. At least I have the Modbus communications working.

please show more context.
To "write" words / delete words from a display doesn't need any delete from an array.
either print something or not.
can you give us a minimalistic example (but complete) code to explain what you really need?

So simply, I'm reading the registers of a 32-input(digital) Modbus module, for the off/on state.
As shown in my code, I am receiving the 0s and 1s from the module, and needing to create a List that will be displayed on the largest small display screen I can get for Arduino, and may be emailed using an ESP8266. (without cloud data storage)

When an input goes on(1) it needs to be added to the Display List, and going off(0) the item will be removed from the Display List. These are not rapid on/off changes, usually 2-15 minutes duration each.

(The below array would not display within the code tags)
const char* arInput[]={"Bin 1", "Bin 2", "Bin 3", "Bin 4", "Bin 5", "Bin 6", "Bin 7", "Bin 8", "Bin 9", "Bin 10", "Bin 11", "Bin 12", "Bin 13", "Bin 14", "Bin 15", "Bin 16", "Bin 17",Bin 18", "Bin 19", "Bin 20", "Bin 21", "Bin 22", "Bin 23", "Bin 24", "Bin 25", "Bin 26", "Bin 27", "Bin 28", "Bin 29", "Bin 30", "Bin 31", "Bin 32"};

String onList[10];

void loop()
{
  uint8_t result;
  uint8_t j;
  uint16_t data[32]; 
  
   for (int s = 1; s < 2; ++s) // Modbus Slave selector starting at 1
   { 
     node.begin(s, mySerial); //slaveID s
      delay(100);
        result = node.readHoldingRegisters(128, 32);    // Read 32 registers starting at 0x0080(128)
         if (result == node.ku8MBSuccess) 
          {   
           for (int i = 0; i < 32; ++i)
          {
             if (node.getResponseBuffer(i)== 0)// -----------If Input Off ------------
          {
          // Compare to onList items & delete if found ?
           Serial.print("Input ");
           Serial.print(i);
           Serial.println(" off");
            /*  //not working
            if (onList[i] = arInput[i]){ 
              onList[i] != arInput[i];
               Serial.print("onList updated");
               delay(100);
               lcd.setCursor(0, 1);
               lcd.print("                ");
               lcd.print("Polling Inputs"); 
              }
            */ 
           //Serial.println(onInt); 
           // lcd.setCursor(0, 1);
            //lcd.print("                ");
            //lcd.print("Polling Inputs"); 
          } else  //                             ------------- Input is ON ------------
          {
           // Compare to onList, add to onList if not already --- Use a Function -----
           // Serial.print (arInput[i]); // Lookup bin/Input name & display, could be a function to lookup in data file, etc.
             lcd.setCursor(0, 1);
           
             Serial.print(arInput[i]);
             onList[i] = arInput[i];
             Serial.println(" is ON,  ");
             Serial.print("onList entry: "); //(onInt);
            Serial.println(onList[i]);
           lcd.print("Now ON: ");
           lcd.print(onList[i]); 
         } 
                      
        }
    delay(1000);
     }
   }
}

My onList really needs to be in an array or table or editable text file so it can be used for multiple purposes, like sending an email list and displaying.

that's nothing I can put in the IDE an play around.
However. Let me show you something.

For example you could define areas on a display which will be used for a specific input.
If you get an "this input is active" it will be shown for a short time.
The area will be deleted again.

/* Hello Wokwi! */
// https://forum.arduino.cc/t/remove-a-certain-item-from-a-string-array-for-a-temporary-display-list/1108657/16

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);

// char *roomList[] = {"Bath", "Bed", "Beyond", "Closet"};
// s
class Indicator {
  protected:
    char *text;
    const uint8_t col;
    const uint8_t row;
    bool state = 0;
    uint32_t previousMillis = 0;

  public:
    Indicator(uint8_t col, uint8_t row, char *text) : col{col}, row{row}, text{text} {}

    void on() {
      lcd.setCursor(col, row);
      lcd.print(text);
      state = 1;
      previousMillis = millis();
    }
    void off() {
      lcd.setCursor(col, row);
      for (size_t i = 0; i < strlen(text); i++) lcd.print('-');
      state = 0;
    }

    void update(uint32_t currentMillis = millis()) {
      if (state && currentMillis - previousMillis > 1500) {
        off();
      }
    }
};

Indicator indicator[]
{
  {0, 0, "Bath"},
  {6, 0, "Bed"},
  {10, 0, "Beyond"},
  {5, 1, "Closet"}
};

// simulate the change of states and switch on/off indicators on the LCD
void run() {
  static uint32_t previousMillis = 0;
  if (millis() - previousMillis > 2500) {
    previousMillis = millis();
    int actualIndicator = random(4);
    int actualValue = random(2);
    Serial.print(actualIndicator); 
    Serial.print("\t");
    Serial.println(actualValue); 
    if (actualValue == 1)
      indicator[actualIndicator].on();
  }
}

void someOtherActivity() {
  lcd.setCursor(13, 1);
  lcd.print(millis() / 1000);
}

void setup() {
  Serial.begin(115200);
  lcd.init();
  lcd.backlight();
  indicator[0].on();
  indicator[1].on();
  indicator[2].on();
  indicator[3].on();
  randomSeed(analogRead(A3));
}

void loop() {
  run();
  someOtherActivity();

  for (auto &i : indicator) i.update();
}

I know it's a completely different concept than you have.


What you can do is just to add the "active Bins" into a line of buffer in your loop and finally print it to the display.

edit:

Thanks noiasca,
Thats cool, looking and learning.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.