如何查找数组中重复的次数?

时间:2017-02-05 22:39:24

标签: c arrays duplicates

我很困惑如何找出用户输入中重复了多少次。我能够输入数字并查看哪些数字正在重复但不确定如何打印出每个输入的数字以及该数字的使用次数。这就是我到目前为止所拥有的

#include <stdio.h>
#include <stdlib.h>

int main(){

    double numArray[100];
    int x = 0;
    int y = 0;
    int counter = 1;
    int count = 0;

    setvbuf(stdout, NULL, _IONBF, 0);

    printf("Enter any number of integers between 0 and 99 followed a non-numeric: \n");

    for (x = 0; x < 100; x++) {
        if (scanf("%lf", &numArray[x]) != 1)
            break;
        counter = counter + 1;
    }
    counter = counter - 1;

    for(x = 0; x < counter; x++){
        for(y = x + 1; y < counter; y++){
            if(numArray[x] == numArray[y]){
                printf("duplicate found: %lf\n", numArray[x]);
                break;
            }
        }
    }

    return EXIT_SUCCESS;
}

1 个答案:

答案 0 :(得分:1)

继续我的初始注释,每当你想捕获一个范围内的值的频率时,你通常想要声明一个数组,并让数组的每个元素代表该范围内的一个值。 (这适用于整数输入)。例如,在您的情况下,如果要查找用户在0-99范围内输入的整数值的频率,您将声明一个包含100个元素的数组(表示值0-99)和将所有值初始化为0 [1]

然后,每次用户在范围中输入有效值时,都会增加该元素。例如,如果您的用户输入58,则会增加array[58] = array[58] + 1;(或简称为array[58]++;)。 array[58]的值现为1,表示用户已输入58一次。 (如果再次输入58,则为2,依此类推......)

这非常适合您的输入循环。您只需声明说int x;并在scanf来电中填写x,验证它是否在范围内,然后array[x]++;例如宣布您的numarrayint [100],您可以执行 [2]

#define NMAX 100  /* define constants, avoid 'magic' numbers in code */
...
for (;;) {  /* loop until non-numeric encountered */
    int x;
    if (scanf("%d", &x) != 1)     /* check for non-numeric */
        break;
    if (x < 0 || x >= NMAX) {   /* validate value in range */
        fprintf (stderr, "error: value outside of range -- "
                 "try again.\n");
        continue;      /* if out of range - get new number */
    }
    numarray[x]++;     /* increment frequency at element x */
}

现在,在您的情况下,0-99与C中使用的从零开始的数组索引完全匹配,但您可以通过调整索引来索引任何范围。例如,如果您对一系列50-150感兴趣,则只需根据需要调整索引(例如numarray[x-50]++;

但是,在您的代码中,我们还不清楚您的实际意图是什么。例如,您要求0-99之间的值,但随后将numarray声明为浮点类型。如果您的目的是让用户输入整数值,那么您的数组类型应该是整数类型。这可以简化为典型的频率问题,您只需按照与以下类似的方式处理:

#include <stdio.h>
#include <stdlib.h>

#define NMAX 100  /* define constants, avoid 'magic' numbers in code */

int main (void){

    int i, numarray[NMAX] = {0};  /* C favors all lower-case over
                                   * camelCase variable names  */

    printf ("Enter any number of integers between 0 and 99 "
            "followed a non-numeric: \n");

    for (;;) {  /* loop until non-numeric encountered */
        int x;
        if (scanf("%d", &x) != 1)     /* check for non-numeric */
            break;
        if (x < 0 || x >= NMAX) {   /* validate value in range */
            fprintf (stderr, "error: value outside of range -- "
                    "try again.\n");
            continue;      /* if out of range - get new number */
        }
        numarray[x]++;     /* increment frequency at element x */
    }

    for (i = 0; i < NMAX; i++)   /* output frequency of values */
        printf (" %2d : %d times\n", i, numarray[i]);

    return EXIT_SUCCESS;
}

示例使用/输出

例如,您可以在500之间生成0-99个值,并输出生成的每个500个数字的频率与以下内容类似:

$ ./bin/freqarray < <(for i in $(seq 1 500); do
printf " %d" $(($RANDOM %100)); done; echo "done")
Enter any number of integers between 0 and 99 followed a non-numeric:
  0 : 4 times
  1 : 7 times
  2 : 7 times
  3 : 4 times
  4 : 5 times
  5 : 11 times
  6 : 5 times
  7 : 5 times
  8 : 3 times
  9 : 8 times
 10 : 5 times
 ...
 90 : 8 times
 91 : 2 times
 92 : 5 times
 93 : 8 times
 94 : 4 times
 95 : 4 times
 96 : 8 times
 97 : 6 times
 98 : 4 times
 99 : 8 times

处理浮点值

现在,如果您真的希望用户输入浮点值,例如58.0183158.01826538等等,从概念上考虑每个数字的频率并不存在任何差异,但是实现更加复杂,因为浮点< / em>数字存储在内存中。请参阅IEEE floating point以及本网站上的众多帖子。与浮点存储和随机用户输入的精确比较相关的问题可以变得相当复杂 - 很快。即使对于0-99的范围,也涉及字面上4e+18 + 64位值。

如第二条评论中所述,一种可以帮助的方法是散列输入值并将散列值存储在散列表中减少跟踪/存储所有值所需的数组大小。您必须平衡与存储大小相关的精度。

您无法声明4e+18元素数组。 哈希表本质上提供了存储和查找机制,可以为您提供合理的准确性,并且还提供合理的存储大小。如果用户输入具有相同哈希的2值,则会在表中生成冲突,您可以使用该表来指示重复的条目。如果那是你的意图,那么你需要调查可用的浮点哈希函数来满足你的需求(从你的问题来看,它看起来不像你想要的那样,而且远远超出了完整的解释)

仔细看看,如果您有任何疑问,请告诉我。如果您的意图不同,请编辑问题,我很乐意与您进一步合作。

脚注1:选择一个能够保存您期望的最大条目数的类型数组,例如数组中的每个int元素最多可以捕获INT_MAX2147483647次重复(int32-bits

脚注2: C通常支持所有小写的变量名称,并避免使用 camelCase MixedCase < / em>变量名;为常量和宏保留所有大写。这是一个风格问题 - 所以完全取决于你。