c 链表 - 是否可以创建一个独立于有效负载的迭代器函数?

2023-12-12

所有,在我的应用程序中,我有许多正在创建的链接列表。例如,一个(struct record)保存具有数百个节点(文本行)的转录文本,而第二种类型的链接列表(struct srch_results)保存使用 strstr() 搜索第一个列表的搜索结果。应用程序中每个列表可以有多个列表。问题是我发现自己为每个列表类型重新创建每个正向/反向迭代器,这基本上是复制代码并更改列表的结构类型。例如,一组遍历struct record的函数和一组遍历struct srch_results的函数是:

// Simple structure to use as the base for depo double linked list
struct record
{
char *line;
int lineno;
int linetype;
struct record *prev;
struct record *next;
};

typedef struct record rec;

// Simple structure to use as the base for search results double linked list
struct srch_results
{
char *lineptr;
struct record *node;
struct srch_results *prev;
struct srch_results *next;
};

typedef struct srch_results srchres;

// general functions to operate on 'rec' type

void
rec_prn_node (rec *node) {
fprintf (stdout, "%s()  prev: %p  cur: %p  next: %p\n", __func__, node->prev, node, node->next);
}

void
rec_prn_payload (rec *node) {
fprintf (stdout, "%s() lineno: %d, linetype: %d line: %s\n",
    __func__, node->lineno, node->linetype, node->lineptr);
}

void
rec_iterfwd (void fnc (srchres *list), srchres *list) {

rec *iter = list;   // second copy to iterate list

if (iter ==  NULL) {
    fprintf (stdout,"%s(), The list is empty\n",__func__);
} else {
    do {
    fnc (iter);
    iter = iter->next;
    } while (iter != list);
}
}

// general functions to operate on 'srchres' type

void
srch_prn_node (srchres *node) {
fprintf (stdout, "%s()  prev: %p  cur: %p  next: %p\n", __func__, node->prev, node, node->next);
}

void
srch_prn_payload (srchres *node) {
fprintf (stdout, "%s() node: %p lineptr: %s\n", __func__, node->node, node->lineptr);
}

void
srch_iterfwd (void fnc (srchres *list), srchres *list) {

srchres *iter = list;   // second copy (set to last) to iterate list

if (iter ==  NULL) {
    fprintf (stdout,"%s(), The list is empty\n",__func__);
} else {
    printf ("in %s()\n", __func__);
    do {
    fnc (iter);
    iter = iter->next;
    } while (iter != list);
}
}

有没有办法创建可以在任一列表上操作的通用 void 迭代器类型?一些通用迭代器和通用 typedef 允许传递回调函数和列表地址,以便迭代器遍历给定列表,调用每个节点上提供的函数?

所有结构都具有结构地址和地址->下一个、地址->上一个。我尝试根据其他一些利用回调的 void 迭代器函数来定义 void * 函数,但我似乎不是在我传递的列表中迭代地址,而是从堆栈中获取地址。 (即 list->prev 是堆栈上前一个列表的地址,而不是列表中前一个节点的地址)。好消息是,通缉列表地址实际上最终出现在回调中,只是不是以我想要的可用方式。

// generic linked-list-iterator struct to hold (prev: cur: next:) pointers
struct lliterator
{
struct lliterator *prev;
struct lliterator *next;
};

typedef struct lliterator lliter;

void *
srch_prn_node (lliter *node) {
fprintf (stdout, "%s()  prev: %p  cur: %p  next: %p\n", 
    __func__, node->prev, node, node->next);
return NULL;
}

void iterator (void *fnc (void *list), void *list) {

lliter *iter = list; // second copy (set to last) to iterate list

if (iter ==  NULL) {
    fprintf (stdout,"%s(), The list is empty\n",__func__);
} else {
    do
    {
    fnc (iter);
    iter = iter->next;
    } while (iter != list);
}
}

// called in the code as

iterator ((void *)srch_prn_node2, (void *)sresults);

这可能是不可能的,但目的是将现有结构地址作为 void 传递,然后使用 typedef 结构迭代器对该地址进行操作,该迭代器包含与传递的每个列表中包含的成员等效的 ->next 和 ->prev 成员。上面的示例可以编译,但运行时,当回调到达堆栈上的最后一个列表时,它会出现段错误。 (即,创建一个结构体记录和一个结构体 srch_results 后,它将迭代两次,在出现段错误之前为每个列表提供地址。这样的事情是否可能,或者是否缺少我能够找到答案的示例?


你有多种选择。

1)使用TAILQ宏see here.

2) 创建一个包含指向数据的通用指针的节点链表:

typedef struct Node {
    struct Node *prev;
    struct Node *next;
    void *data;
} Node;

然后您可以迭代列表Nodes,并投射data指向您认为列表包含的任何类型的指针。在这种情况下,Node必须独立于数据进行分配。另外,如果您从其他指针访问数据,您将无法找到关联的数据Node除非数据指向Node.

3)创建一个没有数据指针的节点,并将其嵌入到您的数据结构中。

