Hi wanted to display repeated elements of a Random array whose size can be specified by the user. The problem I am getting in the output is , the function is printing a repeated number as many times as it has been repeated but I want to print it only once. Here is my code and output following the former:
您希望显示随机数组的重复元素,其大小可由用户指定。我在输出中遇到的问题是,该函数正在重复打印重复次数,但我想只打印一次。以下是我的代码和输出:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 0;
}
free(repeats);
}
Here is the output I am getting
这是我得到的输出
Enter the size of the array:
5
What's in the array:
3 1 2 0 3
3 occurs 2 times
3 occurs 2 times
I want "3 occurs 2 times" to print once. Please help!
我想要“3次出现2次”打印一次。请帮忙!
5 个解决方案
#1
2
What's happening is that your code realizes 3 is repeated twice, in this block:
发生的事情是你的代码实现3重复两次,在这个块中:
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
}
When i
is equal to 0, it will look at the array and realize that 3 is repeated, so count>1
will be true
. Then, when i
is equal to 4, count>1
will be true
again, and you get the double print.
当i等于0时,它将查看数组并意识到3重复,因此count> 1将为真。然后,当i等于4时,count> 1将再次为真,并且您将获得双重打印。
In order to fix this, I would create an array that stores the numbers that have already been verified as repeated and check against that.
为了解决这个问题,我将创建一个数组,用于存储已经过重复验证的数字并对其进行检查。
#2
1
Since in your case, value of elements < size_array, so can take this approach.
因为在你的情况下,元素的值
memset(repeats, 0, n*sizeof(repeats[0]));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
count = repeats[a[i]];
if(count>0)
break;
if(a[i] == a[j]){
count++;
}
}
repeats[a[i]] = count;
The idea is to store the count for each value and check before starting search for each new value to check if it has already been counted.
我们的想法是存储每个值的计数,并在开始搜索每个新值之前进行检查,以检查它是否已被计数。
#3
0
Try it:
for(i=0;i<n-1;i++)
{
for(j=1;j<n;j++)
{
So, don't compare the same one element with itself.
所以,不要将相同的元素与自身进行比较。
#4
0
Thanks guys I got it working with the above ideas! here is what I got..
谢谢你们,我得到了以上的想法!这是我得到的..
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *freq;
freq = malloc(n * sizeof freq[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
freq[i] = -1;
}
for(i=0;i<n;i++){
count = 1;
for(j=i+1;j<n;j++){
if(a[i]==a[j]){
count++;
freq[j] = 0;
}
}
if(freq[i]!=0){
freq[i] = count;
}
}
for(i=0;i<n;i++){
if(freq[i]!=1 && freq[i]!=0){
printf("%d occurs %d times\n",a[i],freq[i]);
}
}
free(freq);
}
#5
0
In display_repeats()
, you may simply update 2 lines and add 3 lines to make your program have the correct behaviour. And we will see it later: we can optimize the final code using C99 syntax and the comma C operator, to write far less lines than your original code (9 lines instead of 20 lines!).
在display_repeats()中,您可以简单地更新2行并添加3行以使您的程序具有正确的行为。我们稍后会看到它:我们可以使用C99语法和逗号C运算符优化最终代码,编写比原始代码少得多的行(9行而不是20行!)。
So, in this answer, you will find how to get the final code that has the correct behaviour and is very short, shorter than your initial code:
因此,在这个答案中,您将找到如何获得具有正确行为并且非常短,比初始代码短的最终代码:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
The idea is to set to -1 each array value that has matched a previous one, just after the count increment. Because you do not want to count this value again.
我们的想法是在计数增量之后将每个与前一个匹配的数组值设置为-1。因为您不想再次计算此值。
So simply do the following:
所以只需执行以下操作:
-
In the two lines where you write
count = 0
, replace 0 by 1, because you are sure that each number in the list must be counted at least one time.在您写入count = 0的两行中,将0替换为1,因为您确定列表中的每个数字必须至少计算一次。
This way, you can avoid checking the case where i equals j in the inner loop: it is already taken into account in count. So add
if (i == j) continue;
at the beginning of the inner loop.通过这种方式,您可以避免在内循环中检查i等于j的情况:它已经在计数中被考虑在内。所以添加if(i == j)继续;在内循环的开头。
-
With the previous updates, you are now sure that when you increment count, in the inner loop, j is not equal to i. Therefore, you can change the value of
a[j]
without changinga[i]
, in the array.通过以前的更新,您现在可以确定当递增计数时,在内部循环中,j不等于i。因此,您可以在数组中更改[j]的值而不更改[i]。
-
So, add
a[j] = -1;
just after having increased count. This way, when i will be incremented to check for a new count of a new value, it is impossible that the new counted value has already been counted.所以,添加一个[j] = -1;刚增加计数后这样,当我将增加以检查新值的新计数时,新计数值不可能已被计数。
-
Finally, you do not want to count how many times -1 is in the array. But you have replaced some values with -1. So simply add
if (a[i] == -1) continue;
at the beginning of the outer loop to avoid counting how -1 there are in the array.最后,您不希望计算数组中-1的次数。但是你用-1替换了一些值。所以只需添加if(a [i] == -1)继续;在外部循环的开头,以避免计算数组中的-1。
This intermediate code is:
这个中间代码是:
void display_repeats(int *a,int n) {
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 1;
for(i=0; i<n; i++) {
if (a[i] == -1) continue;
for(j=0; j<n; j++) {
if (i == j) continue;
if(a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if(count > 1) {
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 1;
}
free(repeats);
}
Now, we can optimize this code.
现在,我们可以优化此代码。
First, we can avoid testing a[i] == a[j]
when j <= i: if such a case happens, we know that we have previously displayed the count for a[j] (the number of times a[j] appears in the array). Therefore we can replace for (j=0; j < n; j++) {
by for (j=i+1; j<n; j++) {
.
首先,当j <= i时,我们可以避免测试[i] == a [j]:如果发生这种情况,我们知道我们之前已经显示了[j]的计数(a [j]的次数]出现在数组中)。因此,我们可以替换为(j = 0; j
With this last update, we know that the first line of the inner loop will never match: i can not be equal to j. So we can remove this line (if (i == j) continue;
).
通过最后一次更新,我们知道内部循环的第一行永远不会匹配:我不能等于j。所以我们可以删除这一行(如果(i == j)继续;)。
Note that the values stored in the repeats array are only used to get the value of count in the printf() call. So we can remove every reference to the repeats array and simply use count in the printf() call.
请注意,存储在repeats数组中的值仅用于获取printf()调用中的count值。因此,我们可以删除对重复数组的每个引用,并在printf()调用中使用count。
Now, you can see that we set count to 1, two times. We can do it only one time, if we do not set it to 1 at the end of the main loop, to prepare a new loop, but at the beginning.
现在,您可以看到我们将计数设置为1,两次。我们只能做一次,如果我们不在主循环结束时将它设置为1,那么准备一个新的循环,但是在开始时。
Now, note that i, j and count have the same type, so only one line may be used to define them: int i = 0, j = 0, count = 1;
. More over, i and j are defined later in the for loops, so no need to define their initial value here. So we can simply write int i, j, count = 1;
. But count is now defined at the beginning of the outer loop, so we do not need to define it previously. So we only need to define i, j and count without an initial value: int i, j, count;
.
现在,请注意i,j和count具有相同的类型,因此只能使用一行来定义它们:int i = 0,j = 0,count = 1;。此外,i和j稍后在for循环中定义,因此无需在此处定义其初始值。所以我们可以简单地写int i,j,count = 1;。但是count现在定义在外部循环的开头,所以我们不需要先定义它。所以我们只需要定义i,j和count而没有初始值:int i,j,count;。
The new intermediate code is:
新的中间代码是:
void display_repeats(int *a, int n) {
int i, j, count;
for (i = 0; i < n; i++) {
if (a[i] == -1) continue;
count = 1;
for(j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using C99 syntax
使用C99语法
But we can do more, using the C99 specification: we can define a variable with the for instruction: we can write for (int i = ...)
. No more need to define it previously. So we can avoid having to write int i, j, count;
, we will define them at first use:
但我们可以使用C99规范做更多事情:我们可以使用for指令定义变量:我们可以为(int i = ...)编写。不再需要先定义它。所以我们可以避免写int i,j,count;,我们将在第一次使用时定义它们:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for(int j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using the comma C operator
使用逗号C运算符
Again, we can do much better! We can use the comma operator (,
): it is a binary operator that evaluates its first operand, discards the result, evaluates the second operand and returns its value. Using the comma operator, we can transform count++; a[j] = -1;
to a single instruction: a[j] = (count++, -1)
. But we can avoid the parenthesis writing count++, a[i] = -1
. Now, we do not need a block for the if statement, since there is only one instruction. Therefore, we can remove a lot of parenthesis.
再说一遍,我们可以做得更好!我们可以使用逗号运算符(,):它是一个二元运算符,用于计算其第一个操作数,丢弃结果,计算第二个操作数并返回其值。使用逗号运算符,我们可以转换count ++; a [j] = -1;单个指令:a [j] =(count ++, - 1)。但我们可以避免括号写入计数++,a [i] = -1。现在,我们不需要if语句的块,因为只有一条指令。因此,我们可以删除很多括号。
The final code is:
最终的代码是:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
#1
2
What's happening is that your code realizes 3 is repeated twice, in this block:
发生的事情是你的代码实现3重复两次,在这个块中:
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
}
When i
is equal to 0, it will look at the array and realize that 3 is repeated, so count>1
will be true
. Then, when i
is equal to 4, count>1
will be true
again, and you get the double print.
当i等于0时,它将查看数组并意识到3重复,因此count> 1将为真。然后,当i等于4时,count> 1将再次为真,并且您将获得双重打印。
In order to fix this, I would create an array that stores the numbers that have already been verified as repeated and check against that.
为了解决这个问题,我将创建一个数组,用于存储已经过重复验证的数字并对其进行检查。
#2
1
Since in your case, value of elements < size_array, so can take this approach.
因为在你的情况下,元素的值
memset(repeats, 0, n*sizeof(repeats[0]));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
count = repeats[a[i]];
if(count>0)
break;
if(a[i] == a[j]){
count++;
}
}
repeats[a[i]] = count;
The idea is to store the count for each value and check before starting search for each new value to check if it has already been counted.
我们的想法是存储每个值的计数,并在开始搜索每个新值之前进行检查,以检查它是否已被计数。
#3
0
Try it:
for(i=0;i<n-1;i++)
{
for(j=1;j<n;j++)
{
So, don't compare the same one element with itself.
所以,不要将相同的元素与自身进行比较。
#4
0
Thanks guys I got it working with the above ideas! here is what I got..
谢谢你们,我得到了以上的想法!这是我得到的..
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *freq;
freq = malloc(n * sizeof freq[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
freq[i] = -1;
}
for(i=0;i<n;i++){
count = 1;
for(j=i+1;j<n;j++){
if(a[i]==a[j]){
count++;
freq[j] = 0;
}
}
if(freq[i]!=0){
freq[i] = count;
}
}
for(i=0;i<n;i++){
if(freq[i]!=1 && freq[i]!=0){
printf("%d occurs %d times\n",a[i],freq[i]);
}
}
free(freq);
}
#5
0
In display_repeats()
, you may simply update 2 lines and add 3 lines to make your program have the correct behaviour. And we will see it later: we can optimize the final code using C99 syntax and the comma C operator, to write far less lines than your original code (9 lines instead of 20 lines!).
在display_repeats()中,您可以简单地更新2行并添加3行以使您的程序具有正确的行为。我们稍后会看到它:我们可以使用C99语法和逗号C运算符优化最终代码,编写比原始代码少得多的行(9行而不是20行!)。
So, in this answer, you will find how to get the final code that has the correct behaviour and is very short, shorter than your initial code:
因此,在这个答案中,您将找到如何获得具有正确行为并且非常短,比初始代码短的最终代码:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
The idea is to set to -1 each array value that has matched a previous one, just after the count increment. Because you do not want to count this value again.
我们的想法是在计数增量之后将每个与前一个匹配的数组值设置为-1。因为您不想再次计算此值。
So simply do the following:
所以只需执行以下操作:
-
In the two lines where you write
count = 0
, replace 0 by 1, because you are sure that each number in the list must be counted at least one time.在您写入count = 0的两行中,将0替换为1,因为您确定列表中的每个数字必须至少计算一次。
This way, you can avoid checking the case where i equals j in the inner loop: it is already taken into account in count. So add
if (i == j) continue;
at the beginning of the inner loop.通过这种方式,您可以避免在内循环中检查i等于j的情况:它已经在计数中被考虑在内。所以添加if(i == j)继续;在内循环的开头。
-
With the previous updates, you are now sure that when you increment count, in the inner loop, j is not equal to i. Therefore, you can change the value of
a[j]
without changinga[i]
, in the array.通过以前的更新,您现在可以确定当递增计数时,在内部循环中,j不等于i。因此,您可以在数组中更改[j]的值而不更改[i]。
-
So, add
a[j] = -1;
just after having increased count. This way, when i will be incremented to check for a new count of a new value, it is impossible that the new counted value has already been counted.所以,添加一个[j] = -1;刚增加计数后这样,当我将增加以检查新值的新计数时,新计数值不可能已被计数。
-
Finally, you do not want to count how many times -1 is in the array. But you have replaced some values with -1. So simply add
if (a[i] == -1) continue;
at the beginning of the outer loop to avoid counting how -1 there are in the array.最后,您不希望计算数组中-1的次数。但是你用-1替换了一些值。所以只需添加if(a [i] == -1)继续;在外部循环的开头,以避免计算数组中的-1。
This intermediate code is:
这个中间代码是:
void display_repeats(int *a,int n) {
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 1;
for(i=0; i<n; i++) {
if (a[i] == -1) continue;
for(j=0; j<n; j++) {
if (i == j) continue;
if(a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if(count > 1) {
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 1;
}
free(repeats);
}
Now, we can optimize this code.
现在,我们可以优化此代码。
First, we can avoid testing a[i] == a[j]
when j <= i: if such a case happens, we know that we have previously displayed the count for a[j] (the number of times a[j] appears in the array). Therefore we can replace for (j=0; j < n; j++) {
by for (j=i+1; j<n; j++) {
.
首先,当j <= i时,我们可以避免测试[i] == a [j]:如果发生这种情况,我们知道我们之前已经显示了[j]的计数(a [j]的次数]出现在数组中)。因此,我们可以替换为(j = 0; j
With this last update, we know that the first line of the inner loop will never match: i can not be equal to j. So we can remove this line (if (i == j) continue;
).
通过最后一次更新,我们知道内部循环的第一行永远不会匹配:我不能等于j。所以我们可以删除这一行(如果(i == j)继续;)。
Note that the values stored in the repeats array are only used to get the value of count in the printf() call. So we can remove every reference to the repeats array and simply use count in the printf() call.
请注意,存储在repeats数组中的值仅用于获取printf()调用中的count值。因此,我们可以删除对重复数组的每个引用,并在printf()调用中使用count。
Now, you can see that we set count to 1, two times. We can do it only one time, if we do not set it to 1 at the end of the main loop, to prepare a new loop, but at the beginning.
现在,您可以看到我们将计数设置为1,两次。我们只能做一次,如果我们不在主循环结束时将它设置为1,那么准备一个新的循环,但是在开始时。
Now, note that i, j and count have the same type, so only one line may be used to define them: int i = 0, j = 0, count = 1;
. More over, i and j are defined later in the for loops, so no need to define their initial value here. So we can simply write int i, j, count = 1;
. But count is now defined at the beginning of the outer loop, so we do not need to define it previously. So we only need to define i, j and count without an initial value: int i, j, count;
.
现在,请注意i,j和count具有相同的类型,因此只能使用一行来定义它们:int i = 0,j = 0,count = 1;。此外,i和j稍后在for循环中定义,因此无需在此处定义其初始值。所以我们可以简单地写int i,j,count = 1;。但是count现在定义在外部循环的开头,所以我们不需要先定义它。所以我们只需要定义i,j和count而没有初始值:int i,j,count;。
The new intermediate code is:
新的中间代码是:
void display_repeats(int *a, int n) {
int i, j, count;
for (i = 0; i < n; i++) {
if (a[i] == -1) continue;
count = 1;
for(j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using C99 syntax
使用C99语法
But we can do more, using the C99 specification: we can define a variable with the for instruction: we can write for (int i = ...)
. No more need to define it previously. So we can avoid having to write int i, j, count;
, we will define them at first use:
但我们可以使用C99规范做更多事情:我们可以使用for指令定义变量:我们可以为(int i = ...)编写。不再需要先定义它。所以我们可以避免写int i,j,count;,我们将在第一次使用时定义它们:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for(int j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using the comma C operator
使用逗号C运算符
Again, we can do much better! We can use the comma operator (,
): it is a binary operator that evaluates its first operand, discards the result, evaluates the second operand and returns its value. Using the comma operator, we can transform count++; a[j] = -1;
to a single instruction: a[j] = (count++, -1)
. But we can avoid the parenthesis writing count++, a[i] = -1
. Now, we do not need a block for the if statement, since there is only one instruction. Therefore, we can remove a lot of parenthesis.
再说一遍,我们可以做得更好!我们可以使用逗号运算符(,):它是一个二元运算符,用于计算其第一个操作数,丢弃结果,计算第二个操作数并返回其值。使用逗号运算符,我们可以转换count ++; a [j] = -1;单个指令:a [j] =(count ++, - 1)。但我们可以避免括号写入计数++,a [i] = -1。现在,我们不需要if语句的块,因为只有一条指令。因此,我们可以删除很多括号。
The final code is:
最终的代码是:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}