我试图找到频率这个词,我无法弄清楚为什么程序一直在崩溃..我已经尝试了很多方法,但我仍然遇到同样的崩溃。难道我做错了什么? *输入是一个书籍文件和我想要创建的新文件。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char *argv[] )
{
FILE *fp,*fp2;
int ch, total, counter, totalcounter, i;
int letters[25], letterfrequency[25];
for(i=0; i<25; i++)
{
letters[i] = 0;
letterfrequency[i] = 0;
}
printf("Opening: %s", argv[1]);
fp = fopen(argv[1], "r");
if (!fp)
{
perror("fopen");
exit(1);
}
while((ch=fgetc(fp)) != EOF)
{
if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
{
counter = toupper(ch);
ch = counter - 65;
letters[ch]++;
totalcounter++;
}
}
fp2 = fopen(argv[2], "w");
for(i=0;i<25;i++)
{
fprintf(fp2, "%c: Times used: %s\tFrequency Used: %s", i+65, letters[i], letters[i]/totalcounter);
}
fclose(fp);
fclose(fp2);
return 0;
}
答案 0 :(得分:3)
您的代码存在许多问题。首先是它有警告。这些警告指出了问题。不幸的是,大多数C编译器默认情况下不会向您显示警告。您必须使用-Wall
启用它们。但-Wall
并不代表“所有警告”,哦不。如果你问为什么,简短的回答是C是数十年可疑设计选择的积累,习惯它。 : - /我运行了更多的警告和检查:-Wall -Wwrite-strings -Wextra -Wconversion -std=c99 -pedantic -g
。
有一堆未使用和未初始化的变量,你的printf规范是错误的,而你错过了include
toupper
。我会让你解决所有问题。
接下来的问题是你将letters
初始化为25长,但字母表有26个字符。幸运的是,你也只是迭代了25次,但这意味着你将失去'Z'。这是一个容易犯的错误。 26项长数组从0到25,但其长度为26。
不是在整个地方重复数组的长度,而是可能错过一个,最好在一个地方定义它。
#define NUM_LETTERS 26
然后有一种更快速,更简单的方法来初始化数组。
int letters[NUM_LETTERS] = {0};
没有必要指定每个元素,C将用最后一个元素填充其余元素。
由于在非某个字符的内容上调用toupper
是完全安全的,它只会使字符不变,您可以简化while
循环。
while((ch=fgetc(fp)) != EOF) {
ch = toupper(ch);
if( 'A' <= ch && ch <= 'Z' ) {
ch -= 65;
letters[ch]++;
totalcounter++;
}
}
请注意我使用的样式'A' <= ch && ch <= 'Z'
。这样可以更轻松地查看从ch
到A
范围内检查Z
。
下一个问题是:letters[i]/totalcounter
。
在C中,如果你除以两个整数,你会得到一个整数。这意味着20/100
为0
。如果需要小数,则必须将其中一个变量转换为浮点类型:(double)letters[i]/totalcounter)
。
可能没有从文件中读取字母而totalcounter
为0.如果是这样letters[i]/totalcounter
将导致被零除错误。所以你必须检查那个案例。
if( totalcounter != 0 ) {
for( i=0; i<NUM_LETTERS; i++ ) {
printf("%c: Times used: %d\tFrequency Used: %f\n",
i+65, letters[i], (double)letters[i]/totalcounter
);
}
}
else {
printf("No letters found.\n");
}
您无法检查用户是否为您提供了文件名参数。如果他们不这样做,你的程序将崩溃。添加使用情况检查非常重要。
if( argc < 2 ) {
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
exit(1);
}
请注意,我没有将结果写入文件,而且我的版本只有一个文件,一个要阅读的文件。我的版本输出到stdout。
通常,将程序结果打印到stdout比打印到文件更好。这使程序能够很好地与外壳管道配合使用,使其更加灵活。
./wordcount somefile # output to the screen
./wordcount somefile.txt > somefile.count # output to a file
./wordcount somefile.txt | program # output to another program
答案 1 :(得分:1)
更改您的数组以获取所有字母,即int letters[26];
另一个letterfrequence
您似乎不会用于任何事情
您的fprintf
格式说明符错误
你有
fprintf(fp2, "%c: Times used: %s\tFrequency Used: %s",
i+65, letters[i], letters[i]/totalcounter);
但是letters
是一个int数组,所以正确的说明符应该是%d
(int)而不是%s
(string)
您尚未初始化totalcounter
,因此可能会发生0分割或其他任意分割。
toupper
位于标题ctype.h
中,标题丢失。