这段代码有几个问题,我们可以通过一些更完整的测试来说明。这是一个简短的、独立的、可编译的(在 C99 中)示例(参见 SSCCE),其中包含一些测试和一些额外的诊断结果:
#include <stdio.h>
void printArray(char *name, int *list, int size) {
printf ("%s = {",name);
for (int i = 0; i < size; i++) {
printf ("%d ",list[i]);
}
printf ("}\n");
}
void countOccurrences(int *list, int size, int *uniques, int *values) {
for (int i = 0, t = 0; i < size; i++) {
int temp = list[i];
if (temp == 0) {
//If the number was a repeat of another previous number
continue;
//skip over it and go to the next element in list
}
uniques[t] = 1;
values[t] = temp;
for (int j = i+1; j <= size; j++) {
//this iterates through list for any repeats of temp
if (temp == list[j]) {
//All repeats of temp turn to 0
uniques[i]++;
list[j] = 0;
}
}
t++;
}
}
void test(int *x, int size) {
const int n = 10;
int uniques[n],values[n];
for (int i = 0; i < n; i++) {uniques[i] = 0; values[i] = -1; }
countOccurrences (x,size,uniques,values);
printArray ("uniques",uniques,sizeof(uniques)/sizeof(*uniques));
printArray ("values ",values,sizeof(values)/sizeof(*uniques));
}
int main (int argc, char* argv[]) {
int x1[] = {1, 2, 1, 2, 2, 1, 2};
int x2[] = {1, 2, 3, 1, 2, 3, 1, 2, 3};
int x3[] = {1, 2, 1, 3, 1, 2, 3};
int x4[] = {3, 2, 1, 3, 1, 2, 3};
test(x1,sizeof(x1)/sizeof(*x1));
test(x2,sizeof(x2)/sizeof(*x2));
test(x3,sizeof(x3)/sizeof(*x3));
test(x4,sizeof(x4)/sizeof(*x4));
return 0;
}
(编辑感谢@Matt McNabb 的建议,将通用代码重构为test() 函数)
... 其输出为:
uniques = {3 4 0 0 0 0 0 0 0 0 }
values = {1 2 -1 -1 -1 -1 -1 -1 -1 -1 }
uniques = {4 3 3 0 0 0 0 0 0 0 }
values = {1 2 3 -1 -1 -1 -1 -1 -1 -1 }
uniques = {4 2 1 1 0 0 0 0 0 0 }
values = {1 2 3 -1 -1 -1 -1 -1 -1 -1 }
uniques = {3 2 3 0 0 0 0 0 0 0 }
values = {3 2 1 -1 -1 -1 -1 -1 -1 -1 }
第一个测试会为您提供预期的输出。第二个测试显示列表中的第一项有额外的计数。这可以通过更改来解决:
for (int j = i+1; j <= size; j++){
到
for (int j = i+1; j < size; j++){
...因为代码正在计算数据末尾之外的一个空格。修复了这个错误的输出是:
uniques = {3 4 0 0 0 0 0 0 0 0 }
values = {1 2 -1 -1 -1 -1 -1 -1 -1 -1 }
uniques = {3 3 3 0 0 0 0 0 0 0 }
values = {1 2 3 -1 -1 -1 -1 -1 -1 -1 }
uniques = {3 2 1 1 0 0 0 0 0 0 }
values = {1 2 3 -1 -1 -1 -1 -1 -1 -1 }
uniques = {3 2 2 0 0 0 0 0 0 0 }
values = {3 2 1 -1 -1 -1 -1 -1 -1 -1 }
第三和第四个测试结果更难解释,因为预期的输出应该是什么并不那么明显。计数功能似乎旨在按照在list 中找到这些数字的顺序报告唯一数字的计数。然而,在第三次测试中,“3”的第一次出现在列表中的第四项。改变:
uniques[i]++;
到
uniques[t]++;
... 表示计数作为计数列表中的tth 项输出,给出输出:
uniques = {3 4 0 0 0 0 0 0 0 0 }
values = {1 2 -1 -1 -1 -1 -1 -1 -1 -1 }
uniques = {3 3 3 0 0 0 0 0 0 0 }
values = {1 2 3 -1 -1 -1 -1 -1 -1 -1 }
uniques = {3 2 2 0 0 0 0 0 0 0 }
values = {1 2 3 -1 -1 -1 -1 -1 -1 -1 }
uniques = {3 2 2 0 0 0 0 0 0 0 }
values = {3 2 1 -1 -1 -1 -1 -1 -1 -1 }
这个输出现在是正确的,但是如果没有我添加到代码中的values 数组,很难解释在uniques 中找到的计数。请注意,在最后一个测试用例中,第一个计数是 list 中的 3s 的数量,而不是 1s 的数量。
最后,将参数修改为函数通常是不好的做法。在 C 中这样做是必要的,因为您不能从函数返回数组,但是修改 uniques 和 values 指向的数组通常是可以容忍的,因为它们可以明确地用于从函数向外返回结果。但是,修改用于向函数提供输入数据的参数,就像 countOccurrences() 对 list 所做的那样通常是不明智的,因为这意味着使用 countOccurrences() 的代码必须在将指针传递给之前复制 list如果它还想将list 的原始内容用于其他目的,则该列表为countOccurrences()。
如果我们知道要计算的整数都小于或等于uniques 数组的大小,那么@Saravana Kumar 建议的函数运行起来更快,更容易纠正:
// Requirements:
// uniques initially contains all zeros
// no integer in list is less than zero or greater than sizeof(uniques)/sizeof(int)-1
//
void countOccurrences2 (int *list, int size; int *uniques) {
for (int i = 0; i < size; i++) {
uniques[list[i]]++;
}
}