Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何将字符数组(字符串)传递到链表(队列)中_C_Linked List - Fatal编程技术网

C 如何将字符数组(字符串)传递到链表(队列)中

C 如何将字符数组(字符串)传递到链表(队列)中,c,linked-list,C,Linked List,我有一个C程序代码,它将一个句子分割成单独的单词,并将这些单词放入一个链表中。我的问题是我是否应该将数据作为指针传递,还是传递到单词数组 我在这里包含了部分代码。一些论坛说使用strcpy传递字符串,但这是在my*insert_at_foot函数中还是在数据结构中 测试输入在这里,我想在运行scanf后读取最后一行以获取字典(在百分号之后) 谢谢大家:) 如果您仍在努力解决这个问题,那么您已经不远了,但是根据您提供的示例数据文件,您可以更轻松地读取和解析信息。如果查看该文件,您只关心读取最后一行

我有一个C程序代码,它将一个句子分割成单独的单词,并将这些单词放入一个链表中。我的问题是我是否应该将数据作为指针传递,还是传递到单词数组

我在这里包含了部分代码。一些论坛说使用strcpy传递字符串,但这是在my*insert_at_foot函数中还是在数据结构中

测试输入在这里,我想在运行scanf后读取最后一行以获取字典(在百分号之后)

谢谢大家:)


如果您仍在努力解决这个问题,那么您已经不远了,但是根据您提供的示例数据文件,您可以更轻松地读取和解析信息。如果查看该文件,您只关心读取最后一行数据并将其拆分为单词。查看前面的所有行,它们都以标点符号(
%
)开头,而最后一行以字母字符开头

虽然有很多方法可以做到这一点,但一种非常有效的方法是使用
fgets
(或POSIX
getline
)简单地将每一行读入一个固定的缓冲区(比如
word
),然后使用
中的工具测试第一个字符是
ispunt()
还是
isdigit()
。如果其中一项测试
为真
,只需阅读下一行即可。这种方法的简单性意味着当退出读循环时,读缓冲区中包含了最后一行。一个简单的实施方案是:

#define MAXLETTERS 256
...
    char word[MAXLETTERS] = "",   /* fixed buffer to hold each line */
        *p = word,                /* pointer to with for strtok */
        *delim = " \t\n";         /* delimiters to use with strtok */
    ...
    while (fgets (word, MAXLETTERS, stdin)) /* read/discard until last line */
        if (ispunct (*word) || isdigit (*word))
            continue;
        else
            break;
使用
word
中包含的行,您可以使用
strtok
根据您在此处指定的任何分隔符(
'
'\n'
)将行分隔为单个单词
strtok
返回一个指针,指向每个单词的开头,在每次连续调用时,指针将指向行中的下一个单词。对strtok的第一次调用使用包含行的缓冲区的名称,例如

    char word[MAXLETTERS] = "",   /* fixed buffer to hold each line */
    ...
    p = strtok (p, delim);        /* 1st call to strtok for 1st word */
每次连续调用都使用
NULL
代替
buf
,例如

    p = strtok (NULL, delim);     /* all subsequent calls use NULL */
strtok
到达原始字符串的末尾时,它将返回
NULL

注意:
strtok
在标记字符串时插入
'\0'
字符来修改字符串——因此,如果需要维护原始字符串,请复制原始字符串)

然后,只需将每个标记(单个单词)传递给
insert\u-at\u foot(list,p)
函数。您可以将所有步骤组合成一个简单的
for
循环,如下所示:

    /* tokenize last line using strtok */
    for (p = strtok (p, delim); p; p = strtok (NULL, delim))
        insert_at_foot (list, p);   /* insert word in llqueue */
insert_at_foot()
中,不能分配字符串。如注释中所述,问题的一个潜在来源是您使用了typedefed数组,该数组掩盖了函数中
word
的类型。它只是
char*
,您必须使用
strcpy
复制到
new->word
不是
new->word=word;

修复该问题,整理函数并为
列表添加验证检查,您可以执行以下操作:

