Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.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_Algorithm_Linked List - Fatal编程技术网

C 链表无限循环

C 链表无限循环,c,algorithm,linked-list,C,Algorithm,Linked List,尝试创建一个程序,在将当前节点移动到头部时,计算与strcmp进行比较的次数。但是算法有一些问题。。它有时“有效”,有时给我一个无限的机会。现在已经尝试了几个小时的lldb,并且每两行代码就放一次printf消息,但是我不知道如何找出问题所在。我想它在算法中的某个地方,但我看不出有什么问题 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct Node2 {

尝试创建一个程序,在将当前节点移动到头部时,计算与strcmp进行比较的次数。但是算法有一些问题。。它有时“有效”,有时给我一个无限的机会。现在已经尝试了几个小时的lldb,并且每两行代码就放一次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;
    }
}
#包括
#包括
#包括
类型定义结构节点2
{
字符*字;
结构节点2*next;
}节点2;
Node2*head=NULL;
Node2*now=NULL;
int uniqueWords=0;
int TotalMTFRCompariations=0;
Node2*iNode(char*word)
{   
Node2*ptr=malloc(sizeof(Node2));
节点2*tmp=头部;
节点2*prev=头部;
while(tmp)
{
总mtfr++;
printf(“当前单词:%s”,tmp->word);
如果(strcmp(tmp->word,word)==0)
{
上一步->下一步=tmp->下一步;
tmp->next=头部;
返回tmp;
}
prev=tmp;
tmp=tmp->next;
printf(“tmp递增。\n”);
}
ptr->word=malloc(strlen(word)+1);
strcpy(ptr->word,word);
ptr->next=NULL;
if(head==NULL)
{
头部=现在=ptr;
返回ptr;
}
其他的
{
ptr->next=头部;
水头=ptr;
}
返回ptr;
}
char*getString()
{
静态字符缓冲区[128];
while(fgets(buffer,128,stdin)!=NULL)
{
iNode(缓冲区);
}
返回缓冲区;
}
int main()
{
getString();
printf(“总字数:%d,总MTFR比较:%d\n”,唯一字数,总MTFR比较);
节点2*ptr2=头部;
节点2*tmp2=头部;
while(ptr2!=NULL)
{
tmp2=ptr2->next;
免费(ptr2->word);
免费(ptr2);
ptr2=tmp2;
}
}
我的主机刚刚被垃圾邮件发送到:
tmp增加。
但这种情况并不总是发生——只是偶尔发生,所以我不知道是什么原因造成的


输入和输出示例:

您为字符串分配的内存太少:

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;
}
我得到了输出:

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;
    }
}
#包括
#包括
#包括
#包括
类型定义结构节点2
{
字符*字;
结构节点2*next;
}节点2;
Node2*head=NULL;
Node2*now=NULL;
int uniqueWords=0;
int TotalMTFRCompariations=0;
bool DEBUG=true;
静止的
Node2*iNode(char*word)
{   
如果(调试)
printf(“addNode2调用[[%s].\n”,word);
节点2*tmp=头部;
节点2*prev=0;
while(tmp)
{
总mtfr++;
printf(“当前单词:%s\n”,tmp->word);
如果(strcmp(tmp->word,word)==0)
{
printf(“已输入:[[%s]]\n”,tmp->word);
如果(上一个!=0)
{
上一步->下一步=tmp->下一步;
tmp->next=头部;
水头=tmp;
}
//tmp->next=prev;
返回tmp;
}
prev=tmp;
tmp=tmp->next;
printf(“tmp递增。\n”);
}
Node2*ptr=malloc(sizeof(Node2));
printf(“新单词:[[%s]]\n”,单词);
uniqueWords++;
ptr->word=malloc(strlen(word)+1);
strcpy(ptr->word,word);
ptr->next=NULL;
if(head==NULL)
{
头部=现在=ptr;
返回ptr;
}
其他的
{
ptr->next=头部;
水头=ptr;
}
返回ptr;
}
静止的
char*getString(void)
{
静态字符缓冲区[128];
while(fgets(buffer,128,stdin)!=NULL)
{
char*nl=strchr(缓冲区“\n”);
如果(nl!=0)
*nl='\0';
printf(“行:[[%s]]\n”,缓冲区);
iNode(缓冲区);
}
返回缓冲区;
}
内部主(空)
{
getString();
printf(“总字数:%d,总MTFR比较:%d\n”,唯一字数,总MTFR比较);
节点2*ptr2=头部;
节点2*tmp2=头部;
while(ptr2!=NULL)
{
printf(“释放:[[%s]]\n”,ptr2->word);
tmp2=ptr2->next;
免费(ptr2->word);
免费(ptr2);
ptr2=tmp2;
}
}

它有一些诊断打印。换行符剥离意味着诊断输出比您在聊天中看到的要短,如果您费心查看聊天(字符串的末尾有一个换行符-包括换行符在内的行被视为单词)。

您为字符串分配的内存太少:

ptr->word = malloc(strlen(word));
strcpy(ptr->word, word);
您需要分配
strlen(word)+1
字节以允许空终止符

当写入超出分配的空间时,将调用未定义的行为。对你来说不幸的是,这
ptr->word = malloc(strlen(word));
ptr->word = malloc(sizeof(word));