- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个 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->word
(不 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
内存使用/错误检查
在您编写的任何动态分配内存的代码中,您对分配的任何内存块负有 2 个责任:(1) 始终保留指向起始地址的指针内存块,因此,(2) 它可以在不再需要时被释放。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出您分配的 block 的边界,尝试读取或基于未初始化的值进行条件跳转,最后, 以确认您释放了所有已分配的内存。
对于 Linux valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都易于使用,只需通过它运行您的程序即可。
$ 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)
始终确认您已释放所有分配的内存并且没有内存错误。
检查一下,如果您还有其他问题或者我是否以任何方式误解了您的问题,请告诉我。
关于c - 如何将字符数组(字符串)传递到链表(队列),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50383139/
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求提供代码的问题必须表现出对所解决问题的最低限度理解。包括尝试过的解决方案、为什么它们不起作用,以及预
为什么在 C# 中添加两个 char 结果是 int 类型? 例如,当我这样做时: var pr = 'R' + 'G' + 'B' + 'Y' + 'P'; pr 变量变为 int 类型。我希望它是
下面的代码可以编译,但 char 类型的行为与 int 类型的行为不同。 特别是 cout ::ikIsX >() ::ikIsX >() ::ikIsX >() using names
我正在寻找一个正则表达式,它可以匹配长度为 1 个或多个字符但不匹配 500 的内容。这将在 Rails 路由文件中使用,特别是用于处理异常。 路线.rb match '/500', to: 'err
对于 C 编程作业,我正在尝试编写几个头文件来检查所谓的“X 编程语言”的语法。我最近才开始,正在编写第一个头文件。这是我编写的代码: #ifndef _DeclarationsChecker_h_
为什么扩展的 ascii 字符(â、é 等)被替换为 字符? 我附上了一张图片...但我正在使用 PHP 从 MySQL 中提取数据,其中一些位置有扩展字符...我使用的是 Arial 字体。 您可以
我有一个与 R 中的断线相关的简单问题。 我正在尝试粘贴,但在获取(字符/数字)之间的断线时遇到问题。请注意,这些值包含在向量中(V1=81,V2=55,V3=25)我已经尝试过这段代码: cat(p
如何将 ANSI 字符 (char) 转换为 Unicode 字符 (wchar_t),反之亦然? 是否有用于此目的的任何跨平台源代码? 最佳答案 是的,在 中你有mbstowcs()和 wcsto
函数 fromCharCode 不适用于国际 ANSI 字符。例如,对于 ID 为 192 到 223 的俄语 ANSI (cp-1251) 字符,它返回特殊字符。如何解决这个问题? 我认为,需要将A
如果不喜欢,我想隐藏 id,但不起作用 SELECT * FROM character, character_actor WHERE character.id NOT LIKE character_a
现在这个程序成功地反转了键盘输入的单词。但是我想在我反转它之前“保存”指针中的单词,所以我可以比较两者,反转的和“原始的”,并检查它们是否是回文。我还没有太多经验,可能会出现比我知道的更多的错误,但我
Memcpy 和 memcmp 函数可以接受指针变量吗? char *p; char* q; memcpy(p,q,10); //will this work? memcmp(p,q,10); //w
恐怕我对一个相当过饱和的主题的细节有疑问,我搜索了很多,但找不到一个明确的答案来解决这个特定的明显-imho-重要的问题: 使用UTF-8将byte[]转换为String时,每个字节(8bit)都变成
我有一个奇怪的问题。我需要从 stat 命令打印输出字符串。 我已经编写了获取一些信息的代码。 import glob import os for file in glob.glob('system1
我正在使用 Java 并具有其值如下所示的字符串, String data = "vale-cx"; data = data.replaceAll("\\-", "\\-\\"); 我正在替换其中的“
String urlParameters = "login=test&password=te&ff"; 我有一个String urlParams,& - 是密码的一部分,如何使其转义,从而不被识别为分
大家好,我只想从此字符串中提取第一个字母: String str = "使 徒 行 傳 16:31 ERV-ZH"; 我只想获取这些字符: 使 徒 行 傳 并且不包括 ERV-ZH 仅数
这个问题已经有答案了: Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized point
所以, 我有一个字符**;它本质上是一个句子,带有指向该句子中每个单词的指针;即 'h''i''\0''w''o''r''l''d''\0''y''a''y''!''\0' 在这种情况下,我希望使用可
这个问题在这里已经有了答案: Using quotation marks inside quotation marks (12 个答案) 关闭 7 年前。 如何打印 " 字符? 我知道打印 % 符号
我是一名优秀的程序员,十分优秀!