list_t *insert_at_foot (list_t *list, char *word)
{
    node_t *new = malloc(sizeof *new);
    assert (list != NULL && new != NULL);   /* validate both list & node */

    strcpy (new->word, word);   /* you cannot assign strings, strcpy */
    new->next = NULL;           /* initialize next to NULL */

    if (list->foot==NULL) {     /* check if list is empty */
        /* this is the first insertion into the list */
        list->head = list->foot = new;
    }
    else {  /* additional nodes added at foot */
        list->foot->next = new;
        list->foot = new;
    }

    return list;
}
总而言之(并填写您在帖子中未提供的功能),一个工作示例可能类似于:

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

#define MAXLETTERS 256

typedef struct node node_t;

/* listops.c */
struct node {
    char word[MAXLETTERS]; //dereferences the first letter in data_t[MAXLETTERS]
    node_t *next;
};

typedef struct {
    node_t *head;
    node_t *foot;
} list_t;

list_t *insert_at_foot (list_t *list, char *word);

int is_empty_list (node_t *thenode)
{
    return thenode == NULL;
}

int main (void) {

    char word[MAXLETTERS] = "",
        *p = word,
        *delim = " \t\n";
    list_t *list = calloc (1, sizeof *list);    /* allocate list */

    while (fgets (word, MAXLETTERS, stdin)) /* read/discard until last line */
        if (ispunct (*word) || isdigit (*word))
            continue;
        else
            break;

    /* tokenize last line using strtok */
    for (p = strtok (p, delim); p; p = strtok (NULL, delim))
        insert_at_foot (list, p);   /* insert word in llqueue */

    // print_list(list);
    node_t *iter = list->head;      /* temp node to iterate over list */
    while (!is_empty_list(iter)) {  /* while node not NULL */
        node_t *victim = iter;      /* temp node to free */
        printf("%s\n", iter->word); /* output word saved in node */
        iter = iter->next;          /* set iter to next node */
        free (victim);              /* free current node */
    }
    free (list);    /* don't forget to free the list */
}

list_t *insert_at_foot (list_t *list, char *word)
{
    node_t *new = malloc(sizeof *new);
    assert (list != NULL && new != NULL);   /* validate both list & node */

    strcpy (new->word, word);   /* you cannot assign strings, strcpy */
    new->next = NULL;           /* initialize next to NULL */

    if (list->foot==NULL) {     /* check if list is empty */
        /* this is the first insertion into the list */
        list->head = list->foot = new;
    }
    else {  /* additional nodes added at foot */
        list->foot->next = new;
        list->foot = new;
    }

    return list;
}
示例使用/输出

$ ./bin/llqueue <dat/llqueue.txt
hugh
jackman
is
retiring
the
wolverine
character
after
logan
始终确认已释放所有已分配的内存,并且没有内存错误


仔细检查一下,如果您还有其他问题或我对您的问题有任何误解,请告诉我。

