Thread: Problem Using bsearch

  1. #1
    Registered User
    Join Date
    Sep 2003
    Posts
    69

    Problem Using bsearch

    Hello,

    I'm currently working on an assignment where I have to take in names from stdin, put them in an array of structs (where each struct has a name and a number), and then qsort that array. Then, I have to use bsearch to search for names (from a file provided as a command-line argument) and then output the number associated with the name. Here is my code:

    Code:
     #include <stdio.h>
     #include <string.h>
     #include <stdlib.h>
     
     #define MAX_PERSON 100
     #define MAX_NAME 10
     
     struct person {
        char name[MAX_NAME];
        int num;
     };
     
     int compare(const void *p, const void *s) {
        return strcmp(((struct person*)p)->name, ((struct person*)s)->name);
     }
     
     int compare2(const void *p, const void *s) {
        return strcmp((char *)p, ((struct person*)s)->name);
     }
     
     main(int argc, char *argv[]) {
        char buf[BUFSIZ];
        char *tok;
        char *result;
        char lookup[3];
        int lineNum = 1;
        int pos = 0;
        int i;
        FILE *fp;
        struct person people[MAX_PERSON];
        struct person *match;
        
        while ( fgets(buf,BUFSIZ,stdin) != NULL ) {
           tok = strtok(buf," ");
           strcpy(people[pos].name,tok);
           people[pos].num = lineNum;
           pos++;
           tok = strtok(NULL,"\n");
           strcpy(people[pos].name,tok);
           people[pos].num = lineNum;
           pos++;
           lineNum++;
        }
        
        qsort(people,pos,sizeof(struct person), compare);
        
        if ( (fp = fopen(argv[1],"r")) == NULL) {
           fprintf(stderr,"Cannot open %s\n",argv[1]);
           exit(1);
        }
        
        while ( fgets(buf,BUFSIZ,fp) != NULL ) {
           tok = strtok(buf," ");
           strncpy(lookup,tok,3);
           match = (struct person*)bsearch(lookup,people,pos,sizeof(struct person),compare2);
           printf("%s",match->name);
        }
           
           
        for (i = 0; i < pos; i++) {
           printf("%s %d\n", people[i].name,people[i].num);
        }
     }
    I seem to be getting a segmentation fault from the printf statement in the while loop. That is just there for testing purposes. Am I even using bsearch correctly? My compare2 function might be incorrect, but I don't even know if the whole thing is correct. Please help! Oh, I used strncpy with 3 because each name will only have 3 letters in them and the lines of names from the CLA file have the first name as Ann: Bill Bob and so on. So, I used strncpy to get rid of the colon and any end of line characters.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Am I even using bsearch correctly?
    I would suggest that's a NO

    Normally, I would do
    struct person lookup;

    and copy the appropriate information from the user into this structure.

    This means you can use compare() as the search function and get rid of compare2() altogether. At the very least, you don't have to worry whether lookup is passed to compare() as the first or second parameter.

    > strncpy(lookup,tok,3);
    Here's another mistake - this doesn't mean that it has a \0 on the end to make it a proper string.

    > I seem to be getting a segmentation fault from the printf statement
    Have you printed the sorted array just to verify that the array is in fact sorted correctly.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2003
    Posts
    69
    Yes, the array does get sorted correctly. So what you're saying to do is take tok and go strcpy(lookup.name,tok) and then use the same code for bsearch but replace compare2 with compare? Do I have to do any casting to whatever bsearch returns? Or will it return a pointer to a struct person no matter what?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Sounds about right to me

    You shouldn't need to cast anything
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Does this help?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct person
    {
       char name[32];
       int  num;
    };
    
    int cmp_name(const void *a, const void *b)
    {
       const struct person *x = a, *y = b;
       return strcmp(x->name, y->name);
    }
    
    int cmp_num(const void *a, const void *b)
    {
       const struct person *x = a, *y = b;
       return (x->num > y->num) - (x->num < y->num);
    }
    
    void display(const char *label, const struct person *p, size_t size)
    {
       puts(label);
       for ( ; size--; ++p )
       {
          printf("name = \"%s\", num = %d\n", p->name, p->num);
       }
       putchar('\n');
    }
    
    int main(void)
    {
       struct person *found, key, in[] =
       {
          {"Fred", 7},
          {"Anne", 4},
          {"Paul", 3},
          {"Judy", 6},
          {"Jeff", 5},
          {"Jose", 1},
          {"Vlad", 2},
       };
       size_t count = sizeof in / sizeof *in; /* number of records */
       display("Unsorted:", in, count);
       /*
        * Search for a particular 'name'. Make sure the array is sorted by 'name'.
        */
       qsort(in, count, sizeof *in, cmp_name);
       display("Sorted by 'name':", in, count);
    
       strcpy(key.name, "Jeff");
       printf("Searching for 'name' = \"%s\"... ", key.name);
       found = bsearch(&key, in, count, sizeof *in, cmp_name);
       if ( found )
       {
          printf("'num' = %d\n\n", found->num);
       }
       else
       {
          puts("not found.\n");
       }
       /*
        * Search for a particular 'num'. Make sure the array is sorted by 'num'.
        */
       qsort(in, count, sizeof *in, cmp_num);
       display("Sorted by 'num':", in, count);
    
       key.num = 3;
       printf("Searching for 'num' = %d... ", key.num);
       found = bsearch(&key, in, count, sizeof *in, cmp_num);
       if ( found )
       {
          printf("'name' = \"%s\".\n\n", found->name);
       }
       else
       {
          puts("not found.\n");
       }
       return 0;
    }
    
    /* my output
    Unsorted:
    name = "Fred", num = 7
    name = "Anne", num = 4
    name = "Paul", num = 3
    name = "Judy", num = 6
    name = "Jeff", num = 5
    name = "Jose", num = 1
    name = "Vlad", num = 2
    
    Sorted by 'name':
    name = "Anne", num = 4
    name = "Fred", num = 7
    name = "Jeff", num = 5
    name = "Jose", num = 1
    name = "Judy", num = 6
    name = "Paul", num = 3
    name = "Vlad", num = 2
    
    Searching for 'name' = "Jeff"... 'num' = 5
    
    Sorted by 'num':
    name = "Jose", num = 1
    name = "Vlad", num = 2
    name = "Paul", num = 3
    name = "Anne", num = 4
    name = "Jeff", num = 5
    name = "Judy", num = 6
    name = "Fred", num = 7
    
    Searching for 'num' = 3... 'name' = "Paul".
    */
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help understanding a problem
    By dnguyen1022 in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2009, 04:21 PM
  2. Memory problem with Borland C 3.1
    By AZ1699 in forum C Programming
    Replies: 16
    Last Post: 11-16-2007, 11:22 AM
  3. Someone having same problem with Code Block?
    By ofayto in forum C++ Programming
    Replies: 1
    Last Post: 07-12-2007, 08:38 AM
  4. A question related to strcmp
    By meili100 in forum C++ Programming
    Replies: 6
    Last Post: 07-07-2007, 02:51 PM
  5. WS_POPUP, continuation of old problem
    By blurrymadness in forum Windows Programming
    Replies: 1
    Last Post: 04-20-2007, 06:54 PM