【问题标题】:My for loop is adding +1 excess and i do not know why我的 for 循环添加了 +1 多余的,我不知道为什么
【发布时间】:2021-12-13 02:58:36
【问题描述】:

基本上,我试图制作一个循环遍历给定数组的程序,并检查右侧元素是否比左侧元素大 2 倍,如果为 true,则在中间插入这两个元素的平均值。之后,它打印出插入元素的数组,然后再次循环遍历数组,计算某个数字出现的次数。我用笔和纸成功地编写了所有代码,并将问题写成更小的块,然后用 C 进行编码,但问题是当我输入 100 个零(一百个零)时。程序打印出数字 0 重复了 200 次而不是 199 次。我不知道为什么。对不起,代码很糟糕,我目前的任务是擅长用纸笔解决问题,等我变得体面并发展我的逻辑之后,我会尝试让代码更简单。

Input sample: 
Enter the number of elements: 100
Enter the array: 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
After adding middle element: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002.33412e-310 
The number is repeated 200 time/s

我的代码

#include <math.h>
#include <stdio.h>

#define EPSILON 0.0001

int main() {
  int n, i, j, k, digit, length = 0, digit_array[10] = {0};
  double array[200], temp;
  do {
    printf("Enter number of elements: ");
    scanf("%d", &n);
  } while (n <= 0 || n >= 101);

  printf("Enter elements: ");

  length = n;

  for (i = 0; i < length; i++)
    scanf("%lf", &array[i]);

  for (i = 0; i < length; i++) {
    temp = array[i] + array[i];
    if (fabs(temp - array[i + 1]) < EPSILON) {
      for (j = length; j > i + 1; j--)
        array[j] = array[j - 1];
      array[i + 1] = (array[i] + array[i + 1]) / 2.;
      i++;
      length++;
    }
  }

  printf("After adding middle element: \n");
  for (i = 0; i < length; i++)
    printf("%g ", array[i]);

  for (i = 0; i < length; i++) {
    temp = array[i];
    digit = ((int)(temp * 10)) % 10;
    digit_array[digit]++;
  }
  printf("\n");

  for (i = 0; i < 10; i++) {
    if (digit_array[i] != 0)
      printf("Number %d is repeated %d time/s.\n", i, digit_array[i]);
  }

  return 0;
}

【问题讨论】:

  • 我希望这可以解释为什么链表在中间插入比数组更好。
  • @yano 我还在学C,想先熟悉一下数组。
  • 代码超出了数组的末尾。在循环的最后一次迭代中,i 等于 length-1。这意味着表达式 temp - array[i+1] 正在读取 array[length],但 array[length] 超出了数组的末尾。
  • 尚未完全审查代码,但for (i = 0; i &lt; length-1; i++) 可能会工作。
  • @user3386109 对我来说是正确的:godbolt.org/z/j1sPcGc6x

标签: c loops for-loop epsilon


【解决方案1】:

与其不断移动数组,不如使用两个数组更容易、更快捷。你只需要这个:

// Inputs:
//   n: The number of inputs.
//   a: An array of at least n doubles containing the inputs.
//   b: An array of at least n*2-1 doubles that will containing the outputs.

// Outputs:
//   m: The number of outputs.
//   b: An array of at least m doubles containing the outputs.

size_t i = 0;
size_t j = 0; 

double prev = b[j++] = a[i++];

while (i < n) {
   double next = a[i];
   if (fabs(prev*2 - next) < EPSILON) {   // If a[i-1] exactly equal a[i]*2.
      b[j++] = next / 2.0 + prev / 2.0;   // Or: b[j++] = prev * 1.5;
   }

   prev = b[j++] = a[i++];
}

size_t m = j;

关于prev * 1.5

average(next, prev)
= ( next + prev ) / 2
= ( prev * 2 + prev ) / 2
= ( prev * 3 ) / 2
= prev * 1.5

包含在适当的功能中:

int f(double *a, size_t n, double **b_ptr, size_t *m_ptr) {
   double b = malloc( (n*2-1) * sizeof(double) );  // We need up to this much.
   if (b == NULL) {
      *b_ptr = NULL;
      return 0;
   }

   size_t i = 0;
   size_t j = 0; 

   double prev = b[j++] = a[i++];

   while (i < n) {
      double next = a[i];
      if (fabs(prev*2 - next) < EPSILON) {   // If a[i-1] exactly equal a[i]*2.
         b[j++] = next / 2.0 + prev / 2.0;   // Or: b[j++] = prev * 1.5;
      }

      prev = b[j++] = a[i++];
   }

   b = realloc(b, j * sizeof(double));  // Free the excess. (Optional)
   size_t m = j;

   *b_ptr = b;
   *m_ptr = m;
   return 1;
}

【讨论】:

  • 正如我所写,我仍然只是学习初学者任务,我不理解你写的代码的一半,我认为我只是复制粘贴代码对自己没有任何好处:/
  • 除了使用 malloc 而不是硬编码数组的大小之外,这里没有什么是你没有使用的。忽略int i = 0; 之前和循环之后的所有内容。查看更新
  • 好的,我理解了 prev * 1.5。非常感谢你们的澄清。由于我对stackoverflow还是新手,我不知道如何代表+1你们,但我认为无论如何你不需要我。非常感谢@ikegami
  • 您点击了帖子旁边的向上箭头。可能有最低的声誉?
  • 是的,先生,15 代表
猜你喜欢
  • 2018-08-04
  • 2018-06-05
  • 1970-01-01
  • 1970-01-01
  • 2021-04-22
  • 2018-10-11
  • 2022-10-23
  • 2020-07-13
  • 1970-01-01
相关资源
最近更新 更多