0

I am working on this code where you'll need to compare last names and first names and swap them in alphabetical order. I got that right but when I need to find the name and print that using my binary search function searching for the last name it will not print out the correct data or record. It will print a different name record. I am using pointers and calling functions. Please help. (int main()) was already provided

struct _student
{
    char firstname[16];
    char lastname[16];
    char address[32];
    char city[24];
    char county[24];
    char state[3];
    char zip[9];
    char phone[16];
    char email[36];
};
typedef struct _student Student;

void swap(Student* s1, Student* s2)
{
    Student Swap;
    Swap = *s1;
    *s1 = *s2;
    *s2 = Swap;
}

int nameCmp(Student* s1, Student* s2)
{
    int result1 = strcmp(s1->lastname, s2->lastname);
    int result2 = strcmp(s1->firstname, s2->firstname);

    if (result1 < 0)
    {
        return -1;
    }
    else if (result1 == 0)
    {
        if (result2 < 0)
        {
            return -1;
        }
        else if (result2 == 0)
        {
            return 0;
        }

        return 0;
    }
    else
    {
        return 1;
    }
}

void exchangeSort(Student s[], int count, int (*compare)(Student*, Student*))
{
    
    for (int i = 0; i < count - 1; i++)
    {
        for (int j = i + 1; j < count; j++)
        {
            if (compare(&s[i], &s[j]) > 0)
            {
                swap(&s[i], &s[j]);
            }
        }
    }
}

int bSearch(Student data[], int count, char name[], int (*compare)(Student*, Student*))
{
    int low = 0, high = count - 1;
    while (low <= high)
    {
        int mid = (high + low) / 2;
        int cmp = compare(name, &data[mid]);
        if (cmp == 0)
            return mid;
        if (cmp > 0)
        high = mid - 1; 
        else
        low = mid + 1;  
    }

}

int readRowFromFile(FILE* f, Student* s)
{
    memset(s, 0, sizeof(Student));
    return fscanf(f, " %[^,], %[^,], %[^,], %[^,], %[^,], %[^,], %[^,], %[^,], %s\n",
        s->firstname, s->lastname, s->address, s->city, s->county, s->state, s->zip, s->phone, s->email);
}

// Main routine
int main()
{
    // Variable to hold the print format string
    char* fmt = "%-12s%-16s%-32s%-20s%-3s%-6s%-24s\n";

    // Declare an array variable to hold all the records
    Student rData[1000];

    // Open the file for reading, MAKE SURE THE FILE NAME MATCHES WHAT YOU HAVE
    FILE* f = fopen("Samplerecords.csv", "rt");
    if (!f)
    {
        printf("Unable to open file. \n");
        keypress();
        return 0;
    }

    // Variable to hold the number of records actually read
    int count = 0;

    // Skip the header row
    int rc = readRowFromFile(f, &rData[0]);

    // Read the rest of the file
    while (!feof(f) && count < 1000)
    {
        rc = readRowFromFile(f, &rData[count]);
        if (rc > 0)
            count++;
    }

    // Close the file
    fclose(f);

    // Print the first 10 records before sorting
    printf("Before sorting:\n");
    for (int i = 0; i < 10; i++)
    {
        printf(fmt, rData[i].firstname, rData[i].lastname,
            rData[i].address, rData[i].city, rData[i].state, rData[i].zip, rData[i].email);
    }

    // Sort the records by name
    exchangeSort(rData, count, nameCmp);

    // Print the first 10 records after sorting
    printf("\n\nAfter name sort:\n");
    for (int i = 0; i < 10; i++)
    {
        printf(fmt, rData[i].firstname, rData[i].lastname,
            rData[i].address, rData[i].city, rData[i].state, rData[i].zip, rData[i].email);
    }

    // Find the index of the record of "Bernardo Figueroa" (search last name only)
    int index = bSearch(rData, count, "Figeroa", nameCmp);
    if (index >= 0)
    {
        printf("\nFound:\n");
        printf(fmt, rData[index].firstname, rData[index].lastname,
            rData[index].address, rData[index].city, rData[index].state, rData[index].zip, rData[index].email);
    }
    else
    {
        printf("\nRecord not found\n");
    }

    keypress();
    return 0;
}

Output

