将节点添加到链表的功能不起作用 C

娜塔莉·劳埃德(Natalie Lloyd)

我有以下程序,该程序从文本文件读取单词并创建一个链接列表,每个节点包含:单词,计数,下一个。

当链接列表中已存在单词时,将更新计数,否则,将在链接列表的末尾创建一个节点。

除了在链接列表末尾添加一个单词的功能以外,我所有的功能都起作用。节点的链接可能存在错误?

输入以下文本文件:第1行“我的名字是natalie”,第2行“我的狗是niko”我应该得到以下输出:my(2),name(1),is(2),natalie(1), dog(1),niko(1)但我得到:my(2),dog(2),s(1),iko(1),is(1),niko(1)

我的错误在哪里?

//function to add word to linked list
struct WordNode *addWord(char* word, struct WordNode *wordListHead){
        //create new node
        struct WordNode *current = malloc(sizeof(struct WordNode));
        current->word = word;
        current->count = 1;
        current->next = NULL;

        //
        while(1){
                if((wordListHead != NULL)&&(wordListHead->next ==NULL)){
                        //connect 
                        wordListHead->next=current;
                        break;
                }
                wordListHead = wordListHead->next;
        }

}

主要在这里调用:

char *filename = argv[1];
        FILE *fp = fopen(filename, "r");
        printf("%s\n", filename);
        if (fp == NULL){
                printf("Error: unable to open the file ");
                printf("%s", filename);
                return 1;
        }

        else {

                char *delim = " \t\n,:;'\".?!#$-><(){}[]|\\/*&^%@!~+=_"; // These are our word delimiters.
                char line[1000];
                char * token;
                int count = 0;//count used so that first word of the doc can be created as head node
                //create head pointer
                struct WordNode *wordListHead = NULL;
                //create current pointer 
                struct WordNode *current = NULL;

                //iterate through each line in file
                while(fgets(line, 1000, fp)){
                        //seperate each word

                        //first word of line
                        token = strtok(line, delim);
                        printf("%s\n", token);

                        if(count == 0){
                                //first word of document, create first wordnode (head node)
                                wordListHead = malloc(sizeof(struct WordNode));
                                wordListHead->word = token;
                                wordListHead->count = 1;
                                wordListHead->next = NULL;
                        }

                        else{
                                //check if first word of line exists in linked list
                                if((doesWordExist(token, wordListHead)) == 0){
                                        //update count
                                        updateCount(token, wordListHead);
                                }
                                else{
                                        //create node
                                        addWord(token, wordListHead);
                              }
                        }


                        //iterate through all the other words of line
                        while ((token=strtok(NULL, delim)) != NULL){
                                printf("%s\n", token);

                                //check if name is in linked list
                                if((doesWordExist(token, wordListHead)) == 0){
                                        //update count
                                        updateCount(token, wordListHead);
                                }
                                else{
                                        //create node
                                        addWord(token, wordListHead);
                                }
                        }
                        count++;
                }
                printWordList(wordListHead);

        }

}


此处定义的结构:

//structure definition of linked list node
#ifndef WORDLISTH
#define WORDLISTH
struct WordNode{
        char *word;
        unsigned long count;
        struct WordNode *next;
};
void printWordList( struct WordNode *wordListHead);

struct WordNode *addWord(char* word , struct WordNode *wordListead);

#endif

其他功能供参考:

//function to check if word is in linked list
bool doesWordExist(char* myword, struct WordNode *wordListHead){

        while (wordListHead != NULL){
                if(strcmp(wordListHead->word, myword) == 0){
                        return 0;
                }
                wordListHead= wordListHead-> next;
        }
        return 1;
}

//function to update the count of word 
void updateCount(char* myword, struct WordNode *wordListHead){

        while (wordListHead != NULL){
                if(strcmp(wordListHead->word, myword) == 0){
                        //update count value
                        //capture current count and add 1
                        int curcount = wordListHead->count;
                        int newcount = curcount + 1;
                        wordListHead->count = newcount;
                        //printf("%d\n", newcount);
                }
                wordListHead= wordListHead-> next;
        }

}
//function to print word list
//takes head node as argument
void printWordList( struct WordNode *wordListHead){
        //WordNode *toyptr = wordListHead;
        while (wordListHead != NULL){
                printf("%s\n", wordListHead->word);
                printf("%ld\n", wordListHead->count);
                wordListHead = wordListHead -> next;
        }
}
克雷格·埃斯蒂

当存储token到结构中时,将使用作为输入缓冲区一部分的指针。

在新的输入行上,从前几收集的令牌将被破坏/清除。

您需要分配空间以将令牌存储在堆上的结构中。使用strdup了点。

因此,在中addWord,您想要:

current->word = strdup(word);

在中main,您想要:

wordListHead->word = strdup(token);

更新:

这是主要问题。但是,您的代码做了很多不必要的复制。

