【问题标题】:Inserting a new node at the beginning of a linked list in C在C中链表的开头插入一个新节点
【发布时间】:2014-03-06 06:17:07
【问题描述】:

结构如下所示:

typedef char AirportCode [4];
typedef struct node {
   AirportCode airport;
   struct node *next;
}Node;

我的函数如下所示:

void insertFirst(AirportCode code, Node **listPtr){
   Node *Holder = *listPtr;
   Node *newNode = (Node *)malloc(sizeof(Node));
   if (*listPtr == NULL){
    (*listPtr)->airport = code;
    (*listPtr)->next = NULL; }

   else{
    *listPtr = newNode;
    newNode->airport = code;
    newNode->next = holder; }
}

错误信息是:

incompatible types when assigning to type 'AirportCode' from type 'char *' 

此错误消息出现在我分配代码值的两行中。

【问题讨论】:

标签: c struct linked-list


【解决方案1】:

问题是你不能在C 中分配数组。您只能初始化它们。此外,您不能将数组传递给函数 - 实际上传递的是指向数组第一个元素的指针。以下声明

typedef char AirportCode[4];

定义AirportCode 类型char[4] - 一个4 字符数组。在您的函数insertFirst 中,您将code 类型为char * 分配给(*listPtr)->airport 类型为AirportCodechar[4]。这两个是不兼容的类型,因此您会收到错误消息。

由于你不能将数组传递给函数,你应该做的是传递一个指向数组第一个元素的指针和数组长度。然后将数组复制到结构体的对应成员中。

以下三个声明完全相同。函数中的数组参数实际上是一个指向字符的指针。

void insertFirst(AirportCode code, Node **listPtr);
void insertFirst(char code[4], Node **listPtr);
void insertFirst(char *code, Node **listPtr);

另外,您不应该转换malloc 的结果。不要让typedef 混淆命名空间并造成混乱。在这种情况下,没有它你会更好。如果if 条件*listPtr == NULLtrue,那么您正在取消引用块中的空指针,这显然是一个错误。

if(*listPtr == NULL) {
    // the below statements dereference the null pointer 
    // which is an error and would cause program crash 
    // due to segfault.

    (*listPtr)->airport = code; 
    (*listPtr)->next = NULL;     
}

从您的else 块中,我假设您正在尝试在链表的开头添加一个新节点。我建议进行以下更改(感谢 Jonathan Leffler)。

typedef struct node {
   char airport[4];  // no typedef. explicit array declaration.
   struct node *next;
} Node;

void insertFirst(char *code, Node **listPtr) {
    Node *oldHead = *listPtr;
    Node *newNode = malloc(sizeof(Node));

    if(newNode == NULL) {  // check for NULL
        printf("Not enough memory to allocate\n");
        return;
    }

    // if the struct member code is a string, then use strncpy to 
    // guard against buffer overrun, else use memcpy to copy
    // code to airport. this is assuming that the buffer pointed
    // to by code is never smaller than sizeof newNode->airport

    memcpy(newNode->airport, code, sizeof newNode->airport); 
    newNode->next = oldHead;

    *listPtr = newNode;  // make listPtr point to the new head
}

【讨论】:

  • 我认为使用strcpy()memmove()memcpy() 可能比长期编写循环(两次)更好。目前尚不清楚为什么将新数据复制到旧的第一个节点上,而不是新节点上。如果你仔细看,你可以减少更多的重复代码。另请参阅Inserting node into first place — C programming
  • @JonathanLeffler 谢谢,我更新了我的答案。我忽略的一个明显错误是 OP 的 if 块取消引用空指针。现在,希望我已经删除了代码重复。
  • 更好……但挑剔者在这里 :( (1) 长度是否包括终端空位?(2) 您是否应该检查长度是否适合可用空间?(因为目前机场代码有限到三个字母,除了复制 sizeof(newNode->airport) 字节之外几乎没有任何理由可以删除长度参数。)(3)由于您在 ifelse 中都分配了 *listPtr,所以您应该这样做它在条件之外,这让您只有在*listPtr != NULL 时才有事可做。(您的Holderholder 存在区分大小写的问题。)[...继续...]
  • [...Continuation...] 此外,您可以简单地分配newNode->next = holder,因为如果holder 为null,您将分配null,如果您分配holder 的值holder 不为空,这和给holder 赋值是一样的,不是吗?
  • 现在看起来不错。唯一的条件是内存不足测试;这几乎是不可避免的。
【解决方案2】:

基本情况是这样的

int a=10,b;

b=a

以上works Fine

数组也一样

int a[]={1,2,3};

int b[3]

b=a; ---> this wrong way

correct way is

for(i=0;i<3;i++)
{
   b[i]=a[i];
}

 OR

strcpy(b,a);

char a[4],b[4];
 gets(a);
 b=a;----->wrong assigning

 correct way
 strcpy(b,a);

更多详情请联系Inserting New Node

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多