Сравните два набора символов без CR LF - PullRequest
1 голос
/ 16 апреля 2019

Я хотел бы использовать следующую функцию для сравнения двух массивов символов:

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

Теперь моя проблема в том, что PtrTst->cDatVonCom[5000] отличается от szGeraeteAntwort[255], а все значения выглядят немного иначе: (выписка из лог-файла).

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}

Могу ли я проверить, является ли команда (в данном случае AB A) одинаковой в обоих? Команда может измениться, и она должна быть одинаковой для выполнения оператора if.

UPDATE:

Оба символьных массива всегда есть, и мне нужно проверить, находится ли szGeraeteAntwort в PtrTst-> cDatVonCom. В C # я бы использовал cDatVonCom.Contains ... или что-то вроде этого, чтобы проверить, есть ли там то же самое.

Ответы [ 3 ]

4 голосов
/ 16 апреля 2019

У вас есть две строки, содержимое которых логического вы хотите сравнить, но их буквальное представление может отличаться.В частности, могут быть последовательности завершения линии CR / LF, вставленные в одну или обе, которые не являются значимыми для целей сравнения.Существует много способов решения этой проблемы, но один из них - определить уникальную каноническую форму для ваших строк, подготовить версии обеих строк для этой формы и сравнить результаты.В этом случае канонической формой, вероятно, будет та, которая не содержит символов CR или LF.

Самый общий способ сделать это - создать канонизированные копии ваших строк.Это объясняет случай, когда вы не можете изменить строки на месте.Например:

/*
 * 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;
}

Вы можете использовать это так:

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);
}

Предполагается, что вы сравниваете строки только на равенство.Если бы вы сравнивали их и для порядка , то вы все равно могли бы использовать этот подход, но вам нужно было бы быть более внимательным, чтобы канонизировать столько данных, сколько может вместить пункт назначения, и правильно обработатьдело со слишком большими данными.

3 голосов
/ 16 апреля 2019

Можно использовать функцию, которая сравнивает строки, пропуская некоторые символы.

#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;
}
3 голосов
/ 16 апреля 2019

Есть несколько вещей, которые вы можете сделать; вот два:

  1. Анализирует обе строки (например, используя scanf() или что-то более причудливое)) и во время синтаксического анализа игнорирует переводы строки. Теперь у вас будут разные поля (или указание, что одна из строк не может быть правильно проанализирована, что в любом случае является ошибкой). Затем вы можете сравнить команды.
  2. Используйте совпадение регулярного выражения для этих двух строк, чтобы получить только команду, игнорируя все остальное (рассматривая CR и LF как символы новой строки по существу), и сравните команды. Конечно, вам нужно написать соответствующее регулярное выражение.
...