Need help learning C/C++: strings, arrays, type conversion, etc

First, apologies for my total noobishness. I’m not new to programming, but I am new to C/C++, which now that I have a Photon I must learn.

My current issue is around strings and type conversion. I have managed to get the example snippet from the RC522 RFID/NFC reader working, thanks to this thread, which is great.

However… I want to be able to, say, have an array of NFC card / tag UIDs and when a card / tag is read, if it’s in the array, do X.

So far I’ve managed to do those things in isolation… that is, I can read the cards/tags, and I have an array of strings which are the UIDs. But I can’t for the life of me compare them to each other.

Or, for that matter, even concatenate the UID with a string for debugging when reading a card/tag.

Please help? Even just a pointer to some good docs on this stuff. I hope my issue is clear. Thanks in advance!

Could you show what you’ve tried in order to achieve this so far?

This allows us to assess what way might be best to explain things and also may help you to break out of common ways of thinking (which are valid for one task but have to be “forgotten” in order to dive into another).

It’s often easier to grasp and remember things if you not only see how things do work but also why your intial thought didn’t.

2 Likes

Great points, thanks for replying too.

The code I have at this moment is in a Gist here: https://gist.github.com/Japh/f6886276aa4c552150ae

I’ve tried a whole bunch of different ways that seemed plausible (some from my own thinking, and some from what I could glean from Googling).

My background is mainly in PHP, Python, JavaScript… web stuff.

@Japh, take a look here for inspiration:

There was another project that used a fingerprint scanner coupled with RFID (I believe) and a database but I can't seem to find it.

Oh, I have the RFID part working fine (thanks to the thread I linked). My problem isn’t specifically with that… it’s dealing with strings, and converting between types in C/C++.

Note on the Gist I link above, lines 70-72 don’t work… but I don’t understand why. That’s my primary issue :smile:

I see, there are some things that need to play together

First there are two “major” ways to tackle strings

  1. C strings and
  2. the wiring String object

I prefere 1. since you actually see what’s happening, because you are doing it yourself. It’s slightly more work but safer.
2. is more convenient but since things happen under the hood, you might run into unexpected behaviour if you don’t know the “hidden” implementation.

For above reasons I’d focus on 1.

So looking at your code there are some things to consider

//char *newCardID;    // this only provides a pointer to a char (array), 
                      // but doesn't reserve memory to hold the string
// try this instead
char newCardID[128];  // reserves 128 byte to hold a 127char string with a terminating '\0'
char lastCardID[128];
// or the other way
//String newCardID;   // constructs a new String object with pre-reserved 16byte buffer
...
  // this would work with String, but may cause heap fragmentation when relocating the String object
  //newCardID = ""; 

  char _hex[4];       // dummy var for building
  newCardID[0] = 0;   // terminate C string at beginning (lazy clear string) 
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    sprintf(_hex, " %02x", mfrc522.uid.uidByte[i]);
    strcat(newCardID, _hex);  // or strncat() to avoid buffer overflow
    Serial.print(_hex);
  }
  Serial.println();
  Serial.println(newCardID);

This can be streamlined a lot, but to get the general idea this is easier to understand.
e.g. instead of using _hex and strcat() you could go for

  • sprintf(&newCardID[i*3], " %02x", mfrc522.uid.uidByte[i]) or
  • sprintf(newCardID + i*3, " %02x", mfrc522.uid.uidByte[i]).

About string comparison and direct assignment

  // this would only work as expected with two String objects
  // with C strings this would only check if the two pointer point to the same mem location
  if (lastCardID != newCardID) {
    lastCardID = newCardID; 
    Serial.print(newCardID);
  }

  // for C strings use 
  if (strcmp(lastCardID, newCardID) != 0) {
  {
    strcpy(lastCardID, newCardID); 
  }

(sorry that it took so long, but I’ve had to attend to other duties too)

1 Like

Fantastic, thanks so much!

I’ve had a quick look… compiled ok, and flashed ok, but after first scan I got red flashing LED on the Photon, so will have to look closer tomorrow (it’s 2:00am here now).

Thanks again, I think this has gotten me unstuck :smile:

1 Like

I guess you got SOS +1 red blink, probably since 64 or 128 byte were too little, hence the suggestion about strncat().
I also changed the code marginally, so please re-read :sunglasses:

1 Like

Thanks again, I’ve taken a look back through and made the strncat tweak (I think that’s all I missed, as I had already gone back through it previously for changes).

Switched back to strcat though when I realised I wasn’t sure what to put for size_t. Perhaps 3?!

Anyway, I also noticed I typoed %02x as %20x. Once I fixed that, it stopped SOSing.

Just tried a little fine tuning and playing around with more stuff, and this is now working just how I wanted it to. I also found a reference which I hadn’t stumbled across before which has helped understand the difference between strcat and strncat.

Thanks so much, @ScruffR!

1 Like