mushroom_man
mushroom_man

Reputation: 1

(C) Finding struct by name in struct array with bsearch

I'm trying to implement function (1) for finding a specific Product by name in struct array. p_array is the struct array containing n number of Products, search_key is pointer to a string with the name of the searched structure cmp is pointer to another function (2) that I have implemented.

/* (1) */
const Product* findProduct(const Product* p_array, const char* search_key, int (*cmp)(const void*, const void*))
{
    return bsearch(&search_key, p_array, 100, sizeof(Product), cmp);
    
}

/* (2) */
int compareAlpha(const void* a, const void* b)
{
    const struct Product *shop_a = a;
    const struct Product *shop_b = b;

    int ret = strcmp(shop_a->name,shop_b->name);
    
    return ret;
}

I have the following problems:

  1. I can't think of a way to find out the length of p_array
  2. Launching the program results in segmention fault and I can't figure out why

My main function is:

void printProducts(Product* array)
{
    int i = 0;
    while(array[i].name[0] != 0)
    {
        printf("product: %s\tprice: %f\t in stock: %d\n", array[i].name, array[i].price, array[i].in_stock);
        i++;
    }
}

int main()
{
    Product array[6] = {
    {"peanut butter", 1.2,  5},
    {"cookies",      12.3, 23},
    {"cereals",       3.2, 12},
    {"bread",     2.7, 12},
    {"butter",    4.2,  5},
    {"\0",      0.0, 0}
    };

    qsort(array, 5, sizeof(Product), compareAlpha);
    printf("sorted lexically:\n");
    printProducts(array);
    
    const Product* search = findProduct(array, "cookies", compareAlpha);
    if(search)
    {
        printf("Found product:\n");
        printf("%s\n", search->name);
    }

    qsort(array, 5, sizeof(Product), compareNum);
    printf("sorted by in stock:\n");
    printProducts(array);

    return 0;
}

And the wanted output is

sorted lexically:
product: bread price: 2.700000 in stock: 12
product: butter price: 4.200000 in stock: 5
product: cereals price: 3.200000 in stock: 12
product: cookies price: 12.300000 in stock: 23
product: peanut butter price: 1.200000 in stock: 5
Found product:
cookies
Product not found!
sorted by in stock:
product: cookies price: 12.300000 in stock: 23
product: bread price: 2.700000 in stock: 12
product: cereals price: 3.200000 in stock: 12
product: butter price: 4.200000 in stock: 5
product: peanut butter price: 1.200000 in stock: 5

Upvotes: 0

Views: 473

Answers (1)

risingStark
risingStark

Reputation: 1155

You have several errors in your code:

  1. conversion not possible in your compareAlpha() function. You should instead write const struct Product* shop_a = (const struct Product*)a;
  2. In your printProducts() function, you should compare the array[i].name[0] to null character '\0' instead of 0 i.e., while(array[i].name[0] != '\0')
  3. Passing the parameter array in printProducts() function, generates a warning. You declared the array as a static array not as a pointer (although it is inherently implemented and can be accessed as a pointer) which generates a warning. You should instead pass it like this void printProducts(Product array[]).
  4. In the findProduct() function, when you call the bsearch() function, you pass the parameter to search as &search_key. You should instead pass it without &.
  5. The return type of findProduct() should be void* and not const Product* because the return type of bsearch() function is void*. So, after you get a return value from findProduct() function, you need to typecast it to const Product*.
  6. You have not used struct keyword while using Product type in some places. In c++, it is optional but in C it is mandatory.

  1. I can't think of a way to find out the length of p_array

You can find the size of the array like this int size = sizeof(array) / sizeof(array[0]); although it is not recommended because it is compiler dependent.


  1. Launching the program results in segmention fault and I can't figure out why

Below is the fully working code with all the above-mentioned errors/warnings rectified.

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

struct Product{
    char name[100];
    double price;
    int in_stock;
};

int compareAlpha(const void* a, const void* b)
{
    const struct Product* shop_a = (const struct Product*)a;
    const struct Product* shop_b = (const struct Product*)b;

    int ret = strcmp(shop_a->name, shop_b->name);

    return ret;
}

int compareNum(const void* a, const void* b)
{
    const struct Product* shop_a = (const struct Product*)a;
    const struct Product* shop_b = (const struct Product*)b;

    int ret = shop_a->in_stock <= shop_b->in_stock;

    return ret;
}

void* findProduct(struct Product p_array[], const char* search_key, int (*cmp)(const void*, const void*))
{
    return bsearch(search_key, (void*)p_array, 5, sizeof(struct Product), cmp);

}



void printProducts(struct Product array[])
{
    int i = 0;
    while(array[i].name[0] != '\0')
    {
        printf("product: %s\tprice: %f\t in stock: %d\n", array[i].name, array[i].price, array[i].in_stock);
        i++;
    }
}

int main()
{
    struct Product array[6] = {
        {"peanut butter", 1.2,  5},
        {"cookies",      12.3, 23},
        {"cereals",       3.2, 12},
        {"bread",     2.7, 12},
        {"butter",    4.2,  5},
        {"\0",      0.0, 0}
    };

    qsort(array, 5, sizeof(struct Product), compareAlpha);
    printf("sorted lexically:\n");
    printProducts(array);

    const struct Product* search = (const struct Product*)findProduct(array, "cookies", compareAlpha);
    if(search)
    {
        printf("Found product:\n");
        printf("%s\n", search->name);
    }else{
        printf("Product not found!\n");
    }

    qsort(array, 5, sizeof(struct Product), compareNum);
    printf("sorted by in stock:\n");
    printProducts(array);

    return 0;
}

Upvotes: 2

Related Questions