addWord不处理空列表。但是,如果这样做,则无需为该main行的第一个单词和后续单词使用单独的[复制]代码。

strcmp可纳入addWord它可以“做到这一切。” (即列表一次扫描)

对于doesWordExist,它bool在匹配项上返回a 如果将指针返回到匹配的元素,则updateCount只需增加计数即可(而不重新扫描列表)。我已经相应地更新了这些功能,但是由于对addWord

这是我将简化和重构代码的方式:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int bool;

#ifdef DEBUG
#define dbgprt(_fmt...) \
    printf(_fmt)
#else
#define dbgprt(_fmt...)     do { } while (0)
#endif

//structure definition of linked list node
#ifndef WORDLISTH
#define WORDLISTH
struct WordNode {
    char *word;
    unsigned long count;
    struct WordNode *next;
};
void printWordList(struct WordNode *wordListHead);

#endif

//function to add word to linked list
struct WordNode *
addWord(char *word, struct WordNode **list)
{
    struct WordNode *curr;
    struct WordNode *prev = NULL;
    struct WordNode *newnode = NULL;

    for (curr = *list;  curr != NULL;  curr = curr->next) {
        if (strcmp(curr->word,word) == 0) {
            newnode = curr;
            break;
        }
        prev = curr;
    }

    // create new node
    do {
        // word already exists
        if (newnode != NULL)
            break;

        newnode = malloc(sizeof(struct WordNode));
        newnode->word = strdup(word);
        newnode->count = 0;
        newnode->next = NULL;

        // attach to tail of list
        if (prev != NULL) {
            prev->next = newnode;
            break;
        }

        // first node -- set list pointer
        *list = newnode;
    } while (0);

    // increment the count
    newnode->count += 1;

    return newnode;
}

//function to check if word is in linked list
struct WordNode *
findWord(char *myword, struct WordNode *head)
{
    struct WordNode *curr;

    for (curr = head;  curr != NULL;  curr = curr->next) {
        if (strcmp(curr->word,myword) == 0)
            break;
    }

    return curr;
}

//function to update the count of word
void
updateCount(char *myword, struct WordNode *head)
{
    struct WordNode *match;

    match = findWord(myword,head);
    if (match != NULL)
        match->count += 1;
}

//function to print word list
//takes head node as argument
void
printWordList(struct WordNode *head)
{
    struct WordNode *curr;

    for (curr = head;  curr != NULL;  curr = curr->next) {
        printf("%s", curr->word);
        printf(" %ld\n", curr->count);
    }
}

int
main(int argc, char **argv)
{
    char *filename = argv[1];
    FILE *fp = fopen(filename, "r");

    printf("FILE: %s\n", filename);
    if (fp == NULL) {
        printf("Error: unable to open the file ");
        printf("%s", filename);
        return 1;
    }

    // These are our word delimiters.
    char *delim = " \t\n,:;'\".?!#$-><(){}[]|\\/*&^%@!~+=_";

    char line[1000];
    char *token;

    // create head pointer
    struct WordNode *wordListHead = NULL;

    // iterate through each line in file
    while (fgets(line, sizeof(line), fp)) {
        // seperate each word

        // first word of line
        char *bp = line;

        while (1) {
            token = strtok(bp, delim);
            bp = NULL;

            if (token == NULL)
                break;

            dbgprt("TOKEN1: %s\n", token);

            addWord(token,&wordListHead);
        }
    }

    printWordList(wordListHead);

    return 0;
}

更新#2:

注意,addWordfindWord复制代码。的第一部分addWord是[基本上]复制findWord工作。

但是,addWord不能只使用findWord[这将是可取的],因为findWord,如果它不能找到一个匹配的回报NULL在这种情况下,它[没有办法]回传addWord需要追加的最后一个元素(即列表的“尾部”)

尽管我们可以添加一个额外的参数来findWord传播该值,但更好的解决方案是创建一个定义“列表”的不同结构。

在现有代码中,我们使用指向单词头节点的“双星”指针作为“列表”。使用单独的结构更清洁,并具有一些其他优点。

我们只需传递一个指向列表的简单指针即可。我们不再需要担心我们是否应该传递双星指针。

尽管我们仅使用链接列表,但如果我们希望将列表转换为链接列表,则可以使用单独的列表结构[稍后]。

我们只需要传递一个指向列表的指针,列表就可以跟踪列表的开头,列表的尾部以及列表中元素的数量。

链接列表很适合与进行排序mergesort列表计数有助于提高效率,因为查找列表的“中点”(合并排序需要知道)要容易得多。

为了显示双向链表的开头,我在prevstruct这个词中添加了一个元素。目前尚未使用,但它暗示了双向链接的版本。

我重新设计了所有函数,以使用指向列表的指针,而不是指向头节点的指针。

因为列表结构具有tail指针,addWord所以现在可以调用findWord如果findWord确实没有找到匹配,addWord可以简单地使用head/tail指针在列表中找到正确的插入点。

为了进一步简化,我更改了节点[和列表结构]一词以使用某些typedef语句。

同样,将占主导地位的struct指针作为第一个参数是更常见/惯用的,因此我已经颠倒了某些函数上参数的顺序。

无论如何,这是[更多]重构代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int bool;

#ifdef DEBUG
#define dbgprt(_fmt...) \
    printf(_fmt)
#else
#define dbgprt(_fmt...)     do { } while (0)
#endif

//structure definition of linked list node
#ifndef WORDLISTH
#define WORDLISTH

// word frequency control
typedef struct WordNode Word_t;
struct WordNode {
    const char *word;
    unsigned long count;
    Word_t *next;
    Word_t *prev;
};

// word list control
typedef struct {
    Word_t *head;
    Word_t *tail;
    unsigned long count;
} List_t;

void printWordList(List_t *list);

#endif

// create a list
List_t *
newList(void)
{
    List_t *list;

    list = calloc(1,sizeof(*list));

    return list;
}

// function to check if word is in linked list
Word_t *
findWord(List_t *list,const char *myword)
{
    Word_t *curr;

    for (curr = list->head;  curr != NULL;  curr = curr->next) {
        if (strcmp(curr->word,myword) == 0)
            break;
    }

    return curr;
}

//function to add word to linked list
Word_t *
addWord(List_t *list,const char *word)
{
    Word_t *match;

    do {
        // try to find existing word
        match = findWord(list,word);

        // word already exists
        if (match != NULL)
            break;

        // create new node
        match = malloc(sizeof(*match));
        match->word = strdup(word);
        match->count = 0;
        match->next = NULL;

        // attach to head of list
        if (list->head == NULL)
            list->head = match;

        // append to tail of list
        else
            list->tail->next = match;

        // set new tail of list
        list->tail = match;

        // advance list count
        list->count += 1;
    } while (0);

    // increment the word frequency count
    match->count += 1;

    return match;
}

//function to update the count of word
void
updateCount(List_t *list,const char *myword)
{
    Word_t *match;

    match = findWord(list,myword);
    if (match != NULL)
        match->count += 1;
}

//function to print word list
//takes head node as argument
void
printWordList(List_t *list)
{
    Word_t *curr;

    for (curr = list->head;  curr != NULL;  curr = curr->next) {
        printf("%s", curr->word);
        printf(" %ld\n", curr->count);
    }
}

int
main(int argc, char **argv)
{
    char *filename = argv[1];
    FILE *fp = fopen(filename, "r");

    printf("FILE: %s\n", filename);
    if (fp == NULL) {
        printf("Error: unable to open the file ");
        printf("%s", filename);
        return 1;
    }

    // These are our word delimiters.
    char *delim = " \t\n,:;'\".?!#$-><(){}[]|\\/*&^%@!~+=_";

    char line[1000];
    char *token;

    // create list/head pointer
    List_t *list = newList();

    // iterate through each line in file
    while (fgets(line, sizeof(line), fp) != NULL) {
        // seperate each word

        // first word of line
        char *bp = line;

        while (1) {
            token = strtok(bp, delim);
            bp = NULL;

            if (token == NULL)
                break;

            dbgprt("TOKEN1: %s\n", token);

            addWord(list,token);
        }
    }

    printWordList(list);

    return 0;
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

C ++朋友功能不起作用

C 中在单向链表末尾添加节点的函数不起作用

将节点添加到C中的链表时,EXC_BAD访问

C ++:按字母顺序将节点添加到双向链表

删除链表节点,C++ 函数不起作用

C# 拆分功能不起作用

mysql c api mysql 查询功能不起作用

C#模糊功能不起作用

C ++堆栈实现弹出功能不起作用

向量擦除功能不起作用C ++

C:使用链表将数据添加到结构

如何在没有头/尾指针的情况下将多个节点添加到C中的链表?

添加到地图的类中的互斥体不起作用C ++

在JavaScript中将光标移动功能添加到对象创建功能不起作用

为什么将EXE文件转换为二进制代码,添加到C并重新创建,为什么不起作用?

C++ - 将节点设置为 NULL 不起作用

添加到购物车按钮不起作用,Selenium C# 元素不可交互

在c ++中将元素添加到空向量中:为什么push.back有效,[]不起作用

C#使用目录服务将用户添加到Active Directory,启用属性不起作用

为什么此交换功能不起作用?(在C中交换字符串)

重命名和删除txt文件的功能不起作用C ++

C-编译时没有错误,但功能不起作用

将VSIX功能添加到C#类库

此功能中的功能不起作用,添加到收藏夹电子商务项目

将元素添加到已排序的链表C ++中时出现的问题

尝试将键:值对添加到 res.locals.object 不起作用(节点/快递)

添加功能不起作用

如何将XML子节点添加到父节点C#

链表上的插入功能不起作用