简单的C链表程序可能存在内存问题

时间:2014-09-02 10:14:16

标签: c linked-list

我正在尝试编写一个程序,用于计算段落中单词的出现次数。

我遵循的逻辑:我正在使用链接列表。我正在按顺序搜索 - 如果新单词遇到在列表中添加单词,但如果单词已存在于列表中,则会增加其计数标记。

//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

我总是可以为同一个问题实现任何其他逻辑,但我想知道这个实现的问题。

提前致谢

2 个答案:

答案 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的内容复制到其中。

我希望这能解决你的问题。