Chris
  • 26,361
  • 5
  • 21
  • 42
  • 1
    Please provide complete code as a [mre]. That is, include `main`, `#include`s, all type definitions (such as `Stduent`) and any other code needed to make it complete so that others can run it to see the exact problem. – kaylum Nov 07 '21 at 03:38
  • Thunder Thigh, who or what text suggested using `!feof(f)`? – chux - Reinstate Monica Nov 07 '21 at 03:42
  • 1
    The last `return 0` inside `else if (result1 == 0)` looks to be wrong. It means it will return 0 for the case that `result1==0 && result2 > 0` – kaylum Nov 07 '21 at 03:43
  • 1
    @chux-ReinstateMonica teacher provided for us the main so were not supposed to touch that part the only code we have to work on is the swap, nameCmp, exchange, and binary. I am having problems with my binary – Thunder Thigh Nov 07 '21 at 03:44
  • 1
    Your compare function expects two students, but `int cmp = compare(name, &data[mid]);` passes a string and a student. – Retired Ninja Nov 07 '21 at 03:45
  • `fscanf(f, " %[^,], %[^,], %[^,], %[^,], %[^,], %[^,], %[^,], %[^,], %s\n",` risk undefined behavior as all of these specifiers deserve a width limit. – chux - Reinstate Monica Nov 07 '21 at 03:45
  • @kaylum still getting the same problem. It's not finding the certain name I need even if i delete the last return 0; – Thunder Thigh Nov 07 '21 at 03:45
  • I guessed as much. There are probably multiple problems in your code. Have you made an attempt to debug it? If so, what did you find? Where do things *first* go wrong? – kaylum Nov 07 '21 at 03:46
  • @RetiredNinja what should I do to compare the last names and find the last name I am looking for – Thunder Thigh Nov 07 '21 at 03:47
  • 1
    Thunder Thigh, "teacher provided for us the main so were not supposed to touch that part the only code" -->> know that teacher is providing a weak approach. Better to test the return value of `fscanf() == 9` and [**not** `feof()`](https://stackoverflow.com/q/5431941/2410359).. – chux - Reinstate Monica Nov 07 '21 at 03:47
  • If you are simply looking to match a last name then you need a different compare function that does that. What happens if there are multiple students with the same last name? Do you just match the first you find? – Retired Ninja Nov 07 '21 at 03:51
  • @RetiredNinja how can I fix that? Bc in our compare function it needs to search for the last name first so if both last name are the same than it will search the first name and swap whichever name goes first in alphabetical order – Thunder Thigh Nov 07 '21 at 04:13
  • @kaylum for some reason when I debugging it it is skipping over my return mid; in my binary search – Thunder Thigh Nov 07 '21 at 04:14
  • Your name comparison function is sub-optimal. It shouldn't compare the `firstname` fields until it knows that the `lastname` fields are equal. You should avoid the bushy decision tree too: `if (result1 > 0) return +1; else if result1 < 0) return -1; else return strcmp(s1->firstname, s2->firstname);` – Jonathan Leffler Nov 07 '21 at 05:22
  • Your compiler should have produced at least one warning. – n. m. could be an AI Nov 07 '21 at 06:14

1 Answers1

0

The first thing you need to learn is to set a high warning level for your compiler and then fix all warnings before you run the program.

For gcc you can use the flags -Wall -Wextra and maybe also -Werror. When I compile your code with the flags -Wall -Wextra, I get:

main.cpp: In function 'bSearch':
main.cpp:132:27: warning: passing argument 1 of 'compare' from incompatible pointer type [-Wincompatible-pointer-types]
  132 |         int cmp = compare(name, &data[mid]);
      |                           ^~~~
      |                           |
      |                           char *
main.cpp:132:27: note: expected 'Student *' {aka 'struct _student *'} but argument is of type 'char *'
main.cpp:141:1: warning: control reaches end of non-void function [-Wreturn-type]
  141 | }
      | ^

These two warnings tells all about bugs in your code, i.e.

  1. Your compare function can't be used for comparing a Student with a string

  2. The bSearch function is missing a return when no match is found

Further, notice that the search is supposed to look for last name only but your nameCmp looks at both first and last name. So you need another compare function for the search.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • I am sorry I am new to coding. I get that it needs to be a structure for compare(name, &data[mid]) but when we call the function in main it is using the char to search for Figeroa how do I convert the char to a Structure – Thunder Thigh Nov 07 '21 at 17:09