typedef struct Node {
    struct Node *prev;
    struct Node *next;
} Node;

typedef struct DataA {
    char something;
    Node node;
    int whatever;
} DataA;

typedef struct DataB {
    char dunno;
    Node node;
    int noclue;
} DataB;

然后您可以从指针转换为Node通过向后移动指针来指向指向封闭数据的指针:

DataA *p = (DataA*)((uintptr_t)pNodeA - offsetof(DataA, node));
DataB *p = (DataB*)((uintptr_t)pNodeB - offsetof(DataB, node));

请注意,如果您将Node在数据开始时,您不需要调整指针的值,因此您可以简单地从Node* to DataA* or DataB*.

在这种情况下,每条数据都有自己的Node,并且你不需要Node和数据相互指向。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c 链表 - 是否可以创建一个独立于有效负载的迭代器函数? 的相关文章

  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • 计算另一个表达式中的 C# 表达式

    我想在另一个表达式中使用一个表达式 Expression
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 使用 LINQ 更新 IEnumerable 对象的简单方法

    假设我有一个这样的业务对象 class Employee public string name public int id public string desgination public int grade List
  • 使用查询表达式对 List 进行排序

    我在使用 Linq 订购这样的结构时遇到问题 public class Person public int ID get set public List
  • 使用 C# 和 wpf 创建类似 Dock 的应用程序

    我需要创建一个与我们购买笔记本电脑时获得的应用程序类似的应用程序 仅当鼠标指针到达窗口顶部时它才可见 那么我怎样才能使用 C 4 0 来做到这一点呢 http www notebookcheck net uploads pics win2
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 析构函数中的异步操作

    尝试在类析构函数中运行异步操作失败 这是代码 public class Executor public static void Main var c1 new Class1 c1 DoSomething public class Class
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • Project Euler #8,我不明白我哪里出了问题[关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我正在做项目欧拉第八题 https projecteuler net problem 8 其中我得到了这个大得离谱的数字 7316
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • 选择查询不适用于使用Parameters.AddWithValue 的参数

    C 中的以下查询不起作用 但我看不出问题所在 string Getquery select from user tbl where emp id emp id and birthdate birthdate cmdR Parameters
  • 使用 jQuery 从 ASP.Net JSON 服务获取数据

    我正在尝试调用 Google 地图地理编码 API 从纬度 经度对中获取格式化的地址 然后将其记录到控制台 我正在尝试获取为给定位置返回的第一个 formatted address 项目 我很简单无法从 JSON 中提取该项目 我不知道为什
  • 如何调试 .NET 运行时中的内部错误?

    我正在尝试调试一些处理大文件的工作 代码本身works 但 NET 运行时本身会报告零星错误 对于上下文 这里的处理是一个 1 5GB 文件 仅加载到内存中一次 在循环中处理和释放 故意尝试重现此否则不可预测的错误 我的测试片段基本上是 t
  • 如何在 winforms 应用程序的主屏幕显示之前显示欢迎屏幕?

    我想在应用程序启动时加载欢迎屏幕 然后用户单击欢迎屏幕上的按钮 然后关闭欢迎屏幕 最后显示主屏幕 static void Main startup method being called Application EnableVisualSt
  • 如何使用placement new重新初始化该字段?

    我的课程包含字段 private OrderUpdate curOrderUpdate 我一遍又一遍地使用它 经常需要重新初始化 for int i 0 i lt entries size i auto entry entries i ne
  • 结构化绑定的用例有哪些?

    C 17 标准引入了新的结构化绑定 http en cppreference com w cpp language structured binding功能 最初是proposed http www open std org jtc1 sc
  • 为什么匹配模板类上的部分类模板特化与没有模板匹配的另一个部分特化不明确?

    这个问题可能很难用标题中的句子来描述 但这里有一个最小的例子 include
  • 使用未分配的局部变量

    我遇到了一个错误 尽管声明了变量 failturetext 和 userName 错误仍然出现 谁能帮帮我吗 Use of Unassigned local variable FailureText Use of Unassigned lo

