如何将一个字符数组(字符串)传递到链接列表(队列)

编码器

我有一个C程序代码,其中涉及将一个句子分为多个单独的单词,然后将这些单词放入一个链表中。我的问题是我是否应该将数据作为指针或字数组传递。

我在这里包括了部分代码。某些论坛曾说过使用strcpy传递字符串,但这是在我的* insert_at_foot函数中还是在数据结构中?

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

#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

谢谢大家:)

typedef struct node node_t;

/* word of max letters stored in each data_t value */
typedef char data_t[MAXLETTERS];

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

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

int 
main (int argc, char *argv[]){
    ...
    while(scanf("%s", getword(word, limit))!=EOF){
        insert_at_foot(list, word);
    }

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

    print_list(list);
  }

  list_t
*insert_at_foot(list_t *list, data_t word) { 
    node_t *new;
    new = (node_t*)malloc(sizeof(*new));
    assert(list!=NULL && new!=NULL);
    //strcpy(new->data, word);
    new->data = word;
    new->next = NULL;
    if (list->foot==NULL) {
        /* this is the first insertion into the list */
        list->head = list->foot = new;
    } else {
        list->foot->next = new;
        list->foot = new;
    }
    return list;
}
大卫·兰金

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

尽管有很多方法可以做到这一点,但一种非常有效的方法是word使用fgets(或POSIX getline简单地将每一行读入固定缓冲区(例如),然后使用<ctype.h>测试第一个字符ispunct()的工具isdigit()如果进行任何测试true,只需阅读下一行。这种方法的简单性意味着退出读循环时,读缓冲区中将包含最后一行。一个简单的实现是:

#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_at_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 (),您无法分配字符串。如评论中所述,问题的一个潜在根源是您键入了一个数组,该数组掩盖word了函数的类型很简单char*,您必须使用它strcpy来复制到new->wordnot new->word = word;

要解决此问题并整理功能并为添加验证检查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;
}

放在一起(并填写您在帖子中未提供的功能),一个工作示例可能类似于:

#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

内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于任何已分配的内存块,您都有两个责任:(1)始终保留指向该内存块的起始地址的指针,因此,(2)在没有内存块时可以将其释放需要更长的时间。

必须使用内存错误检查程序来确保您不尝试访问内存或不在分配的块的边界之外/之外写入,尝试读取或基于未初始化的值进行条件跳转,最后确认您可以释放已分配的所有内存。

对于Linuxvalgrind是正常的选择。每个平台都有类似的内存检查器。它们都很容易使用,只需通过它运行程序即可。

$ 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)

始终确认已释放已分配的所有内存,并且没有内存错误。

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

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

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

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何将一个字符串数组存储到另一个字符串数组中?

如何将一个字符串值传递给COUNTIF?

如何将“$@”或数组连接到一个字符串

如何将列表的子字符串转换为一个字符串

如何将一个字符串转换为字符串数组?

如何将一个字符串分成2个字符串

如何将字符串向量的最后一个字符大写?

Swift:如何将一个字符串数组拆分为多个匹配值数组?

如何将一个字符串值从<h:inputHidden>到bean属性?

如何将多个字符组合成一个字符串?

如何将一个字符串分成多行单个字符

如何将列表中的元素转换为一个字符串?

如何将一个字符串列表与另一个字符串列表匹配?

StructOpt:如何将所有参数组合在一个字符串中?

如何将一个字符串插入另一个字符串?

如何将一个字符串值与另一个字符串值进行比较?

如何将一个字符串与另一个字符串匹配并为其返回 true?

swift:如何将一个字符串从textField分配给另一个字符串?

Python如何将一个字符串分成几个阶段

熊猫:如何将行转换为一个字符串?

如何将下一个字符串分成几组?

如何将html内容转换为一个字符串

如何将一个字符串拆分为一个长度为3的字符串列表?

如何从字符串数组列表中删除一个字符串,ANDROID

如何将整数和字符串合并为一个字符串?

如何打印由另一个字符串链接列表组成的链接列表?

如何将一个字符串快速复制到另一个字符串的一部分中?

如何从字符串数组或arraylist创建一个字符串?

如何将一个char数组输入标记为一个char和一个字符串?