用C指针初始化双向链表

时间:2022-09-05 19:51:44

Is it possible to initiate the value for *preceding and *next on one line of code?

是否可以在一行代码中启动* before和* next的值?

This is the error I get:

这是我得到的错误:

$ gcc test.c -std=c99
test.c: In function ‘main’:
test.c:34:10: error: expected expression before ‘{’ token
     n3 = { .value = 300, .preceding = &n2, .next = tail };
          ^
test.c:35:10: error: expected expression before ‘{’ token
     n2 = { .value = 200, .preceding = &n1, .next = &n3 };
          ^
test.c:36:10: error: expected expression before ‘{’ token
     n1 = { .value = 100, .preceding = &header, .next = &n2 };
          ^
test.c:37:14: error: expected expression before ‘{’ token
     header = { .next = &n1 };

Or I need to initiate .previous and .next separately?

或者我需要分别启动.previous和.next?

Is it right to set list_pointer = &header and last element in the list .next = tail which in turn tail = (struct entry *) 0? Or are there more convenient ways?

设置list_pointer =&header和列表中的最后一个元素是正确的.next = tail又是tail =(struct entry *)0?还是有更方便的方法?

 // Prints out the elements of the doubly linked  list, from head to tail and backwards.

#include <stdio.h>

struct entry
{
    int            value;
    struct entry   *preceding;
    struct entry   *next;
};

void printPlist(struct entry *list)
{
    list = list->next; // switch from header(start of the list) to n1; because !(header.value) or NULL

    while (list->next) {
        printf("%i\n", list->value);
        list = list->next;
    }

    printf("\n");

    while (list->preceding) {
        printf("%i\n", list->value);
        list = list->preceding;
    }
    printf("\n");
}

int main(void)
{
    struct entry *tail = (struct entry *) 0;
    struct entry header, n1, n2, n3;
    n3 = { .value = 300, .preceding = &n2, .next = tail };
    n2 = { .value = 200, .preceding = &n1, .next = &n3 };
    n1 = { .value = 100, .preceding = &header, .next = &n2 };
    header = { .next = &n1 };
    struct entry *list_pointer = &header;

    printPlist(list_pointer);  // from head to tail and backwards.

    return 0;
}

2 个解决方案

#1


1  

You can define both links in a single line.

您可以在一行中定义两个链接。

struct entry
{
    int            value;
    struct entry   *preceding, *next;
};

You can use pre-processor macros to make initialization extremely concise and convenient.

您可以使用预处理器宏使初始化非常简洁方便。

int main() {

    typedef struct LinkedList {
        struct LinkedList   *prev, *next;
        int value;
    } linkedList_t;

    linkedList_t head =  { &head, &head, 0 };
}

ulist.h is one of many examples of C linked list macros you can use throughout a program. Makes life a lot easier and I've worked in code shops where they use macros like this consistently throughout a product to make the produce readable, easier to write, more consistent and easier to understand and maintain.

ulist.h是您可以在整个程序中使用的C链接列表宏的众多示例之一。让生活变得更轻松,我在代码商店工作,他们在整个产品中使用这样的宏,使产品可读,更容易编写,更一致,更易于理解和维护。

#2


2  

You can't use the designated initializers to re-initialize existing objects.

您不能使用指定的初始值设定项重新初始化现有对象。

You can't use them for creating and initializing the entire list here either, because the required references to the following or preceeding nodes do not yet exist when the objects are created.

您也不能在此处使用它们来创建和初始化整个列表,因为在创建对象时,对于以下节点的必需引用尚不存在。

Therefore I'd recommend to add another function to initialize the entries after they've been created. (Or yet another one, that also creates an entry for you using malloc.)

因此,我建议添加另一个函数来在创建条目后初始化它们。 (或者另一个,也使用malloc为您创建一个条目。)

See this example:

看这个例子:

void initializeEntry(struct entry *this, 
                     int value,
                     struct entry *preceding,
                     struct entry *next)
{
    this->value = value;
    this->preceding = preceding;
    this->next = next;
}

int main()
{
    // declare (and create) the list element objects
    struct entry header, n1, n2, n3;

    // initialize the list elements
    initializeEntry(&header, 0, 0, &n1);
    initializeEntry(&n1, 100, &header, &n2);
    initializeEntry(&n2, 200, &n1, &n3);
    initializeEntry(&n3, 300, &n2, 0);

    // print the list
    printPlist(&header);

    return 0;
}

#1


1  

You can define both links in a single line.

您可以在一行中定义两个链接。

struct entry
{
    int            value;
    struct entry   *preceding, *next;
};

You can use pre-processor macros to make initialization extremely concise and convenient.

您可以使用预处理器宏使初始化非常简洁方便。

int main() {

    typedef struct LinkedList {
        struct LinkedList   *prev, *next;
        int value;
    } linkedList_t;

    linkedList_t head =  { &head, &head, 0 };
}

ulist.h is one of many examples of C linked list macros you can use throughout a program. Makes life a lot easier and I've worked in code shops where they use macros like this consistently throughout a product to make the produce readable, easier to write, more consistent and easier to understand and maintain.

ulist.h是您可以在整个程序中使用的C链接列表宏的众多示例之一。让生活变得更轻松,我在代码商店工作,他们在整个产品中使用这样的宏,使产品可读,更容易编写,更一致,更易于理解和维护。

#2


2  

You can't use the designated initializers to re-initialize existing objects.

您不能使用指定的初始值设定项重新初始化现有对象。

You can't use them for creating and initializing the entire list here either, because the required references to the following or preceeding nodes do not yet exist when the objects are created.

您也不能在此处使用它们来创建和初始化整个列表,因为在创建对象时,对于以下节点的必需引用尚不存在。

Therefore I'd recommend to add another function to initialize the entries after they've been created. (Or yet another one, that also creates an entry for you using malloc.)

因此,我建议添加另一个函数来在创建条目后初始化它们。 (或者另一个,也使用malloc为您创建一个条目。)

See this example:

看这个例子:

void initializeEntry(struct entry *this, 
                     int value,
                     struct entry *preceding,
                     struct entry *next)
{
    this->value = value;
    this->preceding = preceding;
    this->next = next;
}

int main()
{
    // declare (and create) the list element objects
    struct entry header, n1, n2, n3;

    // initialize the list elements
    initializeEntry(&header, 0, 0, &n1);
    initializeEntry(&n1, 100, &header, &n2);
    initializeEntry(&n2, 200, &n1, &n3);
    initializeEntry(&n3, 300, &n2, 0);

    // print the list
    printPlist(&header);

    return 0;
}