随机推荐

  • 从 GCS 提供具有访问限制的静态页面

    我正在谷歌云存储上提供静态页面 只要它是公开的 它就可以很好地工作 现在我设置了 acl 以便只有一组用户可以读取存储 未经身份验证的用户将被重定向到 google 身份验证 现在的问题是 网站的静态内容 例如 javascript 和 c
  • PHP 中两个日期之间的完整天数?

    我将日期存储在 MySQL 表中 格式为 yyyy mm dd 或典型的 MySQL 日期 格式 我怎样才能知道距离那时还剩多少天 例如 如果我有 2011 03 05 它会说 17 More Days In PHP days strtot
  • 如何在 Chart.JS 中显示饼图的数据子集,同时在悬停时仍显示超集?

    我有一个饼图 当鼠标悬停在一块饼上时 它看起来像这样 除了想要传奇在右边而不是在上面 我对此相当满意 但我只想在饼图中 始终 显示百分比值 并且仍然有
  • 如何实现通用接口?

    我刚刚看到 Go 在其最新版本中合并了泛型 我正在尝试创建一个小项目来了解它是如何工作的 除了现在通用的非常简单的功能之外 我似乎不知道它是如何工作的 我希望能够做这样的事情 type Dao RT any interface FindOn
  • Android 中的 SD 卡文件浏览器

    如何在Android中制作一个文件浏览窗口来访问 浏览和打开SD卡的FAT32内容 看看这个例子 http www remwebdevelopment com dev a34 Directory Browser Application ht
  • 如何在 Snowflake UI 中导出插入语句

    我如何获得出口insertSnowflake UI 中的语句 就像我在 SQL Developer 中可以得到的那样 有一个选项可以获取 csv 和 tsv 格式的数据 但不是insert声明 最简单的方法是使用支持导出到 SQL 的外部工
  • “Táco”比“Taco”更宽。我该如何解决这个问题?

    我正在尝试在没有变音符号的 div 之上加载带有变音符号的 div 不过 间距并不像我那样有效 请参阅下面的代码片段 我该如何解决这个问题 div text width 75 position relative div diacritics
  • 将物体放置在人上方 30 米处

    是否可以将一个物体放置在 30 或 50 米高的人正上方 当我尝试放置链接到锚点的对象时 它在 20 米内可见 在 40 米内不可见 为什么会发生这种情况以及如何配置 It is frustum cullingARCore 中的问题 不在相
  • VS2010 中每个发布配置文件的不同连接字符串

    是否可以根据所选的网络发布配置文件更改连接字符串 或仅服务器主机 也许使用Web config 转换或者其他什么方式 我的意思是 对于配置文件 Test 将连接字符串 MyConnString 在已发布的 Web config 中 更改为
  • 在 x86 上的 C/C++ 中,参数传递和返回值如何在程序集级别工作? [关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我试图找出在 C C 中调用函数时如何传递函数的参数以及如何在程序集级别返回函数的返回值 我找到了这些答案 汇编 x86 调用 C 函数 参数传递如何工作 这说明堆栈用于在 C
  • 如何在没有 scene2d 的情况下检测纹理是否已被触摸 libgdx

    我想知道是否有办法在不使用 scene2d 的情况下检测某个纹理上的触摸 Gdx input isTouched 检测整个屏幕上的触摸 有没有一种方法可以使用无需 scene2d 即可检测纹理上的触摸的方法 当然有 我也从来不使用scren
  • CakePHP 可以自动从模型创建表吗?

    在 python Pylons 中 我可以发出 setup app 命令 它将查看我的模型并为我的特定数据库发出适当的 CREATE TABLE 或 CREATE INDEX ddl 这似乎是 CakePHP 中的一个功能 但我找不到它 事
  • 更多c++多重继承的乐趣[重复]

    这个问题在这里已经有答案了 可能的重复 C 指针多重继承的乐趣 跟进 C 指针多重继承的乐趣 我正在编写一些涉及从基本引用计数指针类继承的代码 并且出现了一些 C 的复杂问题 我已将其减少如下 假设我有 class A int x y cl
  • Angular forkJoin 订阅未触发

    我有几种形式的方法 getFirstDataBunch return this repository getData this parameter pipe switchMap result gt Do something with res
  • 解析 WordPress 帖子内容

    我有一个奇怪的布局 即使在规划阶段 我也不知所措 本质上我需要分离出所有不属于 gallery并将其放入
  • 如何在没有表单的情况下捕获屏幕?

    这是我用来捕获屏幕和鼠标光标作为屏幕截图的类 但我想以某种方式做到 如果表单位于屏幕中间 则不捕获它捕获屏幕和表单后面的区域 但不捕获表单本身 即使表单位于前面 并且我在应用程序运行时单击按钮或更改表单中的某些内容 也不要捕获它 只需继续捕
  • Visual Studio 2008 参考太长?

    我最近重新组织了我们的源代码控制 发现我们的解决方案之一不再构建 我们得到的唯一错误是 错误 65 未知构建错误 指定的路径 文件名或两者都是 太长 完全合格的文件 名称必须少于 260 个字符 并且目录名必须小于 超过 248 个字符 我
  • Titan 如何使用 HBase / Cassandra 实现恒定时间查找?

    在 O Reilly 的书 Graph Databases 第 6 章中 关于 Neo4j 如何存储图形数据库 它说 了解为什么本机图形处理如此高效 与基于大量索引的图表相比 请考虑以下事项 根据实现的不同 索引查找的算法复杂度可能为 O
  • C++ 新手需要打印整数组合的帮助

    假设我得到 整数范围iRange 即从1 up to iRange and 所需数量的组合 我想找到所有可能组合的数量并打印出所有这些组合 例如 Given iRange 5 and n 3 那么组合数就是iRange iRange n n
  • c 链表 - 是否可以创建一个独立于有效负载的迭代器函数?

    所有 在我的应用程序中 我有许多正在创建的链接列表 例如 一个 struct record 保存具有数百个节点 文本行 的转录文本 而第二种类型的链接列表 struct srch results 保存使用 strstr 搜索第一个列表的搜索