- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
尝试创建一个程序来计算在将当前节点移动到头部时使用 strcmp
进行的比较次数。虽然算法有一些问题......它有时“有效”,而在其他时候给了我一个无限循环。现在尝试了 lldb 几个小时,并且每 2 行代码就放置 printf 消息,但我不知道如何查明问题所在。我认为它在算法中的某个地方,但我看不出有什么问题。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node2
{
char* word;
struct Node2 *next;
} Node2;
Node2* head = NULL;
Node2* now = NULL;
int uniqueWords = 0;
int totalMTFRComparisons = 0;
Node2* iNode(char* word)
{
Node2* ptr = malloc(sizeof(Node2));
Node2* tmp = head;
Node2* prev = head;
while (tmp)
{
totalMTFRComparisons++;
printf("Current word: %s", tmp->word);
if (strcmp(tmp->word, word) == 0)
{
prev->next = tmp->next;
tmp->next = head;
return tmp;
}
prev = tmp;
tmp = tmp->next;
printf("tmp incremented.\n");
}
ptr->word = malloc(strlen(word) + 1);
strcpy(ptr->word, word);
ptr->next = NULL;
if (head == NULL)
{
head = now = ptr;
return ptr;
}
else
{
ptr->next = head;
head = ptr;
}
return ptr;
}
char* getString()
{
static char buffer[128];
while (fgets(buffer, 128, stdin) != NULL)
{
iNode(buffer);
}
return buffer;
}
int main()
{
getString();
printf("Total words: %d, total MTFR comparisons: %d\n", uniqueWords, totalMTFRComparisons);
Node2* ptr2 = head;
Node2* tmp2 = head;
while (ptr2 != NULL)
{
tmp2 = ptr2->next;
free(ptr2->word);
free(ptr2);
ptr2 = tmp2;
}
}
我的控制台刚刚收到垃圾邮件:tmp 递增。
但这并不总是发生 - 它只是有时发生,所以我不知道是什么原因造成的。
示例输入和输出:http://pastebin.com/QfuCm7gt
最佳答案
您为字符串分配的内存太少:
ptr->word = malloc(strlen(word));
strcpy(ptr->word, word);
您需要分配 strlen(word) + 1
字节以允许空终止符。
当您写入超出分配的空间时,您会调用未定义的行为。对您来说不幸的是,这可能意味着它有时看起来工作正常 — 它是对未定义行为的有效响应,似乎按预期工作,除非它适合系统改变主意和行为异常。
考虑是否可以使用 strdup()
函数。如果不是,请考虑您是否应该编写和使用您自己的版本。不要忘记检查内存分配是否成功。
(在您修复未定义的行为之前,真的没有必要想知道还有什么问题,如果还有其他问题。)
我写这段代码是为了看看我是否可以模拟你的问题。我不能:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
char *word;
struct Node *next;
} Node;
int totalMTFRComparisons = 0;
Node* head = NULL;
static Node* iNode(char* word)
{
Node* ptr = malloc(sizeof(Node));
Node* tmp = head;
Node* prev = head;
while (tmp)
{
totalMTFRComparisons++;
if (strcmp(tmp->word, word) == 0)
{
prev->next = tmp->next;
tmp->next = head;
//tmp->next = prev;
/* JL: Still a memory leak here. */
/* Either free(ptr) or don't allocate until after the loop */
return tmp;
}
prev = tmp;
tmp = tmp->next;
printf("tmp incremented.\n");
}
ptr->word = malloc(strlen(word) + 1);
strcpy(ptr->word, word);
ptr->next = NULL;
if (head == NULL)
{
head = ptr;
return ptr;
}
else
{
ptr->next = head;
head = ptr;
}
return ptr;
}
static void dump_list(Node *node)
{
while (node != 0)
{
printf("Node word: [[%s]]\n", node->word);
node = node->next;
}
}
static void free_list(Node *node)
{
printf("Freeing list\n");
while (node != 0)
{
Node *next = node->next;
printf("Freeing: [[%s]]\n", node->word);
free(node->word);
free(node);
node = next;
}
}
int main(void)
{
char line[4096];
while (fgets(line, sizeof(line), stdin) != 0)
{
printf("Line: [[%s]]\n", line);
char *ptr = line;
char *tok;
while ((tok = strtok(ptr, "\n\t ")) != 0)
{
printf("Word: [[%s]]\n", tok);
iNode(tok);
ptr = NULL;
}
dump_list(head);
}
free_list(head);
return 0;
}
这或多或少是一个 MCVE。 dump 和 free 函数只是让我确保我可以看到列表中的内容并释放所有内存。
除了修复内存覆盖问题外,我只提供了Node
类型的定义,将static
放在函数前面(以避免编译警告之一否则我会得到),并添加了两个支持函数和 main()
;否则我没有更改您的代码。 (顺便说一句,对第一次编译的唯一提示是关于 cur2
的,我注意到了但忘记删除了 — 这很好;很少有程序,即使是我编写的程序,也能如此干净利落地完成。)
运行时,我输入:
abc def ghi
mno pqr stuvwxyz humongously-and-tempestuously-but-neither-abstemiously-nor-facetiously-long word!
我得到了输出:
abc def ghi
Line: [[abc def ghi
]]
Word: [[abc]]
Word: [[def]]
tmp incremented.
Word: [[ghi]]
tmp incremented.
tmp incremented.
Node word: [[ghi]]
Node word: [[def]]
Node word: [[abc]]
mno pqr stuvwxyz humongously-and-tempestuously-but-neither-abstemiously-nor-facetiously-long word!
Line: [[mno pqr stuvwxyz humongously-and-tempestuously-but-neither-abstemiously-nor-facetiously-long word!
]]
Word: [[mno]]
tmp incremented.
tmp incremented.
tmp incremented.
Word: [[pqr]]
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
Word: [[stuvwxyz]]
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
Word: [[humongously-and-tempestuously-but-neither-abstemiously-nor-facetiously-long]]
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
Word: [[word!]]
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
tmp incremented.
Node word: [[word!]]
Node word: [[humongously-and-tempestuously-but-neither-abstemiously-nor-facetiously-long]]
Node word: [[stuvwxyz]]
Node word: [[pqr]]
Node word: [[mno]]
Node word: [[ghi]]
Node word: [[def]]
Node word: [[abc]]
Freeing list
Freeing: [[word!]]
Freeing: [[humongously-and-tempestuously-but-neither-abstemiously-nor-facetiously-long]]
Freeing: [[stuvwxyz]]
Freeing: [[pqr]]
Freeing: [[mno]]
Freeing: [[ghi]]
Freeing: [[def]]
Freeing: [[abc]]
在 Valgrind 下运行时,我得到了一些奇怪的输出,但那是因为我升级了 o/s(Mac OS X Yosemite 到 El Capitan)而没有更新抑制。泄漏都在系统代码中,而不是在这段代码中,AFAICT。
该代码的一个特点是,如果单词被输入两次,则该单词应该被移到列表的前面。我的测试是针对独特的单词集。问题在于处理第一个单词的重复项。这段代码中有一个看起来很可靠的修复:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct Node2
{
char* word;
struct Node2 *next;
} Node2;
Node2* head = NULL;
Node2* now = NULL;
int uniqueWords = 0;
int totalMTFRComparisons = 0;
bool DEBUG = true;
static
Node2* iNode(char* word)
{
if (DEBUG)
printf("addNode2 called [[%s]].\n", word);
Node2* tmp = head;
Node2* prev = 0;
while (tmp)
{
totalMTFRComparisons++;
printf("Current word: %s\n", tmp->word);
if (strcmp(tmp->word, word) == 0)
{
printf("Already entered: [[%s]]\n", tmp->word);
if (prev != 0)
{
prev->next = tmp->next;
tmp->next = head;
head = tmp;
}
//tmp->next = prev;
return tmp;
}
prev = tmp;
tmp = tmp->next;
printf("tmp incremented.\n");
}
Node2* ptr = malloc(sizeof(Node2));
printf("New word: [[%s]]\n", word);
uniqueWords++;
ptr->word = malloc(strlen(word) + 1);
strcpy(ptr->word, word);
ptr->next = NULL;
if (head == NULL)
{
head = now = ptr;
return ptr;
}
else
{
ptr->next = head;
head = ptr;
}
return ptr;
}
static
char* getString(void)
{
static char buffer[128];
while (fgets(buffer, 128, stdin) != NULL)
{
char *nl = strchr(buffer, '\n');
if (nl != 0)
*nl = '\0';
printf("Line: [[%s]]\n", buffer);
iNode(buffer);
}
return buffer;
}
int main(void)
{
getString();
printf("Total words: %d, total MTFR comparisons: %d\n", uniqueWords, totalMTFRComparisons);
Node2* ptr2 = head;
Node2* tmp2 = head;
while (ptr2 != NULL)
{
printf("Freeing: [[%s]]\n", ptr2->word);
tmp2 = ptr2->next;
free(ptr2->word);
free(ptr2);
ptr2 = tmp2;
}
}
它有一些诊断打印。换行剥离意味着诊断输出比你在聊天中看到的要短,如果你懒得看聊天(字符串末尾有一个换行符——行被视为单词,包括换行符)。
关于c - 链表无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33251062/
今天我们将开始第二个数据类型-链表的学习,同样我们还是用最原始的方式,自己申请内存管理内存来实现一个链表。 01、01、定义 什么是链表?链表在物理存储结构上表现为非顺序性和非连续性,因此链表
前言:笔记是参考B站up主尚硅谷,图片、代码都是哦。在blog写笔记~(图片、代码来源尚硅谷,侵权必删!) 尚硅谷数据结构学习路线B站网站:https://www.bilibili.com/video
这个问题不太可能对任何 future 的访客有帮助;它只与一个较小的地理区域、一个特定的时间点或一个非常狭窄的情况相关,通常不适用于全世界的互联网受众。如需帮助使此问题更广泛适用,visit the
我想创建一个没有全局变量的单个链表。我用 NULL 初始化了第一个元素,然后想将第一个元素 node 复制到 list_。它被复制到函数中,但副作用不起作用。在我的主函数中,该值仍然是NULL。如果我
我正在尝试使链表与此处的链表相似: linked list in C 那就是在另一个结构中有“头”,我首先称它为“头”。但是我发现做那个改变。很难向 list_item 结构添加值。我已经尝试了一些东
我正在尝试理解链表的代码。我明白他们是如何工作的。我正在查看一些与动态内存和链表有关的代码,我在此处对其进行了简化: #include #include typedef struct nod
有人可以解释下面的代码吗?我是 C 的新手,正在努力弄清楚。为什么我们最后有 queueNodeT? typedef char queueElementT; typedef struct queueN
场景如下:- 我想反转单链表的方向,换句话说,反转后所有指针现在应该指向后.. 这个算法应该需要线性时间。 我想到的解决方案是使用另一个数据结构 A Stack.. 借助它可以轻松反转单向链表,所有指
在 python 中使用链表最简单的方法是什么?在 scheme 中,链表由 '(1 2 3 4 5) 定义。 Python 的列表 [1, 2, 3, 4, 5] 和元组 (1, 2, 3, 4,
本文首发公众号:小码A梦 一般数据主要存储的形式主要有两种,一种是数组,一种是链表。数组是用来存储固定大小的同类型元素,存储在内存中是 一片连续 的空间。而链表就不同于数组。链表
虽然之前有人问过关于链表与数组的问题,但答案大多归结为我们大多数人在某个时候可能已经学到的东西: 列表擅长插入和删除 数组擅长随机访问 现在像 Bjarne Stroustrup 这样受人尊敬的人有
位置 在堆中,碎片化(每个节点的 malloc) - 在几种不同的方式(缓慢分配,缓慢访问,内存碎片)方面效率低下 在堆中,在一个大块中 - 当需要重新分配 时,数据结构获得的所有灵活性都将丢失 在堆
我完成了泛型的学习,但并不容易。不过,我确实明白了。这是我的理解。我希望您纠正我的错误并回答几个问题:)。 public class LinkedList { //class definition }
我将如何创建一个链接列表来在 OCaml 中保存我的数据?我正在尝试制作一个单链表,但是我遇到了语法问题。我只想制作一个模块来简单地从链表中获取'a,插入'a或删除'a。 有人知道吗? 最佳答案 正如
我在使用这段代码时遇到了问题,我不确定我做错了什么 #include #include #include #include typedef struct flight_struct{
我正在创建一个函数来删除给定列表的最后一个节点(作为参数输入)。该函数本身非常简单,如下所示。 function popBack(list) { var current = list.head
我正在尝试开发一种方法,该方法将在链接列表中的当前节点之前插入传递给它的节点。它有3个条件。对于此实现,不能有任何头节点(仅对列表中第一个节点的引用),并且我无法添加更多变量。 如果列表为空,则将传递
使用 scala,我已将大约 100000 个节点添加到链表中。当我使用函数 length 时,例如 mylist.length。我收到“java.lang.StackOverflowError”错误
所以我正在学习处理链表。我将如何递归地添加节点内的项目。我可以通过执行 sum = h.item +h.next.item+h.next.next.item 添加它们,但这只有在我有小的链接列表时才有
所以我一直在努力理解链表的概念(一直在看一些示例代码,我在互联网上找到了这个。现在如果我能请别人确认我是否正确掌握了一些概念。我将绘制图表,说明我认为每个代码链接的作用。 #include #inc
我是一名优秀的程序员,十分优秀!