Strings vergleichen funktioniert nicht -- warum?

Hallo.
ich habe ein RFID-Tag mit einem Text beschrieben und konnte es auch bereits erfolgreich wieder auslesen.
Dazu habe ich dieses Shield
https://aptofun.de/NFC_Shield_V2.0
und diesen Code verwendet:

Das funktioniert zunächst nun zwar alles -- aber wenn ich den String "payloadAsString" mit irgendwas vergleichen will wie z.B.:

if (payloadAsString == "Inhalt")
oder aber
if (payloadAsString.equals("Inhalt")) {

funktioniert das nicht und ich wüsste gerne warum?!
Wie muss das richtig lauten, damit es funktioniert?
Danke.

Stell den Code bitte hier rein, dann kann ihn jeder lesen.

Und wie sieht die Ausgabe von payload (HEX) genau aus?

Das liegt daran, dass payloadAsString vom Typ String ist (von dessen Verwendung auf dem Arduino in der Regel abgeraten wird) und "Inhalt" vom Type const char * (C-String).
Letzterer ist kein Objekt und hat deshalb auch weder den Vergleichsoperator == überladen noch besitzt er eine Methode equals().

Abhilfe:

  • "Inhalt" in einen String konvertieren (bitte nicht, das ist nur eine theoretische Möglichkeit)
  • strcmp() verwenden und dabei payloadAsString.c_str() verwenden (geht, ist aber nicht schön).
  • Den Code so umschreiben, dass auch payloadAsString ein C-String wird und strcmp() verwenden.

wno158:
Das liegt daran, dass payloadAsString vom Typ String ist (von dessen Verwendung auf dem Arduino in der Regel abgeraten wird) und "Inhalt" vom Type const char * (C-String).
Letzterer ist kein Objekt und hat deshalb auch weder den Vergleichsoperator == überladen noch besitzt er eine Methode equals().

Das stimmt nicht. Du kannst natürlich ein String Objekt mit einem Literal vergleichen. Es wäre sehr schlecht wenn das nicht ginge

Und die entsprechenden Methoden und Operatoren musst du in der String Klasse suchen:

unsigned char equals(const char *cstr) const;
unsigned char operator == (const char *cstr) const {return equals(cstr);}

Sorry wno158, das ist nicht richtig.

void setup() {
Serial.begin(9600);
String s("Hallo");
const char* cp = "Hallo";
if (s == cp) Serial.println(" String == char* vergleicht zwei Strings");
if (s.equals("Hallo") ) Serial.println(" String::equals geht auch");
}

void loop() {
}

Erzeugt zwei Zeilen Ausgabe

Natürlich gebe ich dir Recht, dass man immer besser ohne String-Objekte auskommt. Strings sollen das Leben erleichtern. Wenn sie das nicht tun, ist es immer besser, sie einfach gar nicht zu verwenden.

String payloadAsString = "";
        for (int c = 0; c < payloadLength; c++) {
          payloadAsString += (char)payload[c];
        }

Hier ist nicht 1 String zu sehen, sondern payloadLength viele, denn für jeden Buchstaben wird ein neuer String erzeugt und der vorige auf den Müll geworfen.

Oh - Danke ihr beiden!
Wieder was dazu gelernt; habe mich nicht an die eigene Regel gehalten, erstmal im Header selbst nachzusehen.
Schäm.

Dann würde es natürlich doch helfen, etwas mehr vom Code des TO zu sehen :wink:

wno158:
Dann würde es natürlich doch helfen, etwas mehr vom Code des TO zu sehen :wink:

Hi. Viel mehr kann ich (TO) nicht beisteuern -- ich habe den Code bisher nur um diese Zeilen ergänzt, die das RFID-Tag auslesen und dann den Wert auf einen Zähler addieren sollen.
Also konkret:

Serial.println(payloadAsString);
 if (payloadAsString == "ABC")
   {Serial.println("Wert:10");
    wert=10;}
 if (payloadAsString == "DEF")
   {Serial.println("Wert:15");
    wert=15;}
   
    gesamt = gesamt + wert;
    Serial.println(gesamt);

Das funktioniert so leider nicht -- ich bin aber leider auch (noch?) kein Experte in Sachen Arduino-Programmierung. Daher wäre ich für einen Tipp dankbar, wie ich

Den Code so umschreiben, dass auch payloadAsString ein C-String wird und strcmp() verwenden.

das bewerkstelligen kann?

Du solltest zumindest die Deklaration der beteiligten Variablen noch bekannt geben.

Gruß Tommy

Tommy56:
Du solltest zumindest die Deklaration der beteiligten Variablen noch bekannt geben.

Das sind alles integer ... und zwar oberhalb des loops definiert als:

int gesamt = 0;
int wert = 0;

Es ging eigentlich eher um die Zeichenkettenvariablen.
Das ist halt der Nachteil, wennmj es nur Frgmente gibt.

Gruß Tommy

whiterabbit07:
Daher wäre ich für einen Tipp dankbar, wie ich
Den Code so umschreiben, dass auch payloadAsString ein C-String wird und strcmp() verwenden.
das bewerkstelligen kann?

Das steht doch in #5:

if (payloadAsString == String("ABC"))
...
if (payloadAsString == String("DEF"))

Oder zusammenhängend:

void setup() {
  Serial.begin(9600);
  byte wert = 0, gesamt = 0;
  String payloadAsString = "ABC";
  Serial.println(payloadAsString);

  if (payloadAsString == String("ABC"))
  { Serial.println("Wert: 10");
    wert = 10;
  }
  if (payloadAsString == String("DEF"))
  { Serial.println("Wert: 15");
    wert = 15;
  }

  gesamt = gesamt + wert;
  Serial.println(gesamt);
}

void loop() {
}

Oder auch so:

void setup() {
  Serial.begin(9600);
  byte wert = 0, gesamt = 0;
  String payloadAsString = "ABC";
  Serial.println(payloadAsString);

  if (!strncmp (payloadAsString.c_str(), "ABC", 3))
  { Serial.println("Wert: 10");
    wert = 10;
  }
  if (!strncmp (payloadAsString.c_str(), "DEF", 3))
  { Serial.println("Wert: 15");
    wert = 15;
  }

  gesamt = gesamt + wert;
  Serial.println(gesamt);
}

void loop() {
}

whiterabbit07:
Hi. Viel mehr kann ich (TO) nicht beisteuern

Dochdoch...
Dein Code.

Wenn ich das sehe:

         byte payload[payloadLength];
        record.getPayload(payload);

gibt es da ein array.
Da ginge so ziemlich alles...

@whiterabbit:
Das mit dem Umarbeiten kannst Du sparen. Die Kollegen haben mich freundlich darauf hingewiesen, dass die Vergleiche funktionieren sollten. Die String-Klasse kann mit Zeichenkettenkonstanten umgehen.

Ich lege mal den originalen Code aus dem Link in #0 zugrunde.

Was dann hilfreich wäre: Die Ausgabe aus dem Monitor, die hinter " Payload (HEX): " erscheint.
Daran kann man dann sehen, was die Payload wirklich ist und (vielleicht) warum die Vergleiche fehlschlagen und die Zuweisungen nicht ausgeführt werden.

Hallo.
Ich habe gerade mal ein TAG mit dem Begriff "Hammer" beschrieben. Das Auslesen liefert jetzt erwartungsgemäß:

Payload (HEX): 00 48 61 6D 6D 65 72  .Hammer
Payload (String): Hammer

Ist da evtl ein Zeichen zuviel?

michael_x:

String payloadAsString = "";

for (int c = 0; c < payloadLength; c++) {
         payloadAsString += (char)payload[c];
       }



**Hier ist nicht 1 String zu sehen, sondern payloadLength viele, denn für jeden Buchstaben wird ein neuer String erzeugt und der vorige auf den Müll geworfen.**

Das ist vermutlich das Problem -- aber wie kann man das anders machen?

whiterabbit07:

Payload (HEX): 00 48 61 6D 6D 65 72  .Hammer

Payload (String): Hammer



Ist da evtl ein Zeichen zuviel?

Ja und es ist auch noch das Zeichenkettenendesteuerzeichen.

Der Fehler liegt also beim Einlesen, nicht beim Vergleich!

Das Steuerzeichen 0x00 schließt eventuell die vorhergehende Zeichenkette ab oder Du hast den Tag falsch beschrieben.

whiterabbit07:
erwartungsgemäß:

Payload (HEX): 00 48 61 6D 6D 65 72  .Hammer

Payload (String): Hammer



Ist da evtl ein Zeichen zuviel?

Ja.
agmue war schneller - aber Du musst Dich jetzt leider durch die lib wühlen.

Zuerst musst Du sicherstellen, das auch das geschrieben wird, was du übergibst und nicht zusätzlich noch ein \0 ...

Puh, das wird mir leider echt zu kompliziert ... ich bin da ~newbie ...
Die Datei, die ich zum Formatieren und Beschreiben verwendet habe, sind auch auf der Seite oben angegeben. Konkret war das diese:
Example #4: Write an NDEF Message to a Tag

Wenn es einfacher ist, nicht den String sondern das Byte zu vergleichen, wäre mir das auch egal ... Hauptsache irgendeine Fallunterscheidung für die RFID-Tags?!

whiterabbit07:
Example #4: Write an NDEF Message to a Tag

der schreibt mittels:
addUriRecord - also etwas aus der lib...

Wenn es einfacher ist,

Nein ist es nicht.
Es ändert nichts an der Tatsache, das zwischen dem was Du übergibst und dem was Du zurück bekommst ein Unterschied ist.
Das musst Du lösen - und nicht an den Ergebnissen rumbasteln bis sie passen!

@TO: Du musst erst mal raus bekommen (erstes HEX-Einlesen nach Neustart), ob das 0-Byte ein Rest oder ein Inhalt ist.
Danach kann man weiter sehen.

Gruß Tommy