2

我对 LinkedLists 的经验很少,并且无法弄清楚测试字符串是否在其中一个节点中的逻辑。整个程序正在等待客户端发送 DNS 查询,然后在无限循环中发送回响应。我想做的是:

确定 LinkedList 是否具有客户端请求的主机名。如果不存在,请将其添加到 LinkedList 并在执行查找后将答案保存到同一节点。如果它在那里,只需给客户我已经查找并存储在answer[].

这是一段简化的代码:

struct queryCache {
    char* hostName;
    uint8_t answer[UDP_RECV_SIZE];
    struct queryCache* next;
};
struct queryCache* qcRoot;

int main (int argc, char** argv) {
    // ...unrelated code

    qcRoot = malloc(sizeof(struct queryCache));
    qcRoot->hostName = 0;
    qcRoot->next = 0;

    while (1) {
        // Wait for client with recvfrom()

        char* cqHostName;
        // Code that malloc()s and strcpy()s the client hostname into cqHostName

        // Determine if cqHostName is in the cache
        int hostNameInCache = 0;
        struct queryCache* currQC = qcRoot;
        while (currQC) {
            if (!strcmp(currQC->hostName, cqHostName)) {
                puts("In the cache");
                hostNameInCache = 1;
                break;
            }
            currQC = currQC->next;
        }

        // If cqHostName is not in the cache add its name
        if (!hostNameInCache) {
            currQC->hostName = malloc(strlen(cqHostName)+1);
            strcpy(currQC->hostName, cqHostName);
            printf("Added HOSTNAME: %s to the cache\n", cqHostName);

            currQC->next = malloc(sizeof(struct queryCache));
            currQC = currQC->next;
            currQC->hostName = 0;
            currQC->next = 0;
        }

        // Code that does a recursive DNS

        // Code that will copy the response into the appropriate answer[] of the LinkedList
    }
}

该程序似乎只是在第一个客户端请求后退出而没有给出错误。如果我删除 LinkedList 代码,它工作得很好,所以我很确定出了什么问题与我如何检查字符串是否在 LinkedList 中有关。

4

3 回答 3

1

根据您的代码,当您尝试执行currQC->hostName = malloc(strlen(cqHostName)+1);.

您接受的答案确实可以解决这种特定情况,在 while 循环中,如果您这样做,while(currQC->next)那么您会错过检查 list 中的最后一项

因此,该代码引入了另一个问题,并没有立即显现。我建议检查下一个元素是否为空,而不是如果它像 in 则中断if (!currQC->next) break; else currQC=currQC->next

编辑:当然,我的建议意味着您将希望将 while 循环替换为 do {}while(1); 相反,因为 while 条件将不再被测试。

于 2013-10-23T07:27:52.443 回答
1

什么时候hostNameInCache是 0,最有可能currQCNULL,所以你不能推迟它。

将 while 循环的条件更改为

#------------v
while (currQC->next) {
    if (!strcmp(currQC->hostName, cqHostName)) {
            puts("In the cache");
            hostNameInCache = 1;
            break;
        }
        currQC = currQC->next;
}
于 2013-10-23T07:12:50.067 回答
0

在 C 中,通常有两种方法来处理单链表:作为堆栈或作为队列。

将列表作为堆栈处理时,您在头部添加新项目。将其作为队列处理时,您在尾部添加新项目。


最简单的是堆栈方法:

struct node
{
    int data;
    struct node *next;
};

...

struct node *head = NULL;

/* Add one node */
struct node *n1 = malloc(sizeof(struct node));
n1->data = 1;
n1->next = head;   /* This and the next line is what adds the node */
head = n1;

/* Add another node */
struct node *n2 = malloc(sizeof(struct node));
n2->data = 2;
n2->next = head;   /* This and the next line is what adds the node */
head = n2;

在上面的代码之后,列表包含两个节点:

2 --> 1 --> 空

对于队列方法,您需要跟踪尾部和头部:

struct node *head = NULL;
struct node *tail = NULL;

/* Add one node */
struct node *n1 = malloc(sizeof(struct node));
n1->data = 1;
n1->next = NULL;

if (tail != NULL)
    tail->next = n1;
else
{
    /* List is empty */
    head = tail = n1;
}

/* Add another node */
struct node *n2 = malloc(sizeof(struct node));
n2->data = 2;
n2->next = NULL;

if (tail != NULL)
    tail->next = n2;
else
{
    /* List is empty */
    head = tail = n2;
}

在此之后,列表看起来像

1 --> 2 --> 空

我建议您阅读此答案几次,并考虑您对列表的处理与此处使用的方法有何不同。我还建议您使用调试器逐行单步执行您的代码,以查看为什么您的列表处理无法按预期工作。

于 2013-10-23T07:25:01.980 回答