-2

I'm new to C and C++, and can't seem to work out how I need to compare these values:

Variable I'm being passed:

typedef struct {
    uint8_t ssid[33];

String I want to match. I've tried both of these:

uint8_t AP_Match = "MatchString";
unsigned char* AP_Match = "MatchString";

How I've attempted to match:

if (strncmp(list[i].ssid, "MatchString")) {
if (list[i].ssid == AP_Match) {
if (list[i].ssid == "MatchString") {

// This one fails because String is undeclared, despite having 
// an include line for string.h
if (String(reinterpret_cast<const char*>(conf.sta.ssid)) == 'MatchString') {

I've noodled around with this a few different ways, and done some searching. I know one or both of these may be the wrong type, but I'm not sure to get from where I am to working.

jww
  • 97,681
  • 90
  • 411
  • 885
Ben Dauphinee
  • 4,061
  • 8
  • 40
  • 59
  • What we need to know is what's actually *in* `ssid`. It's a sequence of 8-bit unsigned integers that may encode "MatchString" in some way. But without knowing in what way, there's no way to do the comparison. It's like asking how to compare a string to the number four. Is the string "4", "four", "XXXX", or what? Compare the string to the number four assuming what kind of encoding? And, here, compare the sequence of 8-bit integers to a string assuming what kind of encoding? – David Schwartz Sep 01 '18 at 15:43
  • @DavidSchwartz How would I determine the contents of that variable to answer this question? All I know is when I do this: printf("%s\n",list[i].ssid); I get MatchString – Ben Dauphinee Sep 01 '18 at 15:46
  • You get that on some machine that happens to have the right encoding. But what happens if you run the code on a machine that uses EBCDIC or some other string encoding? Is `ssid` guaranteed to be an ASCII encoded string or is it guaranteed to match the platform's native string encoding scheme? You have to know what the problem is to be sure you've solved the problem and not written code that just happens to work when you tested it. – David Schwartz Sep 01 '18 at 15:51
  • 2
    `reinterpret_cast` is not C, but C++. This language provides a string type, use it. And don't use tags for a different language. – too honest for this site Sep 01 '18 at 15:54
  • To use an analogy, say the string was "four" and you were comparing it to the number four. You'd need to know if the string was guaranteed to be in English or just happened to be in English because you're on a machine that uses English. Otherwise, you *could* *not* write the correct code, just code that happened to work on your machine. If you don't know what encoding `ssid` is supposed to be using, you cannot reliably tell by looking at it because you don't know what those results depend on, and your code has to know that to be correct. – David Schwartz Sep 01 '18 at 15:54
  • You could write code that just compares to "four" or you could write code that converts the input to English and then compares. Both would work on your machine, but only one would be right. To know which is right, you need a specification of the encoding the input is using, and you cannot tell that by looking because it would be "four" on your English machine in both cases. So you really don't know what the encoding on the string is, and you cannot write the correct code to compare it without that. Answers you get that ignore this will necessarily create unreliable code. – David Schwartz Sep 01 '18 at 15:57
  • @DavidSchwartz I'm not a new _programmer_ just new to C. Instead of commenting what is the right _idea_ of how to do this, maybe give me a hint about the right direction to go in to work out how to get the information needed to solve this? – Ben Dauphinee Sep 01 '18 at 15:59
  • 1
    Possible duplicate of [Comparing uint8\_t data with string](https://stackoverflow.com/q/34693203/608639) – jww Sep 01 '18 at 16:04

2 Answers2

1

There is no such type as "String" defined by any C standard. A string is just an array of characters that are stored as unsigned values based on the chosen encoding. 'string.h' provides various functions for comparison, concatenation, etc. but it can only work if the values you are passing to it are coherent.

The operator "==" is also undefined for string comparisons, because it would require comparing each character at each index, for two arrays that may not be the same size and ultimately may use different encodings, despite the same underlying unsigned integer representation (raising the prospect of false positive comparisons). You can possibly define your own function to do it (note C doesn't allow overloading operators), but otherwise you're stuck with what the standard libraries provide.

Note that strncmp() takes a size parameter for the number of characters to compare (your code is missing this). https://www.tutorialspoint.com/c_standard_library/c_function_strncmp.htm

Otherwise you would be looking at the function strcmp(), which requires the input strings to be null-terminated (last character equal to '\0'). Ultimately it's up to you to consider what the possible combinations of inputs could be and how they are stored and to use a comparison function that is robust to all possibilities.

As a final side note

if (list[i].ssid == "MatchString") {

Since ssid is an array, you should know that when you do this comparison, you are not actually accessing the contents of ssid, but rather the address of the first element of ssid. When you pass list[i].ssid into strcmp (or strncmp), you are passing a pointer to the first element of the array in memory. The function then iterates over the entire array until it reaches the null character (in the case of strcmp) or until it has compared the specified number of elements (in the case of strncmp).

0

To match two strings use strcmp:

if (0==strcmp(str1, str2))

str1 and str2 are addresses to memory holding a null terminated string. Return value zero means the strings are equal.

In your case one of:

if (0==strcmp(list[i].ssid, AP_Match))
if (0==strcmp(list[i].ssid, "MatchString"))
Andreas
  • 5,086
  • 3
  • 16
  • 36
  • Don't use Yoda conditions. Every halfway modern compiler will warn about the assignment-in-a-condition flaw. Write easily readable code. – too honest for this site Sep 01 '18 at 15:52
  • 2
    @toohonestforthissite In this case I did Yoda to get the code to align better. Nothing, I regret – Andreas Sep 01 '18 at 15:54
  • As one typically does not use an `if`, but `if … else if` ladder and there is code in the `if` bodies, alignment does not make sense. (in fact it's not used for e.g. de3clarations since the 80ies by most programmers, as its problems outnumber the small potential benefit). – too honest for this site Sep 01 '18 at 16:05
  • @toohonestforthissite - John Robbins recommended placing constants on the left to avoid accidental assignment dating back to the mid 1990s. Robbins used it as a control to contain programming errors. You seem to be pleading a style argument. – jww Sep 01 '18 at 16:11
  • @jww: Read my comment carefully. Leave the warnings to the compiler. It's not just a style argument, by a well researched psychological yoda conditions are harder to comprehend by the average human (and remember this is read and adopted mostly by beginners). Re. recommendations: in the 80ies `return` results were often parenthtised and the K&R coding style was common. Tempora mutantur … – too honest for this site Sep 01 '18 at 16:19
  • @toohonestforthissite - Thanks. It is interesting we both have an interest in psychology to understand why things fail. Users often ignore warnings (or don't enable them), and that outcome allows the assignment to occur. The safer code is the un-stylish one. – jww Sep 01 '18 at 16:23
  • @jww: The "users forget enabling warnings …" argument applies to much more and more common errors in C. It's a non-sequitur for the problem at hand. Said that, it's a red herring, as an assignment **too** a function is illegal, so there would be a message however you write it. (but yeah, first thing programming beginners should get used to is to enable all warnings **and fix them**.) – too honest for this site Sep 01 '18 at 16:31