0

Ok so im stuck on the tabulate funtion in runoff for pset3.

The issue im having is that when i call to "printf" the candidates vote counts the votes still come out as 0. So i dont think the votes are being tabulated at all.

So far here's where i THINK i am in regards to knowledge and what my code is doing (or supposed to be doing) and please feel free to correct me so I can improve.

  • If I execute loops within loops, it allows me to build / itereate over / access data within a 2 dimentional array.
  • The vote function is called into action via the line "if (!vote(i, j, name))"
  • This line of code is executed within the 2nd dimention (attempting to populate the voters preferences) Therefore when writing the " vote " function I dont need to execute 2 loops to iterate over the 2nd dimention of the array I am attempting to populate.
  • " preferences[voter][rank] = i " therefore is populated like so -> [voter] is populated via the i'th for loop within main, and [rank] is populated via the i'th for loop within vote
  • For the tabulate function. I establish 2 loops to access the second dimention of the "candidates" array. Then once confirming that the name passing through the vote function is true and not eliminated, the programme adds one vote to the appropriate candidate.

Below is the code I have so far for the problem, all help is appreciated:

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

  // Max voters and candidates
  #define MAX_VOTERS 100
  #define MAX_CANDIDATES 9

  // preferences[i][j] is jth preference for voter i
  int preferences[MAX_VOTERS][MAX_CANDIDATES];

  // Candidates have name, vote count, eliminated status
  typedef struct
  {
      string name;
      int votes;
      bool eliminated;
  }
  candidate;

  // Array of candidates
  candidate candidates[MAX_CANDIDATES];

  // Numbers of voters and candidates
  int voter_count;
  int candidate_count;

  // Function prototypes
  bool vote(int voter, int rank, string name);
  void tabulate(void);
  bool print_winner(void);
  int find_min(void);
  bool is_tie(int min);
  void eliminate(int min);

  int main(int argc, string argv[])
  {
    // Check for invalid usage
    if (argc < 2)
    {
        printf("Usage: runoff [candidate ...]\n");
        return 1;
    }
    // Populate array of candidates
    candidate_count = argc - 1;
    if (candidate_count > MAX_CANDIDATES)
    {
        printf("Maximum number of candidates is %i\n", MAX_CANDIDATES);
        return 2;
    }
    for (int i = 0; i < candidate_count; i++)
    {
        candidates[i].name = argv[i + 1];
        candidates[i].votes = 0;
        candidates[i].eliminated = false;
    }

    voter_count = get_int("Number of voters: ");
    if (voter_count > MAX_VOTERS)
    {
        printf("Maximum number of voters is %i\n", MAX_VOTERS);
        return 3;
    }

    // Keep querying for votes
    for (int i = 0; i < voter_count; i++)
    {

        // Query for each rank
        for (int j = 0; j < candidate_count; j++)
        {
            string name = get_string("Rank %i: ", j + 1);

            // Record vote, unless it's invalid
            if (!vote(i, j, name))
            {
                printf("Invalid vote.\n");
                return 4;
            }
        }

        printf("\n");
    }

    for (int j = 0; j < candidate_count; j++)
    {
        printf("candidate: %s\n votes:%d\n", candidates[j].name, candidates[j].votes);
    }


    // Keep holding runoffs until winner exists
    while (true)
    {
        // Calculate votes given remaining candidates
        tabulate();

        // Check if election has been won
        bool won = print_winner();
        if (won)
        {
            break;
        }

        // Eliminate last-place candidates
        int min = find_min();
        bool tie = is_tie(min);

        // If tie, everyone wins
        if (tie)
        {
            for (int i = 0; i < candidate_count; i++)
            {
                if (!candidates[i].eliminated)
                {
                    printf("%s\n", candidates[i].name);
                }
            }
            break;
        }

        // Eliminate anyone with minimum number of votes
        eliminate(min);

        // Reset vote counts back to zero
        for (int i = 0; i < candidate_count; i++)
        {
            candidates[i].votes = 0;
        }
    }
    return 0;
    }

    // Record preference if vote is valid
    bool vote(int voter, int rank, string name)
    {
    // Iterate over the number of candidates
        for(int i = 0; i < candidate_count; i++)
        {

            //Check if any of the name entered by the user matches any of the candidates names
            if (strcmp(name, candidates[i].name) == 0)
            {
                preferences[voter][rank] = i;
                return true;
                break;
            }
        }

        return false;
    }

   // Tabulate votes for non-eliminated candidates
    void tabulate(void)
    {
      // Iterate over the number of candidates to find 'true' votes

    for(int i = 0; i > voter_count; i++)
    {

        for (int j = 0; j > candidate_count; j++)

        if (candidates[preferences[i][j]].eliminated == false)
        {
            candidates[preferences[i][j]].votes++;
            return;
        }
    }

    return;
    }

This code gives the following results:

~/Week_3/pset3/runoff/ $ ./runoff james john
Number of voters: 2
Rank 1: james
Rank 2: john

Rank 1: james
Rank 2: john

candidate: james
 votes:0

candidate: john
 votes:0
1

One problem I see:

In tabulate() for(int i = 0; i > voter_count; i++) I think you meant to write i < voter_count because otherwise it will not enter the loop since your condition will turn out to be 0 > 2

The same holds true for the next loop as well: for (int j = 0; j > candidate_count; j++). Here too, change j > candidate_count to j < candidate_count to enter the loop.

You can revisit the problem after this first step.

Update in response to comment:

I don’t think tabulate() is giving the same result. After you have made the correction from > to < you will find that vote is incremented. You may want to verify this using debug50.

The next problem I see is that it appears to return immediately after incrementing the votes count (just once perhaps):-

candidates[preferences[i][j]].votes++;
return;

Another observation: In vote() break will not get executed since it is after return:-

preferences[voter][rank] = i;
return true;
break;

I am only trying to get you one step forward and you might want to use the debugger. It can provide you information for every iteration much better than I can in an answer here.

Also, personally, I find it useful to manually execute each iteration and note down the value of the variable as I go along.

| improve this answer | |
  • thanks for spotting this. Unfortunatley even with these corrections it gives the same result and does not count the votes. – Pot Noodle Aug 3 at 5:42

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .