我正试图从一开始就在C中工作,并确保在继续前进之前理解每一件小事。今天,我的目标是编写一个程序,该程序将采用整数列表(假设少于50个整数),并打印一个表格,其中一侧包含唯一整数列表,另一侧表示它出现的次数。我有我的功能副本,负责计算它出现的次数。
我的函数的快速摘要:接收2个指向数组的指针,以及一个要迭代多少个整数的整数。假设:我们正在检查某些数字x的重复。在阵列的某个地方,我们击中另一个x。它递增x的计数并将x转换为0以用于以后的目的。
样品试验 输入:1 2 1 2 2 1 2 输出:1出现3次。 2出现4次。
输入:1 2 3 1 2 3 1 2 3 输出:1出现3次。 2次出现3次。 3出现3次。
输入:1 2 1 3 1 2 3 输出:1出现3次。 2出现2次。 3出现1次。
虽然该程序大部分都在工作,但我想确保它完全有效。因此,我的问题是上次审判。当它适用于其他2个输入集时,为什么3只被读取一次?
void countOccurrences(int *list, int size, int *uniques){
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;
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++;
}
}
答案 0 :(得分:3)
这是因为,3作为最后一个数字,你将发生次数重置为1
uniques[t] = 1;
并且for循环根本没有运行,因为那是最后一个数字,你不会回顾数组。
我只想编写如下程序。给予列表的值为> = 0
for (int i = 0; i < size; i++){ //this iterates through list for any repeats of temp
uniques[list[i]]++;
}
对于包含任何值的列表,请使用hash table数据结构
答案 1 :(得分:2)
我不会踩踏原始数据。
高级别观点:
for each element
if it apeared before
increment it's count
else
record it's first occurence
假设您需要计算N个元素数组的内容,它不能包含超过N个不同的元素。表示计数的一种简单方法是使用一组值和计数,以及一些使用的条目(看到不同的值)。这将是一条直线:
#define N ...
struct {
int value, cnt;
} count[N];
int entries = 0;
您检查价值v
是否已经存在:
for(k = 0; k < entries && count[k].value != v; k++)
;
if(k == entries) {
/* Not found */
count[k].value = v;
count[k].cnt = 1;
entries++;
}
else {
/* Found it */
count[k].value++;
}
只需要用代码来包装你的数据数组......
(是的,这是非常低效的;对于严重的使用更智能/更快的结构来保持值是必需的。)
答案 2 :(得分:1)
此代码存在一些问题,我们可以通过一些更完整的测试来说明这些问题。这是一个简短的,自包含的,可编译的(在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]++;
...表示计数作为计数列表中的t
项输出,给出输出:
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 }
此输出现在是正确的,但如果没有我添加到代码中的uniques
数组,很难解释values
中的计数。请注意,在上一个测试用例中,第一个计数是3
中list
的数量,而不是1
的数量。
最后,将参数修改为的所有通常是不好的做法。有必要在C中执行此操作,因为您无法从函数返回数组,但修改uniques
和values
指向的数组通常是可以容忍的,因为它们明确可用于向外返回结果功能。但是,修改用于向函数提供输入数据的参数,countOccurrences()
对list
执行操作通常是不明智的,因为这意味着使用countOccurrences()
的代码必须复制{{ 1}}在将指向该列表的指针传递给list
之前,如果它还希望将countOccurrences()
的原始内容用于其他目的。
如果我们知道要计算的整数都小于或等于list
数组的大小,那么@Saravana Kumar建议的函数运行起来更快,更容易纠正:< / p>
uniques