【问题标题】:Inaccurate output in C recursive programC递归程序中的输出不准确
【发布时间】:2017-07-01 19:18:45
【问题描述】:

C 递归函数错误

我正在学习“实用 C 编程,第 3 版” 由 Steve Oualline 撰写,其中包含这项任务,以制作具有以下要求的程序。

练习 9-3:编写一个函数 count(number, array, length) 计算 number 出现在 array 中的次数。该数组具有length 元素。这 函数应该是递归的。编写一个测试程序来配合这个函数。

我在大约 15 分钟内编写了程序,但我的输出并不完全符合我的要求。代码如下:

#include <stdio.h>

int length;
int count(int num2count, int array[length], int size);

int main(void)
{
  char check;
  int i = 0;
  long int num_to_be_counted;
  int ans;
  printf("Please enter the length of array:");
  scanf("%d",&length);
  long int numbers[length];

  for(int i = 0; i != length; ++i) {
    numbers[i] = 0;
  }

  printf("Enter the array:");

  while( check != '\n') {
    scanf("%li",&numbers[i]);
    ++i;
    check = getchar();
  }

  printf("Enter the number to be counted in the array:");

  scanf("%d",&num_to_be_counted);

  for(int i = 0; i != length; ++i) {
    numbers[i] = 0;
  }

  ans = count(num_to_be_counted,numbers,length);

  printf("The number appears %d times in the array.",ans);

  return 0;
}


int count(int num2count, int array[length], int size)
{
  static int times = 0;
  static int i = 0;

  if ( array[i] == num2count) {
    ++times;
  }

  if(i == size) {
    return times;
  }

  while( i != length ) {
    ++i;
    count(num2count,array,length);
  }
}

程序没有错误(逻辑错误除外),这是示例输入和输出

length = 4
numbers = 1 2 2 4
number_to_count = 2
Output: 4

该函数甚至不计算要计算的数字;它只返回数组的大小,例如在本例中为 4。

我们将不胜感激任何形式的帮助。

【问题讨论】:

  • 提示:不要使用全局变量或static 变量。
  • @melpomene 请详细说明?
  • 为什么在接受用户的数组中的所有值后将它们重新分配给0
  • 所以你在 15 分钟内编写了代码,并没有花一分钟来调试。我学习调试/测试比编写代码要花更长的时间。
  • 我尝试运行您的代码并遇到分段错误。你可能想检查你的递归​​函数并将循环放在你检查if(i == size)的地方在函数的开头

标签: c arrays function recursion


【解决方案1】:

代码中的问题:

  • 您的代码将输入数组重置为0,然后再对其进行任何操作。

  • count 在检查if(i == size) 之前访问array[i],即您有越界访问。

  • 您对count 的递归调用被包裹在一个循环中。这是没有意义的,因为嵌套的 count 调用将自行循环(并且在每次迭代中再次调用 count,这将自行循环......)。

  • count 中的所有局部变量都是static,这意味着该函数是无用的:你不能在任何程序中多次调用它。一个更好的测试程序来证明这一点是这样的:

    for (int i = 0; i < length; i++) {
        printf("%d appears %d times in the array\n", numbers[i], count(numbers[i], numbers, length));
    }
    

其他问题:

  • int i; 在您的 main() 函数中未使用。
  • check 在您第一次检查时未初始化。
  • getchar() 的结果分配给char 通常是个坏主意; getchar() 返回 int 是有原因的。
  • 您的程序中存在类型错误:numbers 被声明为 long int 的数组,但您将其传递给采用 int 数组的函数。
  • system() 缺少 #include &lt;stdlib.h&gt;

【讨论】:

  • 当我可以在没有它的情况下访问 system() 时,为什么我需要包含 stdlib?
  • @Muneeb 包括&lt;stdlib.h&gt; 将为system 提供声明,如果您使用不正确的参数调用它,编译器会发出警告。如果没有范围内的声明,system("...") 将起作用(因为system 恰好返回int),但编译器也会接受system(1, 2, 3)(参数数量错误,类型错误)。这种事情通常会导致运行时崩溃(或垃圾结果)。
  • 天哪,为什么我在编码时要照顾这么多东西。如果可以,我想问你一件事?
  • 您编写代码有多久了,当您刚开始编程时,您是否在编写的每个程序中都遇到过错误。我实际上是在 6 个月前开始编码,并想知道我在学习编码方面的进展情况。另外,您能否提供一些技巧来编写更好且不易出错的代码?
  • @Muneeb:我无法回答 Melpomene,但对我来说,它已经超过 30 年了,是的,几个星期以来,我一直都有错误。有时我现在会在第一次编译时获得大量代码,但并不像我想要的那样频繁。有时它在第一次运行时就可以正常工作——这种情况发生得更频繁。至于提示:注意编译器给你的每一个警告,并在运行程序之前修复它。编译器比你更了解 C;如果它打算警告你,那是因为它非常确定你犯了一个错误。假设它是正确的。 (编译器错误非常罕见!)
【解决方案2】:
  1. 在将数组值传递给函数之前不要重置它们。
  2. count 中的 while 循环没有意义,重新考虑它的工作方式,也许打印出递归调用。另外 count 可能不会返回任何内容,请修复它。
  3. 正如 cmets 中已经提到的,在访问数组元素之前检查是否越界。

【讨论】:

    【解决方案3】:

    这里有很多问题。

    首先,这比应有的复杂得多。您使用了static,这根本不需要。

    答案是错误的,因为你计算了多次。

    这是应该的。你可以试着理解这段代码。

    int count(int num2count, int array[], int size)
    {
        if( size<= 0) return 0;
        return (array[size-1]==num2count)+count(num2count,array,size-1);
    }
    

    int count(int num2count, int array[], int size)
    {
        if( size<= 0) return 0;
        return (array[0]==num2count)+count(num2count,array+1,size-1);
    }
    

    为什么我不应该在递归中使用static?这没有错,但它是一个糟糕的设计,因为当你有数千行代码和大量函数时,它就会成为一个问题。然后跟踪哪个变量导致了任何问题或调试它会非常乏味。 1

    你的问题

    int count(int num2count, int array[length], int size)
    {
        static int times = 0;  // bad design and unnecessary.
        static int i = 0;
    
       if ( array[i] == num2count)
       {
        ++times;
       }
    
    
    
       if(i == size)
       {
        return times;
       }
       while( i < length ) <----check
       {
         ++i;
         count(num2count,array,length);
       }
    
    }
    

    另外,count() 不返回任何值,因此没有必要将其存储在变量中。

    1我刚才提到了几个问题和问题的干净解决方案。有关详细说明,请参阅 melpomene 的回答。

    【讨论】:

    • @melpomene.: 抱歉没注意到.. 让我写信。谢谢指点。
    • @coderredoc 为什么这里使用静态错误,如果不使用静态,递归调用函数时,变量将如何在下一阶段保持其值?
    • @melpomene.:请先生检查。
    • [length] 部分毫无意义。您可以将参数声明为int array[]int *array。 (其余的看起来不错。作为一个额外的练习,让它从左到右计数。:-)
    • 我在这里真的很困惑,有人能告诉我代码中的主要问题吗(只是问题,而不是解决方案。我喜欢自己解决问题)。
    猜你喜欢
    • 2018-08-09
    • 2015-01-06
    • 1970-01-01
    • 2020-06-29
    • 1970-01-01
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多