Home > Software engineering >  error: member reference base type 'candidate[9]' is not a structure or union mergesort(can
error: member reference base type 'candidate[9]' is not a structure or union mergesort(can

Time:08-21

I am a beginner in programming. Currently following the CS50 course on edx. I am on week 3 and have to program a simple vote counter but I am getting the following error on line 65

plurality.c:65:25: error: member reference base type 'candidate[9]' is not a structure or union mergesort(candidates.votes, 0, MAX-1, candidates.name);

But my candidates.votes and candidates.name is an array no? Please help me out on this I just have no idea how to solve it.

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

void merge(int a[], int low, int mid, int high); //This function will merge the two sorted arrays
void mergesort(int a[], int low, int high, string name[]); //This function will merge the arrays, is recursive

// Max number of candidates
#define MAX 9

// Candidates have name and vote count
typedef struct
{
    string name;
    int votes;
}
candidate;

// Array of candidates
candidate candidates[MAX];

// Number of candidates
int candidate_count;

// Function prototypes
bool vote(string name);
void print_winner(void);

int main(int argc, string argv[])
{
    // Check for invalid usage
    if (argc < 2)
    {
        printf("Usage: plurality [candidate ...]\n");
        return 1;
    }

    // Populate array of candidates
    candidate_count = argc - 1;
    if (candidate_count > MAX)
    {
        printf("Maximum number of candidates is %i\n", MAX);
        return 2;
    }
    for (int i = 0; i < candidate_count; i  )
    {
        candidates[i].name = argv[i   1];
        candidates[i].votes = 0;
    }

    int voter_count = get_int("Number of voters: ");

    // Loop over all voters
    for (int i = 0; i < voter_count; i  )
    {
        string name = get_string("Vote: ");

        // Check for invalid vote
        if (!vote(name))
        {
            printf("Invalid vote.\n");
        }
    }

    mergesort(candidates.votes, 0, MAX-1, candidates.name);

    // Display winner of election
    print_winner();
}

// Update vote totals given a new vote
bool vote(string name)
{
    // TODO
    for(int i =0; i< MAX; i  )
    {
        if(candidates[i].name == name)
        {
            candidates[i].votes  ;
            return true;
        }
    }
    return false;
}

// Print the winner (or winners) of the election
void print_winner(void)
{
    // TODO
    int win = candidates.votes[MAX-1]
    for(int i = MAX-2; i >=0; i--)
    {
        if(win != candidates[i].votes)
        {
            printf("%s",candidates[i].name);
            return;
        } else
        {
            printf("%s", candidates[i].name);
            win = candidates[i].votes;
        }
    }
    return;
}

void mergesort(int a[], int low, int high, string name[])
{
    int mid;
    if(low < high)
    {
        mid = (low   high) / 2;
        mergesort(a, low, mid);
        mergesort(a, mid 1, high);
        merge(a, low, mid, high, string name);
    }
    else
    {
        return;
    }
}

void merge(int a[], int low, int mid, int high, string name)
{
    int i, j, k, b[high], c[high];
    i = low;
    j = mid   1;
    k = low;

    while(i <= mid && j <= high )
    {
        if(a[i] < a[j])
        {
            b[k] = a[i];
            c[k] = name[i];
            i  ;
            k  ;

        }
        else
        {
            b[k] = a[j];
            c[k] = name[j];
          //  printf("%i ", b[k]);
            j  ;
            k  ;

        }
    }
    while(i <= mid)
    {
        b[k] = a[i];
        c[k] = name[j];
        //printf("%i ", b[k]);
        k  ;
        i  ;

    }
    while(j <= high)
    {
        //printf("%i ", b[k]);
        b[k] = a[j];
        c[k] = name[j];
        k  ;
        j  ;

    }

    for(i = low; i <= high ; i  )
    {
        a[i] = b[i];
        name[i] = c[i];
       // printf("%i", a[i]);
    }

}

CodePudding user response:

You have declared your candidates array as:

candidate candidates[MAX];

Yet you are trying to access the votes and name members on the array itself rather than an individual element.

mergesort(candidates.votes, 0, MAX-1, candidates.name);

From the signature of mergesort:

void mergesort(int a[], int low, int high, string name[])

It would appear you need to collect the votes and name values for each member of the array into new arrays and then pass those to the function.

int votes[MAX];
for (size_t i = 0; i < MAX; i  ) {
    votes[i] = candidates[i].votes;
}

CodePudding user response:

You have at least two problems (maybe more but I don't have the cs50 headers to compile):

Don't compare strings with ==

if(candidates[i].name == name)

Instead, use strcmp:

if(strcmp(candidates[i].name, name) == 0)

And the main problem: If you don't have an array of ints and strings, you can not pass them to a function.

typedef struct
{
    string name;
    int votes;
}
candidate;

// Array of candidates
candidate candidates[MAX];

...

mergesort(candidates.votes, 0, MAX-1, candidates.name);

candidates.votes and candidates.name are not arrays, you need to pass candidates to the mergesort function and instead of

if(a[i] < a[j])

use something like

if(candidates[i].votes < candidates[j].votes)

If the homework doesn't require to implement mergesort, consider using qsort as it will simplify a lot the job:

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

#define MAX 9

// Candidates have name and vote count
typedef struct
{
    char *name;
    int votes;
} candidate;

// Sort by: votes (DESC order), name (ASC order)
int comp(const void *pa, const void *pb)
{
    const candidate *a = pa;
    const candidate *b = pb;

    return
        a->votes > b->votes ? -1 :
        a->votes < b->votes ?  1 :
        strcmp(a->name, b->name);
}

int main(void)
{
    candidate candidates[MAX] =
    {
        {"Ingram", 1}, {"Macias", 5}, {"Sosa", 3}, {"Mayer", 3}, {"Walton", 2},
        {"Christensen", 4}, {"Mckay", 1}, {"Carter", 6}, {"Fitzgerald", 3}
    };

    qsort(candidates, MAX, sizeof(candidate), comp);
    for (size_t i = 0; i < MAX; i  )
    {
        printf("%d %s\n", candidates[i].votes, candidates[i].name);
    }
    return 0;
}

Output:

6 Carter
5 Macias
4 Christensen
3 Fitzgerald
3 Mayer
3 Sosa
2 Walton
1 Ingram
1 Mckay

CodePudding user response:

You can completely delete the merge() and mergesort() code. (No more compiler report or crashing.)

Simply declare a global counter (can't believe I'm suggesting this!)

int maxCnt; // global data value will be 0

Inside vote() add something like this when a candidate's tally increases. (Also corrected the name matching problem.)

if( strcmp( candidates[i].name, name ) == 0 )
{
    candidates[i].votes  ;
    if( maxCnt < candidates[i].votes )
        maxCnt = candidates[i].votes;
    return true;
}

You can then plunge straight into print() because the program already knows the highest tally (that may be shared by multiple candidates.)

printf( "Winner(s): " );
for( int i = 0; i < candidate_cnt; i   )
    if( candidates[i].votes == maxCnt )
        printf( "%s ", candidates[i].name );
printf( "\n" );

And, if a list of all candidates is required (in descending order of votes). This goes through the list first printing the candidates with the highest vote count, but also finds the highest that is less than the current vote count. This repeats until the threshold eventually drops below the last placed candidate.

int nextCnt = 0;
int thisCnt = maxCnt;
do {
    nextCnt = -1;
    for( i = 0; i < candidate_cnt; i   ) {
        int nVotes = candidates[i].votes;

        if( nVotes == thisCnt )
            printf( "%s -- %d\n", candidates[i].name, nVotes );

        if( nVotes < thisCnt && nVotes > nextCnt )
            nextCnt = nVotes;
    }
    thisCnt = nextCnt;
} while( nextCnt >= 0 ); 
  • Related