我需要添加一个名为computeFrequencies的函数,给定一个具有等级的数组,返回一个小数组,其中包含等级的频率分布。 (这只是整个计划的一部分)
我做了这个,但是我对c完全是新手,而且我不确定我做错了什么: 给定错误: histogramtest2.c:16:10:错误:'成绩'被重新声明为不同类型的符号 histogramtest2.c:15:29:注意:先前的“成绩”定义就在这里 histogramtest2.c:20:12:错误:下标值既不是数组也不是指针也不是向量
任何人都可以帮助我吗? 非常感谢
void computeFrequencies(int grades[], int freq[10]){
int i, grades[];
int length=100;
for(i=0; i<length; i++){
grades[i]=i;
switch(i){
case 1: freq[1]++;
break;
case 2: freq[2]++;
break;
case 3: freq[3]++;
break;
case 4: freq[4]++;
break;
case 5: freq[5]++;
break;
case 6: freq[6]++;
break;
case 7: freq[7]++;
break;
case 8: freq[8]++;
break;
case 9: freq[9]++;
break;
default: freq[10]++;
}
}
}
嘿谢谢你的答案,但即使我的错误消失了,我的程序仍无效。 我的程序需要显示某些等级频率的直方图。 任何人都可以帮助我吗?
输入文件名为1.in,包含: 29 6 3 8 6 7 4 8 9 2 10 4 9 5 7 4 8 6 7 2 10 4 1 8 3 6 3 6 9 4
我使用./a.out< 1.in to run
输出应为:
. . . * . * . . . .
. . . * . * . * . .
. . * * . * * * * .
. * * * . * * * * *
* * * * * * * * * *
1 2 3 4 5 6 7 8 9 10
代码:
#include <stdio.h>
#include <stdlib.h>
int *readGrades() {
int x, count;
scanf("%d", &count);
int *grades = malloc(count * sizeof(int));
for (x = 0; x < count; ++x) {
scanf("%d", &grades[x]);
}
return grades;
}
void computeFrequencies(int grades[], int freq[10]){
int i;
int length=100;
for(i=0; i<length; i++){
grades[i]=i;
switch(i){
case 1: freq[1]++;
break;
case 2: freq[2]++;
break;
case 3: freq[3]++;
break;
case 4: freq[4]++;
break;
case 5: freq[5]++;
break;
case 6: freq[6]++;
break;
case 7: freq[7]++;
break;
case 8: freq[8]++;
break;
case 9: freq[9]++;
break;
default: freq[10]++;
}
}
}
int arrayMax(int length, int arr[]) {
int i, max = arr[0];
for (i=1; i < length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
void printHistogram(int freq[10]){
int highestGrade = arrayMax(10,freq);
int x;
int y;
for(x=highestGrade; x>0; x--) {
for(y=1; y<=10; y++) {
if(freq[y] < highestGrade && x > freq[y]) {
if(y==10) {
printf(".\n");
}
else {
printf(". ");
}
} else {
if(freq[y] <= highestGrade && x <= freq[y]) {
if(y==10) {
printf("*\n");
}
else {
printf("* ");
}
}
}
}
}
printf("\n");
printf("1 2 3 4 5 6 7 8 9 10\n");
}
int main(int argc, char *argv[]) {
int *grades;
int frequencies[10];
grades = readGrades();
computeFrequencies(grades, frequencies);
arrayMax(10,frequencies);
printHistogram(frequencies);
return 0;
}
答案 0 :(得分:1)
删除重新声明:
int i, grades[];
^^^^^^^^^
int freq[10]
具有误导性
因为它相当于int freq[]
freq
确实有10个元素长freq[10]
超出范围switch
没用 - 您可以在确定它在边界后直接使用i
答案 1 :(得分:1)
您的代码存在一些问题,我将按照外观的顺序进行讨论。
首先,摆脱“神奇数字”常数,这些常数在上下文中并不是很明显(它们通常不是真正的常量)。例如,直方图中的桶数(10
)。所以我将使用符号常量NFREQ来引用数字10,可以在包含之后使用预处理器宏#define NFREQ 10
来定义。
计算频率的函数中的另一个幻数是100
。除非我们将其作为参数传递,否则无法确保该数字是正确的。此问题会影响正确性,因为它在循环中使用并保护对内存的访问。如果该值太低,您将错过一些数据。相反,如果它太高,则通过读取数组的末尾(通常表现为分段错误)来获得未定义的行为。我们稍后会回到这个函数。我们先来看readGrades()
。
这是读取数据并存储输入的函数。这是您在运行时获取count
参数(我们在上面称为length
)的地方。当您返回值时,您还需要找到一种返回计数的方法。您可以将地址传递给将保存该值的变量。或者,您可以定义一个包含数据(等级)和长度的结构,并返回动态分配和填充的结构。因此,签名可能看起来像int *readGrades(int* cnt)
,并且在您设置的函数*cnt = count
内。
反过来,computeFrequencies()
现在需要额外的长度参数。您可以通过将freq数组的长度作为另一个参数传递来使函数更通用。
void computeFrequencies(int grades[], int freq[], int grades_len){
int i;
memset(freq, 0, sizeof(freq[0])*NFREQ); // (!) init freq array
for (i = 0; i < grades_len; ++i) {
freq[grades[i]-1]++;
}
}
不要忘记初始化freq数组。如果使用简单的printf循环打印中间结果或者检查调试器中的值,则很容易捕获此错误。在这里,我假设等级来自范围[1..10]
,并且等级总数相对较低,否则您需要沿y轴标准化为最大值。所以在这里,在简单的情况下,我们只是增加与等级数组中每个等级对应的桶中的计数器。
此外,为了使您的代码更加健壮,您可以添加一些代码来验证用户输入(如果键入字符而不是数字会发生什么?)。另外,您应该检查malloc
是否未返回NULL
。如果是这样,您的程序无法分配足够的内存,并且exit
应该带有表示错误行为的返回值(例如EXIT_FAILURE
)并打印相应的错误消息以通知用户。
arrayMax()
函数似乎工作正常,只要给定的长度与数组的实际长度匹配(您可以使用sentinel value代替)。它返回最常见等级的最高频率。
打印直方图的功能可以先进行修正,也可以稍微简化一下。一个问题是臭名昭着的越界访问(等级10的频率存储在freq[9]
)。请记住,C中的数组索引从0开始(因此y < NFREQ
,而不是<=
)。其余的代码是自我记录的。
void printHistogram(int freq[]){
int x, y, highestGrade = arrayMax(NFREQ, freq);
for (x = highestGrade; x > 0; --x) {
for (y = 0; y < NFREQ; ++y) {
if (freq[y] >= x && x <= freq[y])
printf("* ");
else
printf(". ");
if (y == NFREQ-1)
printf("\n");
}
}
printf("1 2 3 4 5 6 7 8 9 10\n");
}
最后,通过调用main
,您可以通过显式释放先前您不再需要的内存(free(grades);
中的return语句之前),显式释放您的纪律和意识。在你的情况下,它不是一个真正的问题,因为它将作为主函数返回被隐式释放。