1

I would like to use the following function to compare two char arrays:

if(strcmp((PtrTst->cDatVonCom),szGeraeteAntwort)==0)

Now my problem is that PtrTst->cDatVonCom[5000] is different than the szGeraeteAntwort[255] and the entire values looks a little bit different: (abstract from the logfile).

PtrTst->cDatVonCom:

04/16/19 12:53:36 AB A{CR}{LF}
  0  0{CR}{LF}

szGeraeteAntwort:

04/16/19 12:53:36 AB A  0  0{CR}{LF}

Could I check if the command (in this case AB A) is the same in both? The command can change and it must be in both the same to go through the if statement.

UPDATE:

Both char arrays are always there and i need to check if the "szGeraeteAntwort" is in the PtrTst->cDatVonCom. In C# i would use an cDatVonCom.Contains... or something like this to check if there the same.

kb_
  • 610
  • 4
  • 21
  • 3
    What about other whitespace characters? – Groo Apr 16 '19 at 11:40
  • @Groo What do you mean? Thats there can come a AB A A A as command? – kb_ Apr 16 '19 at 11:42
  • 1
    Are you permitted to modify the arrays' content? – John Bollinger Apr 16 '19 at 11:48
  • @JohnBollinger: Only for the szGeraeteAntwort, the cDatVonCom i can't change. – kb_ Apr 16 '19 at 11:50
  • 2
    And is it really a requirement to use `strcmp` to perform the comparison, rather than some other approach? Exactly one call? – John Bollinger Apr 16 '19 at 11:54
  • 1
    Adding to @JohnBollinger, You extract the command from `cDatVonCom` and use `strstr` which searches the sub string in main array. `strstr` will return valid pointer in the main string if sub string is found otherwise it returns NULL. – kiran Biradar Apr 16 '19 at 11:55
  • 1
    @JohnBollinger: it's not required but it was the only way i've found with my bad c skills – kb_ Apr 16 '19 at 11:56
  • @kiranBiradar: So your way would be if (strstr(PtrTst->cDatVonCom, szGeraeteAntwort) != NULL) ? as if? – kb_ Apr 16 '19 at 12:14

3 Answers3

4

You have two strings that whose logical content you want to compare, but their literal presentation may vary. In particular, there may be CR/LF line termination sequences inserted into one or both, which are not significant for the purposes of the comparison. There are many ways to approach this kind of problem, but one common one is to define a unique canonical form for your strings, prepare versions of both strings to that form, and compare the results. In this case, the canonical form would presumably be one without any CR or LF characters.

The most general way to approach this is to create canonicalized copies of your strings. This accounts for the case where you cannot modify the strings in-place. For example:

/*
 * src  - the source string
 * dest - a pointer to the first element of an array that should receive the result.
 * dest_size - the capacity of the destination buffer
 * Returns 0 on success, -1 if the destination array has insufficient capacity
 */
int create_canonical_copy(const char src[], char dest[], size_t dest_size) {
    static const char to_ignore[] = "\r\n";
    const char *start = src;
    size_t dest_length = 0;
    int rval = 0;

    while (*start) {
        size_t segment_length = strcspn(start, to_ignore);

        if (dest_length + segment_length + 1 >= dest_size) {
            rval = -1;
            break;
        }
        memcpy(dest + dest_length, start, segment_length);
        dest_length += segment_length;
        start += segment_length;
        start += strspn(start, to_ignore);
    }
    dest[dest_length] = '\0';

    return rval;
}

You might use that like so:

char tmp1[255], tmp2[255];

if (create_canonical_copy(PtrTst->cDatVonCom, tmp1, 255) != 0) {
    // COMPARISON FAILS: cDatVonCom has more non-CR/LF data than szGeraeteAntwort
    // can even accommodate
    return -1;
} else if (create_canonical_copy(szGeraeteAntwort, tmp2, 255) != 0) {
    // should not happen, given that szGeraeteAntwort's capacity is the same as tmp2's.
    // If it does, then szGeraeteAntwort must not be properly terminated
    assert(0);
    return -1;
} else {
    return strcmp(tmp1, tmp2);
}

That assumes you are comparing the strings for equality only. If you were comparing them for order, as well, then you could still use this approach, but you would need to be more care ful about canonicalizing as much data as the destination can accommodate, and about properly handling the data-too-large case.

John Bollinger
  • 121,924
  • 8
  • 64
  • 118
3

There are several things you can do; here are two:

  1. Parse both strings (e.g. using scanf() or something more fancy)), and during the parsing ignore the newlines. Now you'll have the different fields (or an indication one of the lines can't be parsed properly, which is an error anyway). Then you can compare the commands.
  2. Use a regular expression matcher on those two strings, to obtain just the command while ignoring everything else (treating CR and LF as newline characters essentially), and compare the commands. Of course you'll need to write an appropriate regular expression.
einpoklum
  • 86,754
  • 39
  • 223
  • 453
  • Thanks for the answer, I've a question for this: do you would make an fgets for both char arrays? – kb_ Apr 16 '19 at 13:53
  • Ok, thanks. I have two char arrays and in one i can set a answer i will expect in the other char array (scale commands with scale anwsers). Therefore i need the check. Can i use the fgets() in the if(...) statement? I'm unsure now.. – kb_ Apr 16 '19 at 14:11
  • Sorry, I misspoke. `fgets()` is for reading from the file . It's `scanf()` which can be used for parsing. Also, this would likely require a small function, not a one-liner. – einpoklum Apr 16 '19 at 14:18
  • Ok but when i see it right scanf is for entering something? Both char arrays are always there and they need only a check if there are the same. You can't enter there something. i'm sorry. – kb_ Apr 16 '19 at 14:25
3

A function that compares the strings while skipping over some characters could be used.

#include <stdio.h>
#include <string.h>

int strcmpskip ( char *match, char *against, char *skip) {
    if ( ! match && ! against) { //both are NULL
        return 0;
    }
    if ( ! match || ! against) {//one is NULL
        return 1;
    }
    while ( *match && *against) {//both are not zero
        while ( skip && strchr ( skip, *match)) {//skip not NULL and *match is in skip
            match++;
            if ( ! *match) {//zero
                break;
            }
        }
        while ( skip && strchr ( skip, *against)) {//skip not NULL and *against is in skip
            against++;
            if ( ! *against) {//zero
                break;
            }
        }
        if ( *match != *against) {
            break;
        }
        if ( *match) {//not zero
            match++;
        }
        if ( *against) {//not zero
            against++;
        }
    }
    return *match - *against;
}

int main( void) {
    char line[] = "04/16/19 12:53:36 AB A\r\n 0  0\r\n";
    char text[] = "04/16/19 12:53:36 AB A 0  0\r\n";
    char ignore[] = "\n\r";

    if ( strcmpskip ( line, text, ignore)) {
        printf ( "do not match\n");
    }
    else {
        printf ( "match\n");
    }

    return 0;
}
xing
  • 1,924
  • 2
  • 11
  • 10