Как написать функцию, которая принимает компаратор в C? - PullRequest
0 голосов
/ 18 февраля 2019

У меня есть структура vector, которая хранит свои данные в двойном пустом указателе.Структура выглядит следующим образом:

typedef struct vector {
    void **data;
    int capacity;
    int size;
} vector;

Я пытаюсь несколько повторить функцию std::find в C ++, чтобы найти элементы в vector, которые у меня есть.Я сделал это, создав функцию vector_find:

int vector_find(vector* v, void *elem, __compar_fn_t cmp)
{
    for (int i = 0; i < v->size - 1; i++)
    {
        if(cmp(v->data[i], elem) == 0)
        {
            return i;
        }
    }
    return -1;
}

Эта функция находится в моем файле vector.c.Он принимает функцию компаратора.Если он найдет элемент, он вернет его местоположение в векторе.

Это все определено в моем файле vector.c.

Теперь я пытаюсь использовать эту функцию в одной из моих программ, в этой функции:

int cstring_cmp(const void *a, const void *b)
{
    const char *ia = *(const char **)a;
    const char *ib = *(const char **)b;
    printf("%s    %s", ia, ib);
    return strcmp(ia, ib);
}

void
execute(vector* tokens)
{
    if (vector_find(tokens, ";", cstring_cmp) > -1)
    {
        printf("semicolon found");
    }
}

Однако, когда я запускаю эту функцию, я получаю segfault со следующей ошибкой:

Program received signal SIGSEGV, Segmentation fault.
__strlen_sse2 () at ../sysdeps/x86_64/multiarch/../strlen.S:120
120 ../sysdeps/x86_64/multiarch/../strlen.S: No such file or directory.

Я проверил несколько вещей:

  1. Я подтвердил, что ошибка возникает в моей функции execute.В частности, когда я вызываю vector_find.

  2. Я убедился, что эта ошибка возникает независимо от того, пусто tokens или нет.Это интересно, потому что цикл for в vector_find никогда не должен выполняться, если вектор, который я передаю vector_find, пуст.

  3. , который я включил в vector.c и файлЯ бегу.

Я также попробовал этот формат:

int vector_find(vector* v, void *elem, int (*cmp) (const void*, const void*))
{
    for (int i = 0; i < v->size; i++)
    {
        if((*cmp) (v->data[i], elem) == 0)
        {
            return i;
        }
    }
    return -1;
}

... и получил ту же ошибку.

Я делаю это правильно?Очевидно нет - где моя ошибка?

Ответы [ 2 ]

0 голосов
/ 18 февраля 2019

Ваша функция сравнения ожидает, что каждый из ее параметров равен char **.Однако вы вызываете vector_find с передачей char * в качестве второго параметра, который затем передается cmp.Попытка использовать char * в качестве char ** вызывает неопределенное поведение при переходе к strcmp на самом деле char.

Вы не показываете, как заполняете свой vector,но я предполагаю, что элементы data имеют тип char *.В этом случае функция сравнения должна ожидать char * вместо char **.

int cstring_cmp(const void *a, const void *b)
{
    const char *ia = a;
    const char *ib = b;
    printf("%s    %s", ia, ib);
    return strcmp(ia, ib);
}
0 голосов
/ 18 февраля 2019

Если я правильно понял, вы написали компаратор, который притворяется, что vector - это const char*.Это не так.Последующее сравнение C-строк, скорее всего, не достигнет потенциального нулевого терминатора и будет выходить за пределы.

Вместо этого напишите компаратор, который фактически сравнивает vector объекты с тем, что выхочу сравнить их с.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...