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 );