【问题标题】:Unique numbers in array数组中的唯一数字
【发布时间】:2014-11-01 07:01:30
【问题描述】:

与我之前的问题类似,这次我尝试打印不出现两次或超过两次的数字。

这是我的代码:

#include <stdio.h>
int main()
{
    int i;
    int a[10]={2,2,2,4,6,6,9,10,10,11};
    for(i=0; i < 10; ++i)
    {
        if(a[i] != a[i+1] && i!=9)
        {    if(i > 0 && a[i] != a[i-1])
             printf("%d ",a[i]);
        }
        if(i==9 && a[i]!=a[i-1])
             printf("%d", a[i]);
    }
    printf("\n");
    return 0;
}

输出结果是正确的,即 4、9、11,但我需要单独考虑 i 的最终值。有没有更好的办法?

【问题讨论】:

  • 不要将代码双重标记为 C 和 C++。那不是 C++,它只是古老的 (C89) C 代码。您至少应该使用int main()。而且,由于您使用的是 C89,因此您也不应该从 main() 中省略 return 0;;这仅在 C99 或更高版本中允许。
  • 现在好吗?如果仍然不正确,请告诉我。
  • 您的代码调用未定义的行为,因为它在检查 i != 9 之前访问了 a[10]。这是个坏消息。 (是的,除了未定义的行为之外,更新后的代码看起来还不错。您可以通过将循环的上限设置为 9 来解决这个问题。不过,分散的 9 和 10 并不是很好,尤其是 9 不是。我d 可能使用const int n = sizeof(a) / sizeof(a[0]); 并循环到i &lt; n - 1
  • @JonathanLeffler:是的,我知道,但我不喜欢它。这是我在这里发布问题的原因之一。
  • 另一个问题。你能假设输入数组是排序的吗?

标签: c arrays loops for-loop


【解决方案1】:

接受回答后

一种在已排序数组上查找唯一值的简化方法。

#include <stdio.h>

int main() {
  int a[] = { 2, 2, 2, 4, 6, 6, 9, 10, 10, 11 };
  size_t n = sizeof a / sizeof a[0];
  int previous = ~a[0];
  size_t i;
  for (i = 0; i < n; i++) {
    if (a[i] != previous)
      printf("%d ", a[i]);
    previous = a[i];
  }
  printf("\n");
  return 0;
}

【讨论】:

    【解决方案2】:

    请注意,逻辑运算符具有优先级,并且在具有相同优先级的情况下,就像在您的 if 语句中一样,它们是从左到右计算的。所以

    if(a[i] != a[i+1] && i!=9)
    

    将在i!=9 之前评估a[10],导致越界读取。如果您将其更改为

    if(i!=9 && a[i] != a[i+1])
    

    问题不会发生,因为i!=9 之前已评估过,并且由于它将为假,因此其余部分已知为假且未评估,没有越界读取。

    更好的是,循环 i=0; i&lt;9 并在循环外移动第二个,完全消除检查 i!=9 的需要。

    此外,您的数组{2,3,.....} 的代码将失败,它不会打印第一个元素 正如它应该。

    这是您的代码的更好版本

    #include <stdio.h>
    int main()
    {
        int i;
        int a[10]={2,2,2,4,6,6,9,10,10,11};
        for(i=0; i < 9; ++i)
        {
            if(a[i] != a[i+1])
            {    
                if(i == 0 || a[i] != a[i-1])
                    printf("%d ",a[i]);
            }
        }
        if(a[8] != a[9])
            printf("%d", a[9]);
        printf("\n");
        return 0;
    }
    

    请注意,在循环之后,我们只需使用正确的下标。更有效,因为添加 ifs 来检查最后一个元素将在每次迭代时评估那些 ifs,而现在它只评估一次。

    希望有帮助

    【讨论】:

    • 这很有帮助!再次感谢哈立德。:)
    【解决方案3】:

    您只需检查 for 循环中 i 的值是否超出数组范围

    我认为这应该可行

    int main()
    {
        int i;
        int a[10]={2,2,2,4,6,6,9,10,10,11};
        for(i=0; i < 10; ++i)
        {
            if(a[i] != a[(i+1)%10])
            {    if(i > 0 && a[i] != a[i-1])
                     printf("%d ",a[i]);
            }
        }
        printf("\n");
        return 0;
    }
    

    【讨论】:

      【解决方案4】:

      您始终可以使用嵌套的 for 循环来检查值。这种方式也适用于未排序的列表。

      int i;
      int j;
      int match; 
      for (i = 0; i < 10; i++)
      {
          match = 0;
      
          for(j = 0; j < 10; j++)
          {
              if (a[i] == a[j] && i!=j)
                  match = 1;
                  break;
          }
          if (match == 0)
              printf("%d",a[i]);
      }
      

      此代码将根据所有其他值检查每个值,并根据您的示例打印仅在列表中找到的数字一次。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-07
        • 2022-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多