【问题标题】:CS50 - week 3 - runoff -My code has a issueCS50 - 第 3 周 - 决赛 - 我的代码有问题
【发布时间】:2022-12-11 04:28:49
【问题描述】:

这是我在 cs50 的第 3 周作业中为 print_winner 函数想出的代码,径流。 这是我的 print_winner 函数。

Print_winner

它会产生一些奇怪的行为。当候选人获得 100% 的选票作为排名 1 时,代码工作正常。但除此之外,代码只会不断重复。我必须使用 Ctr + c 来停止执行。

例如 - ./runoff aa bb cc

如果我将所有第一名的 100% 都给“cc”,它会将获胜者正确打印为“cc”。

1

但是,如果我给出假设,如果我将 2/3 的选票投给 cc,将一票投给另一票,te 代码将继续循环。

enter image description here

请提供任何帮助,我们将不胜感激。 这是我的完整代码。

#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;
        //debug
        printf("candidate %d %s \n", i,candidates[i].name);
    }

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

    //debug -vidu
    for (int ss = 0; ss < voter_count; ss++)
    {
        for (int tt = 0; tt < 3; tt++)
        {
            printf("voter - %d, rank - %d, candidate no - %d \n" , ss, tt, preferences[ss][tt]);
        }
    }

    // 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)
{
    // TODO //take all these details and enter them to the grid
    int count = 0;
    if (voter < voter_count && rank < 3)
    {
        for (int i = 0; i < candidate_count; i++)
        {
            //debug
            printf("--name - %s,\n--candidate.name - %s \n", name, candidates[i].name);

            if (strcmp(name, candidates[i].name) == 0)
            {
                preferences[voter][rank] = i;

                //debug - print
                printf("voter - %d, rank - %d, total votes - %d, %s \n", voter, rank, i, candidates[i].name);

                count = count + 1;

                return true;
                break;
            }
        }

        return false;
    }

    else
    {
        return false;
    }

}

// Tabulate votes for non-eliminated candidates
void tabulate(void)
{
    // TODO //take votes from preferences and put it to the candidates

    for (int i = 0; i < voter_count; i++)
    {
        for (int j = 0; j < candidate_count; j++)
        {
            //check for the index no of preferences first candidate
            if (preferences[i][0] == j && candidates[j].eliminated == false)
            {
                candidates[j].votes = candidates[j].votes + 1;
            }
        }

    }
    //debug = print the canditate table
    for (int k = 0; k < candidate_count; k++)
    {
        printf("DEBUG in vote = Candid name - %s, Index no - %d, votes - %d \n",candidates[k].name, k,candidates[k].votes);
    }

    return;
}

// Print the winner of the election, if there is one
bool print_winner(void)
{
    // TODO //If any candidate has more than half of the vote, their name should be printed and the function should return//if not false
    //debug = print the canditate table
    for (int k = 0; k < candidate_count; k++)
    {
        printf("DEBUG in print_winner = Candid name - %s, Index no - %d, votes - %d \n",candidates[k].name, k,candidates[k].votes);
    }

    int kk = 0;

    //devide by total and
    for (int j=0; j < candidate_count; j++)
    {
        kk = candidates[j].votes/voter_count * 100;
        //debug
        printf("candidate %d candidates[j].votes - %d \n", j, candidates[j].votes);
        printf("candidate %d kk - %d \n", j, kk);
        if (kk > 50)
        {
            printf("the winner is %s \n", candidates[j].name);
            return true;
        }
    }
    return false;
}

// Return the minimum number of votes any remaining candidate has
int find_min(void)
{
    // TODO
    //bubble sort
    for (int step = 0; step < candidate_count; step++)
    {
        // loop to compare array elements
        for (int i = 0; i < (candidate_count - 1); i++)
        {
            // compare two adjacent elements, change > to < to sort in descending order
            if (candidates[i].votes > candidates[i + 1].votes)
            {
                // swapping occurs if elements are not in the intended order
                candidate temp = candidates[i];
                candidates[i] = candidates[i + 1];
                candidates[i + 1] = temp;
            }
        }
    }

    return candidates[0].votes;

}

// Return true if the election is tied between all candidates, false otherwise
bool is_tie(int min)
{
    // TODO
    for (int i=0; i < candidate_count; i++)
    {
        if (candidates[i].votes == candidates[i + 1].votes && candidates[i].votes == min && candidates[i].votes == candidates[candidate_count].votes)
        {
            return true;
        }
    }

    return false;
}

// Eliminate the candidate (or candidates) in last place
void eliminate(int min)
{
    // TODO
    for (int i=0; i < candidate_count; i++)
    {
        if (candidates[i].votes == min)
        {
            candidates[i].eliminated = true;
        }
    }
    return;
}

【问题讨论】:

  • 这可能是我第一次看到有人为 cs50 发布阅读起来并不痛苦的代码!做得好。这似乎是一个微不足道的细节,但您确实应该养成将错误消息写入 stderr 的习惯。现在看起来这并不重要,因为您可能将 stdout 和 stderr 都发送到同一个地方,但是您应该将错误消息发送到 stderr 的想法内化。例如fprintf(stderr, "Invalid vote.\n");
  • votesvoter_count 都是int。所以candidates[j].votes/voter_count 是一个int。除非候选人获得所有选票(除非存在大量选民欺诈!),否则分母始终大于分子,因此candidates[j].votes/voter_count 始终为零。

标签: c computer-science cs50


【解决方案1】:

可能还有其他问题,但跳出的一个是:

kk = candidates[j].votes/voter_count * 100;

由于右侧的两个变量都是int类型,所以除法是整数除法。由于voter_count 始终大于或等于candidates[j].votes,因此kk 的值始终是0100。要获得浮点结果,您可以使用:

kk = ((double)candidates[j].votes / (double)voter_count) * 100;

(两个演员表都不是绝对必要的,外括号也不是;这是一种风格选择。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-23
    • 2017-12-20
    • 2021-08-05
    • 1970-01-01
    相关资源
    最近更新 更多