Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
122 views
in Technique[技术] by (71.8m points)

c - How to find how many times a number has been repeated in an array?

I am confused how to find out how many times a number has been repeated in a user input. I am able to input numbers and see which numbers are repeating but am unsure of how to print out each inputed number and how many times that number was used. This is what I have so far

#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: 
");

    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
", numArray[x]);
                break;
            }
        }
    }

    return EXIT_SUCCESS;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Continuing for my initial comment, whenever you want to capture the frequency of values within a range, you generally want to declare an array and let each element of the array represent one value within the range. (this applies to integer input). For example, in your case, if you want to find the frequency of the integer values entered by a user in the range of 0-99, you would declare an array with 100 elements (representing values 0-99) and initialize all values to 0.[1]

Then each time the user enters a valid value in the range, you increment that element. For example, if your user enters 58, you would increment array[58] = array[58] + 1; (or simply array[58]++;). The value of array[58] is now 1 indicating the user has entered 58 once. (if 58 was entered again, it would be 2, and so on...)

This lends itself nicely for your input loop. You simply declare say int x; and in your scanf call, you fill x, validate it is within the range and then array[x]++; For example with your numarray declared as int [100], you could do [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.
");
        continue;      /* if out of range - get new number */
    }
    numarray[x]++;     /* increment frequency at element x */
}

Now in your case the 0-99 exactly matches the zero-based array indexing used in C, but you can index any range simply by adjusting the indexes. For example, if you were interested in a range of 50-150 you would simply adjust the indexes as required (e.g. numarray[x-50]++;)

However, in your code, it is quite unclear what your actual intent is. For instance you ask for values between 0-99, but then declare numarray as a floating-point type. If your intent was to have the user enter whole number values, then your array type should be an integer type instead. That reduces to the classic frequency problem which you could handle simply in a manner similar to the following:

#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: 
");

    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.
");
            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
", i, numarray[i]);

    return EXIT_SUCCESS;
}

Example Use/Output

For example, you can generate 500 values between 0-99 and output the frequency for each of the 500 numbers generated with something similar to the following:

$ ./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

Handling floating-point values

Now if you truly wanted your user to enter floating-point values, e.g. 58.01831, 58.01826538, etc..., conceptually accounting for the frequency of each number isn't any difference, but the implementation is much more involved given the way floating-point numbers are stored in memory. See IEEE floating point and the numerous post on this site. The problems related to floating point storage and exact comparison of random user input can become fairly involved -- quickly. Even for the range of 0-99 there are literally 4e+18+ 64-bit values involved.

As noted in the second comment, one approach that can help is to hash the input values and store the hashed values in a hash-table to reduce the size of the array needed to track/store all values. You will have to balance precision you keep against storage size.

There is no way you could declare an array of 4e+18 elements. A hash table essentially provides a storage and lookup mechanism that can give you reasonable accuracy, and also provides a reasonable storage size. If the user enters 2-values that have the same hash a collision will be generated in your table, which you could use to indicate a duplicate entry. If that was your intent, then you will need to investigate the floating point hash functions available to meet your needs (which from your question, doesn't seem like what you intended, and it well beyond full-explanation here)

Look things over and let me know if you have any questions. If your intent was different, then please edit the question and I'm happy to work with you further.

footnote 1: choose an array type capable of holding the maximum number of entries you expect, e.g. each int element of the array can capture a maximum of INT_MAX, or 2147483647 repetitions (where an int is 32-bits)

footnote 2: C generally favors variable names of all lower-case, and avoids the use of camelCase or MixedCase variable names; reserving all upper-case for constants and macros. It is a matter of style -- so it is completely up to you.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...