我正在尝试编写一个程序,用于计算段落中单词的出现次数。
我遵循的逻辑:我正在使用链接列表。我正在按顺序搜索 - 如果新单词遇到在列表中添加单词,但如果单词已存在于列表中,则会增加其计数标记。
//case insensitive string matching
int strcicmp(char const *a, char const *b)
{
int d;
for(;;a++,b++)
{
d=tolower(*a)-tolower(*b);
if(d!=0 || !*a)
return d;
}
}
//declare the linked list structure to store distinct words and their count
typedef struct node
{
char *word;
int count;
struct node *next;
} node;
node *ptr, *newnode, *first=NULL, *last=NULL;
void insertnewword(char *ch)
{
newnode=(node*)malloc(sizeof(node));
if(newnode == NULL)
{
printf("\nMemory is not allocated\n");
exit(0);
}
else
{
newnode->word=ch;
newnode->count=1;
newnode->next=NULL;
}
if(first==last && last==NULL)
{
first=last=newnode;
first->next=NULL;
last->next=NULL;
}
else
{
last->next=newnode;
last=newnode;
last->next=NULL;
}
}
void processword(char *ch)
{
int found=0;
//if word is already in the list, increase the count
for(ptr=first;ptr!=NULL;ptr=ptr->next)
if(strcicmp(ptr->word, ch) == 0)
{
ptr->count += 1;
found=1;
break;
}
//if it's a new word, add the word to the list
if(!found)
insertnewword(ch);
}
int main()
{
const char *delimiters=" ~`!@#$%^&*()_-+={[}]:;<,>.?/|\\\'\"\t\n\r";
char *ch, *str;
str=(char*)malloc(sizeof(char));
ch=(char*)malloc(sizeof(char));
//get the original string
scanf("%[^\n]%*c", str);
//fgets(str, 500, stdin);
//get the tokenized string
ch=strtok(str,delimiters);
while(ch!=NULL)
{
//a, an, the should not be counted
if(strcicmp("a", ch)!=0 && strcicmp("an", ch)!=0 && strcicmp("the", ch)!=0)
processword(ch);
ch=strtok(NULL,delimiters);
}
//print the word and it's occurrence count
for(ptr=first; ptr!=NULL; ptr=ptr->next)
printf("%s\t\t%d\n",ptr->word,ptr->count);
return 0;
}
对于少数几个单词似乎工作正常,但如果字数超过6-7,则此程序遇到一些问题。
说输入是:我是个好孩子。我是一个坏男孩。
输入应为
我是2 我2 好1 坏1 男孩2但我得到的是 我2 我2 好1 坏1 (一些垃圾字符)1
我总是可以为同一个问题实现任何其他逻辑,但我想知道这个实现的问题。
提前致谢
答案 0 :(得分:2)
我认为问题来自你的scanf:
in the man scanf:
the next pointer must be a pointer to char, and there must be enough room for all the characters in the string, plus a terminating null byte
但是在你的主要顶部,你的char数组的分配是一口之久:
str=(char*)malloc(sizeof(char));
我认为最好使用像getline这样的函数
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
并设置lineptr指向NULL
答案 1 :(得分:0)
我认为您的链接列表实现不会导致问题,但您的内存分配会导致实际问题。
第一个内存分配问题:
str=(char*)malloc(sizeof(char));
ch=(char*)malloc(sizeof(char));
这里str和ch应该有内存来保存完整的单词以及终止空字符,但是你只分配了一个字节(即char的大小)
第二个内存分配问题:
newnode->word=ch;
此代码片段存在于insertnewword()函数中。 在这里,您已为新节点分配了内存,但尚未为新节点内的char *字分配任何内存。之后,您直接将newnode-&gt; word指向ch,这是main()函数的局部变量。 当您完成第一个单词并进一步标记输入字符串时,ch包含字符串中的下一个单词。现在这可能会破坏链接列表中的数据,因为你已经将newnode-&gt; word直接指向ch。
因此请将内存分配给newnode中的字段,并将ch的内容复制到其中。
我希望这能解决你的问题。