我目前正在尝试编写一个应用程序来计算 ASCII 文件中单词的出现次数(标点符号被删除并忽略空格)。应用程序应该将单词和单词计数存储在一个数据结构中,最终将按降序排序,然后打印到 CSV 文件。
我已经开始使用这个程序,但是在尝试保存新单词时遇到了段错误。这是我的代码(我知道这不是一个完美的实现,我确实计划对其进行改进):
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
#define TRUE 1
#define FALSE 0
/* This program is designed to take an ASCII input file, count the occurrences of words in it
* and write an output file displaying the data. I intend for it to convert uppercase to
* lowercase, so as not to generate duplicate words in the data structure. It should also
* ignore whitespace and punctuation.
*/
void getWords(void);
void printFile(void);
void save(char *input);
struct word {
char *str;
int wc;
};
struct word *warray = NULL;
FILE *infile;
FILE *outfile;
void getWords(void)
{
rewind(infile);
char cw[100]; // Current word storage
int i = 0, j = 0, c;
while((c = fgetc(infile)) != EOF)
{
if(isalpha(c))
{
if(isupper(c))
{
cw[i] = tolower(c);
++i;
}
else
{
cw[i] = c;
++i;
}
}
else
{
if(c == '\n' || c == '\t' || c == ' ')
{
cw[i] = '\0';
i = 0;
save(cw);
for(j = 0; j < cw[99]; j++)
{
printf("%c", cw[j]);
}
}
}
}
}
void printFile(void)
{
int i, c;
printf("Printing the file to be counted in lowercase...\n");
for(i = 0; (c = fgetc(infile)) != EOF; i++)
{
if(ispunct(c) || isdigit(c))
{
++i;
}
else
{
putchar(tolower(c));
}
}
}
void save(char *input)
{
int exists = FALSE, i = 0;
int elements = sizeof(warray)/sizeof(struct word);
if(!warray)
{
warray = malloc(sizeof(struct word));
printf("Made array.\n");
}
else
{
printf("New.\n");
warray = realloc(warray, (elements++)*sizeof(struct word));
}
while(i < elements)
{
printf("in while loop\n");
if(strcmp(input, warray[i].str) == 0)
{
warray[i].wc++;
}
else
{
++i;
}
}
printf("Out while loop\n");
if(strcmp(input, warray[i].str) == 1)
{
printf("Inside save if statement\n");
warray[elements].str = malloc(strlen(input)+1);
strcpy(warray[elements].str, input);
warray[elements].wc = 1;
elements++;
}
}
int main (int argc, char *argv[])
{
if (argc < 3)
{
puts("Please supply the input filename and desired output filename as arguments.");
return 1;
}
infile = fopen(argv[1], "r");
if(infile == NULL)
{
printf("File failed to open. Error: %d\n", errno);
return 1;
}
else
{
puts("File opened successfully.");
printFile();
getWords();
}
return 0;
}
我已经放入了一些打印语句来尝试隔离问题,它似乎在这里遇到了问题,在
save(char *input)
函数中:if(strcmp(input, warray[i].str) == 1)
{
printf("Inside save if statement\n");
warray[elements].str = malloc(strlen(input)+1);
strcpy(warray[elements].str, input);
warray[elements].wc = 1;
elements++;
}
我确实有一种感觉,因为我要求 strcmp 检查它的值是否 == 1,当时也许我应该检查任何非零值,但我已经尝试过,但我仍然得到分段故障。
如果有人能指出我正确的方向,我将不胜感激,并提前致谢!
最佳答案
您的实现中有几个逻辑缺陷。从您的代码中,我假设您想要执行以下操作:
warray
是否为空。如果为空,则分配一个元素。 但是您的代码执行以下操作。
if(!warray)
{
warray = malloc(sizeof(struct word));
printf("Made array.\n");
}
这部分没问题。
else
{
printf("New.\n");
warray = realloc(warray, (elements++)*sizeof(struct word));
}
这不应该在这里。您应该先检查重复项,然后根据需要进行分配。
while(i < elements)
{
printf("in while loop\n");
if(strcmp(input, warray[i].str) == 0)
{
warray[i].wc++;
}
else
{
++i;
}
}
这是错误的。如果这个词已经存在,那么它会卡在
warray[i].wc++;
行中。您应该在增加计数器后返回。if(strcmp(input, warray[i].str) == 1)
{
printf("Inside save if statement\n");
warray[elements].str = malloc(strlen(input)+1);
strcpy(warray[elements].str, input);
warray[elements].wc = 1;
elements++;
}
这也是错误的。在上一个循环之后,
i
的值将等于 elements
的值。但是数组索引是从 0
到 elements-1
。所以 warray[i]
和 warray[elements]
都会导致段错误。 (您之前在 elements
行上增加了 warray = realloc(warray, (elements++)*sizeof(struct word));
的值)注意:
for(j = 0; j < cw[99]; j++)
函数中的 getwords
也可能导致段错误。编辑:我之前没有注意到后增量问题。它应该是
warray = realloc(warray, (++elements)*sizeof(struct word));
代替
warray = realloc(warray, (elements++)*sizeof(struct word));
感谢克罗诺斯。
关于c - 字数统计应用程序 - C,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21966834/