L.D.Regan
L.D.Regan

Reputation: 1

C linear search error

My lsearch function should find the value 11 in my array. It does not, and I don't know where the error is. Why does this code not find the value 11?

#include <stdio.h>
#include <string.h>
#define PF printf
int main() {
    int intcmp(void *ip1, void * ip2);
    void * lsearch(void *key, void *base, int n, int elemSize, 
                   int(* cmpfun)(void *, void *));
    int arr[] = {4, 6, 2, 3, 11, 22, 15};
    int n = sizeof(arr) / sizeof(int);
    int key = 11;
    int *found = lsearch(&key, &arr, n, sizeof(int), intcmp);
    PF("found=%p", found);
    return 1;
}
int intcmp(void *ip1, void * ip2) {
    int *p1 = ip1;
    int *p2 = ip2;
    return *p1 - *p2 == 0;
}
void * lsearch(void *key, void *base, int n, int elemSize, 
               int(* cmpfun)(void *, void *)) {
    int i;
    for(i = 0; i < n; i ++) {
        void *elemArr = (char *)base + i * elemSize;
        if(cmpfun(key, elemArr) == 0)
            return elemArr;
    }

    return NULL;
}

Upvotes: 0

Views: 270

Answers (2)

Gene
Gene

Reputation: 46960

I have annotated the code below:

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

// This is bad practice. It makes your code less readable.
// I won't use it below.
#define PF printf 

// Declare this first so a prototype is not needed.
// You violated a C pattern by using `cmp` in the name.
// Comparison functions in C return <0, 0, >0, not a binary value.
// To wit, later you used the comparison correctly.  I've fixed the
// inconsistency.
int intcmp(void *vp1, void *vp2) 
{   // Most C styles have the brace on its own line, unlike Java. Roll with it.
    int *p1 = vp1, *p2 = vp2;
    return *p1 - *p2; 
}

// Search n elements of size elemSize in the array at 
// base in sequence using cmpfun on key, 
// to test for equality (cmpfun == 0).  Return a pointer 
// to the found element or NULL if none.
void *lsearch(void *key, void *base, int n, 
              int elemSize, int(* cmpfun)(void *, void *)) 
{ 
    int i; 

    for (i = 0; i < n; i++) { 
        void *elemArr = (char*)base + i * elemSize; 
        if (cmpfun(key, elemArr) == 0) 
            return elemArr;
    } 
    return NULL; 
}

int main() 
{   
    int arr[] = {4, 6, 2, 3, 11, 22, 15}; 
    int n = sizeof(arr) / sizeof(int); 
    int key = 11; 
    int *found = lsearch(&key, &arr, n, sizeof(int), intcmp); 
    printf("found=%p (%d)", found, *(int*)found); 
    return 0; // By convention zero corresponds to no error.
} 

Upvotes: 1

Corbin
Corbin

Reputation: 33447

There's a few oddities in your code (PF and the way the functions is declared in main yet defined globally), however, the problem is that your logic if inverted in a two places.

if(cmpfun(key, elemArr) == 0)
        return elemArr;

And:

return *p1 - *p2 == 0;

Mentally run through that when the two elements are equal. The == expression will return 1 when the number does actually equal the other. 1 != 0 thus it's not considered found.

Either through a negation in there or just return *p1 - *p2; directly.

Upvotes: 4

Related Questions