2

I have the following C++ code:

#define VERSION        1
#define TYPE           "this"
...

bool update(const char* json) {
    ...
    const char* theType = doc["type"];     // "this"
    int theVer          = doc["version"];  // 2

    //int ourVer        = VERSION;
    //char ourType[]    = TYPE;

    if ( (theVer > VERSION) && (theType == TYPE) ) {
        return true
    } else {
        return false;
    }
}

I can print both theType and theVer, but I am not able to successfully compare them with the constants. I also tried to compare to the casted constants (commented out) to no avail.

How do I compare strings and integers defined by #define?

BTW. This is coded in ArduinoIDE.

not2qubit
  • 14,531
  • 8
  • 95
  • 135
  • 1
    `theType == TYPE` compares the pointers, not content. Use `strcmp` instead. – L. F. Jul 10 '19 at 11:20
  • @L.F. The comments section is for comments, not answers. Use the answer section instead. – Lightness Races in Orbit Jul 10 '19 at 11:42
  • How do you arrange for `doc[std::string]` to return two different types depending on the run-time value of the string? – rici Jul 10 '19 at 17:13
  • Also: `if (some complicated expression) { return true; } else { return false; }` can be written much more simply (and, imo idiomatically) as `return some_complicated_expression;` – rici Jul 10 '19 at 17:14
  • @rici Obviously I will do something else there, and just trying to simplify the code to be relevant to the question. – not2qubit Jul 11 '19 at 07:41

5 Answers5

3

theType == TYPE compares two pointers. It returns true if and only if the addresses are the same, which is not the case here.

Use strcmp instead:

if (theVer > VERSION && std::strcmp(theType, TYPE) == 0) {
    // ...
}

strcmp three-way compares the actual strings, returning a number that is < 0, == 0, or > 0 when the first string is less than, equal to, or greater than the second. You need #include <cstring> for this.

L. F.
  • 19,445
  • 8
  • 48
  • 82
2

I know L.F's answer has already been accepted but i wish to dissent on their advice to use strcmp. you shouldn't even be using #define anymore but constexpr instead. This allows you to be clear on typing and, in my experience, constexpr play's nicer with intellisense.

What you should use for TYPE is constexpr std::string_view. which wont force you to use old c libraries and can be compared with std::string using the == operator.

#include <string_view>
#include <string>

constexpr int THIS = 1;
constexpr std::string_view TYPE = "this";
...

bool update(const std::string & json) {
    ...
    std::string theType = doc["type"]; // "this"
    int theVer = doc["version"];  // 2

    if ( (theVer > VERSION) && (theType == TYPE) ) {
        return true
    } else {
        return false;
    }
}

https://en.cppreference.com/w/cpp/language/constexpr https://en.cppreference.com/w/cpp/string/basic_string_view

QCTDev
  • 166
  • 6
  • Hi @qctdev and welcome to SO. Your solution is helpful and interesting, since I have not used this syntax before, so please provide a link to the docs. In addition, I am using `#define` because it is doing many other things in my code, that will never change and sometimes not needed for other compiles. – not2qubit Jul 10 '19 at 12:09
  • Thanks for the suggestion, I've added the documentation links. You know your own code best so i shall devolve to your judgement on how it should work. I just wished to state what i understand to be the 'proper' way of doing things should anyone else happen along. – QCTDev Jul 10 '19 at 12:21
  • Question is if `std::string_view` is available in Arduino. This is light platform (2kB of RAM) so there is no heap, so many stuff can't be used there. Bottom line I wouldn't be surprised if there is no `std::string_view` for Arduino (didn't verified that), on other hand since it doesn't use heap there might be some limited version of it (possibly under different name). – Marek R Jul 10 '19 at 13:32
  • to my knowledge string_view doesn't require a heap be available(it works just dandy with things on the stack), however I've just checked and c++ 17 doesn't appear to available for Arduino. Without support for the 2017 standard you wont be able to use string_view (unless you re-implement it yourself which which would be a lot of work for little gain). – QCTDev Jul 10 '19 at 13:46
  • There are third-party implementations of `string_view`, if you want to use them without C++17. You're absolutely right that it doesn't require any storage allocation; that's its entire point. It's very lightweight, and there's absolutely no reason not to use it on an embedded platform. (Indeed, it can often reduce memory use.) – rici Jul 10 '19 at 17:12
  • Using all UPPERCASE names for compile time constant is antipattern. – Slava Jul 10 '19 at 20:07
  • 1
    All caps constants, compile time or otherwise, seems to be the default everywhere I've looked. – QCTDev Jul 11 '19 at 06:33
1

#define is irrelevant.

After preprocessing, your snippet is exactly equivalent to:

bool update(const char* json) {
    const char* theType = doc["type"];     // "this"
    int theVer          = doc["version"];  // 2

    if ( (theVer > 1) && (theType == "this") ) {
        return true
    } else {
        return false;
    }
}

So the problem is reduced to "how do we compare two C-strings?", with a much simpler example like this:

int main()
{
   const char* theType = "this";
   const bool  matches = (theType == "this");
}

The answer is, not with ==, but with strcmp.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0
#define VERSION        1
#define TYPE           "this"
...

bool update(const char* json) {
   ...
   const char* theType = doc["type"];     // "this"
   int theVer          = doc["version"];  // 2

   return (theVer > VERSION) && !strcmp(TYPE,theType) ;
}
Laszlo
  • 769
  • 9
  • 19
0

Maybe this code will help you:

bool func()
{
    const string str = "value";
    int number = 3;
    return str == const_string && number == const_number ? true : false;
}
MyName
  • 135
  • 1
  • 10