谢谢David的全面回答。我错过了这篇文章,但我最终能够使用char指针完成这部分代码,并使用strcpy将word数组复制到其中。现在可以了。我不熟悉我的类中的strtok(),但这段代码可能同样有效?我还有两个阶段需要使用二进制搜索树,并且会随着时间的推移而更新`int main(int argc,char*argv[]){


}

我目前正在使用二进制搜索来查看我的链接列表,如果在我的字典中找到一个单词作为第一个/最后一个/非名字,则将其相应地打印出来,例如在这个测试输出中。如果未找到,则将打印非名称。输入/输出

休伊特 5 95 0 #休 40 60 0 #杰克曼 0 100 0 #洛根 40 0 60 #墨尔本 5 5 90 #悉尼 5 5 90 #扎克 40 40 20 %%%%%%%%%% 休·杰克曼将在洛根之后让金刚狼角色退休 =================================================第一阶段========================= 姓名0:休伊特 标签概率:5%95%0% 第二阶段========================= 姓名数目:7 每个名称的平均字符数:5.86 第三阶段========================= 休 杰克曼 是 退休 这个 狼獾 性格 之后 洛根 第四阶段========================= 休姓,名 杰克曼姓 不是你的名字吗 退休不是你的名字 那不是你的名字 狼獾没有名字 字符不是你的名字 在没有你的名字之后
logan FIRST_NAME
不要
typedef
数组——它会让你感到非常困惑。。。。也不要使用
typedef
指针(同样的原因)。无法分配字符串(例如,
new->data=word;
)错误。(如果您是在启用警告的情况下编译的,则编译器应至少为您提供警告,
-Wall-Wextra
用于gcc/clang,
/W3
用于VS)。您必须使用
strcpy(newdata,word)
,因为
new->data
word
都是
insert\u at\u foot
中的
char*
,但您无法立即判断,因为您已经输入了
typedef char data\u t[maxlets]我可以建议退一步吗?你结合
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#define MAXLETTERS 256

typedef struct node node_t;

/* listops.c */
struct node {
    char word[MAXLETTERS]; //dereferences the first letter in data_t[MAXLETTERS]
    node_t *next;
};

typedef struct {
    node_t *head;
    node_t *foot;
} list_t;

list_t *insert_at_foot (list_t *list, char *word);

int is_empty_list (node_t *thenode)
{
    return thenode == NULL;
}

int main (void) {

    char word[MAXLETTERS] = "",
        *p = word,
        *delim = " \t\n";
    list_t *list = calloc (1, sizeof *list);    /* allocate list */

    while (fgets (word, MAXLETTERS, stdin)) /* read/discard until last line */
        if (ispunct (*word) || isdigit (*word))
            continue;
        else
            break;

    /* tokenize last line using strtok */
    for (p = strtok (p, delim); p; p = strtok (NULL, delim))
        insert_at_foot (list, p);   /* insert word in llqueue */

    // print_list(list);
    node_t *iter = list->head;      /* temp node to iterate over list */
    while (!is_empty_list(iter)) {  /* while node not NULL */
        node_t *victim = iter;      /* temp node to free */
        printf("%s\n", iter->word); /* output word saved in node */
        iter = iter->next;          /* set iter to next node */
        free (victim);              /* free current node */
    }
    free (list);    /* don't forget to free the list */
}

list_t *insert_at_foot (list_t *list, char *word)
{
    node_t *new = malloc(sizeof *new);
    assert (list != NULL && new != NULL);   /* validate both list & node */

    strcpy (new->word, word);   /* you cannot assign strings, strcpy */
    new->next = NULL;           /* initialize next to NULL */

    if (list->foot==NULL) {     /* check if list is empty */
        /* this is the first insertion into the list */
        list->head = list->foot = new;
    }
    else {  /* additional nodes added at foot */
        list->foot->next = new;
        list->foot = new;
    }

    return list;
}
$ cat dat/llqueue.txt
#hewitt
5 95 0
#hugh
40 60 0
#jackman
0 100 0
#logan
40 0 60
#melbourne
5 5 90
#sydney
5 5 90
#zack
40 40 20
%%%%%%%%%%
hugh jackman is retiring the wolverine character after logan
$ ./bin/llqueue <dat/llqueue.txt
hugh
jackman
is
retiring
the
wolverine
character
after
logan
$ valgrind ./bin/llqueue <dat/llqueue.txt
==22965== Memcheck, a memory error detector
==22965== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==22965== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==22965== Command: ./bin/llqueue
==22965==
hugh
jackman
is
retiring
the
wolverine
character
after
logan
==22965==
==22965== HEAP SUMMARY:
==22965==     in use at exit: 0 bytes in 0 blocks
==22965==   total heap usage: 10 allocs, 10 frees, 2,392 bytes allocated
==22965==
==22965== All heap blocks were freed -- no leaks are possible
==22965==
==22965== For counts of detected and suppressed errors, rerun with: -v
==22965== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
name_t name;        
name_t dict[MAXNAMES];

int limit = MAXLETTERS+NULL_BYTE;

list_t *list = make_empty_list();

char buffer[MAXLETTERS + NULL_BYTE];
char *word;

read_dict(&name, &dict[MAXNAMES]);

print_stage(STAGE3);

while(getword(buffer, limit) != EOF){
    //printf("Read a word: %s\n", buffer);
    word = (char *)malloc(strlen(buffer) + NULL_BYTE);
    strcpy(word, buffer);
    //printf("%s\n", word);
    insert_at_foot(list, word);
}


char percent= ' ';

while (!is_empty_list(list)) {
    word = *get_head(list);
    printf("%s\n", word);
    free(word);
    list = get_tail(list);
}

print_list(list); //unlesss printf(&list)

printf("\n");
free_list(list);
list = NULL;

return 0;