【问题标题】:check50 on plurality insists that it doesn't work yet everytime i try with my own input it does workcheck50 on multiple 坚持认为每次我尝试使用自己的输入时它都不起作用
【发布时间】:2021-06-22 08:01:10
【问题描述】:

有问题的程序将候选人姓名和选民选择作为输入,输出是获胜者或获胜者的姓名(如果 2 个或多个候选人之间存在平局)。 每当我尝试使用自己的输入时,它都可以正常工作,无论是单个赢家还是多个赢家。 但 check50 不同意。当我使用调试器时,它最后说的是分段错误,但我看不出代码中的错误在哪里。

我无法理解为什么 check50 坚持认为程序不完全正确。 问题所在的代码部分是:

void print_winner(void)
{
    int c = 0;
    int d[(candidate_count - 1)];
    int e = 0;
    for (int i = 1; i < candidate_count; i++)
    {
        if (candidates[c].votes < candidates[i].votes)
        {
            c = i;
        }
        else if (candidates[c].votes == candidates[i].votes)
        {
            d[e] = i;
            e++;
        }
    }

    printf("%s\n", candidates[c].name);
    for(int i = 0; i < (e + 1); i++)
    {
        if(candidates[c].votes == candidates[(d[i])].votes)
        {
            printf("%s\n", candidates[d[i]].name);
        }
    }
    return;
}

结果是:

:) plurality.c exists
:) plurality compiles
:) vote returns true when given name of first candidate
:) vote returns true when given name of middle candidate
:) vote returns true when given name of last candidate
:) vote returns false when given name of invalid candidate
:) vote produces correct counts when all votes are zero
:) vote produces correct counts after some have already voted
:) vote leaves vote counts unchanged when voting for invalid candidate
:) print_winner identifies Alice as winner of election
:) print_winner identifies Bob as winner of election
:) print_winner identifies Charlie as winner of election
:) print_winner prints multiple winners in case of tie
:( print_winner prints all names when all candidates are tied
    print_winner function did not print all three winners of election

【问题讨论】:

  • 不确定,但这个:for(int i = 0; i &lt; (e + 1); i++) 看起来很奇怪。我希望i &lt; e
  • 欢迎来到 SO。分段错误显然是一些不被认为是通过的情况。通常 check50 会提供有关测试数据的一些信息。至少对于其他任务。对于失败的测试用例,它显示了哪些额外信息?
  • 可以容纳candidate_count - 1 条目的数组的目的是什么?你的循环中i 的范围是多少?
  • 编辑问题以包含minimal reproducible example。如果您没有重现问题的示例输入,您可以将其省略,但至少提供一个其他人可以编译和执行的完整程序。

标签: c segmentation-fault cs50


【解决方案1】:

当程序尝试访问无效的内存地址时会发生分段错误,例如如果您尝试访问矢量int a[10]a[10]。请注意,C 中的索引是从零开始的,这意味着 10 是第 11 个元素。它发生在您代码的某些部分:

int d[candidate_count - 1];
...
for (int i = 1; i < candidate_count; i++)
{
    if (candidates[c].votes < candidates[i].votes)
    ...

i = candidate_count - 1 在最后一次迭代中,索引i 超出了大小为candidate_count-1 的向量的限制。您可以尝试以下方法:

int d[candidate_count];
...
for (int i = 0; i < candidate_count; i++)
{
    if (candidates[c].votes < candidates[i].votes)
    ...

看到这个Wikipedia article about segfault

【讨论】:

  • 您显示的语句访问candidates,大概至少有candidate_count 元素。他们不访问只有candidate_count - 1 元素的d,因此这不是问题的根源。第一个循环中使用d[e] 访问d 的语句以candidate_count - 2 的最大值e 执行,因此它也不是问题的根源。 (e 可能达到candidate_count - 1 的值,但仅在最后一次迭代中d[e] = i; 之后的e++ 中。)
【解决方案2】:

发件人:

            d[e] = i;
            e++;

我们看到ed 中设置的最后一个元素的索引大一。

然后:

    for(int i = 0; i < (e + 1); i++)
    {
        if(candidates[c].votes == candidates[(d[i])].votes)

执行一个迭代,其中ie,所以d[i]d[e],它访问的元素超出了d 中设置的最后一个元素。这个值是未初始化的,可能表现得好像它有一个非常大的正值或负值(因此当表达式试图访问内存越界时导致段错误)或一个小的值导致访问candidates中的一些不需要的元素(因此打印出不正确的名称),或者它可能在您的程序中出现其他一些不希望的行为。

for 语句更改为:

    for (int i = 0; i < e; i++)

【讨论】:

    猜你喜欢
    • 2023-01-08
    • 1970-01-01
    • 1970-01-01
    • 2014-09-19
    • 1970-01-01
    • 2018-09-08
    • 2021-07-27
    • 2020-10-22
    • 1970-01-01
    相关资源
    最近更新 更多