在C中使用函数,声明变量并在多个函数中使用

在C中使用函数,声明变量并在多个函数中使用,c,struct,C,Struct,我想制作一个链接列表,从我的主目录调用到其他地方。此链接列表由节点组成 例如,这不是我的代码,只是它的简化版本 nodeTest.h 我在if行得到错误,head无法识别。在调用main函数之前不能分配内存。您可以在main之外声明一个全局变量,并使用它的地址作为第一个变量。main中的alloc应该可以工作,这是最好的方法。但是您必须对结构进行如下类型转换才能使用它,否则编译将失败 typedef struct First { <element 1> struct first *

我想制作一个链接列表,从我的主目录调用到其他地方。此链接列表由节点组成

例如,这不是我的代码,只是它的简化版本

nodeTest.h
我在if行得到错误,head无法识别。

在调用main函数之前不能分配内存。您可以在main之外声明一个全局变量,并使用它的地址作为第一个变量。main中的alloc应该可以工作,这是最好的方法。但是您必须对结构进行如下类型转换才能使用它,否则编译将失败

typedef struct First {

<element 1>
struct first *next

} First;

第0期:理解链表和C

那上面有很多材料。比如,看看这些

第1期:“未申报的头部”

在使用变量之前,首先需要引入它。该问题是由于
head
不在功能范围内(根据C规则)造成的。因此,您需要将指向它的指针作为参数传递:

void addLL(struct nodeTest *head, int data){
  // now you can access head->data, head->next
  // .. 
}
如果使用
0
表示没有可用数据,则不能存储任何零。 另一种方法是保持列表元素的计数,并检查计数是否正确 为零以确定列表中的哪些内容为空

第2期:“第一->数据”未声明

要么先声明(与
头部
相同),要么使用
头部->数据

第3期:列表设计和API

使用全局状态通常被认为是不好的做法,所以不要使用全局列表。 我建议您为列表定义另一个结构,并在另一个函数(如
list\u add()
list\u remove()
)周围传递一个点,这样您还可以保存指向最后一个元素的指针,使appen成为一个O(1)操作,例如:

struct list {
  struct node *first;
  struct node *last;
  unsigned long length;
};
因此,您可以实现一个函数来检查列表是否为空:

inline bool list_is_empty(struct list* l) {
  assert(l != NULL);
  return l->length;  
}
并在
main
中使用多个列表:

 struct list *list1 = list_create(); // sets length to 0
 struct list *list2 = list_create(); // return a new list
 //...
 list_add(&list1, data); // you pass a pointer to the list to which you want to add
 //...
 struct node *e = list_search(&list1, data);
 if (e == NULL)
   printf("not found\n");
 //...
 list_remove(&list1, data);
 //
 list_destroy(&list1); 
向列表中添加元素可以实现如下操作:

int list_add(struct list* l, int data) {

    if (l == NULL)
        return LIST_FAILURE; // or exit with an error message

    l->last->next = list_elem_create(data); // dynamically creates a new node
    l->last = l->last->next;
    l->length++;
    return LIST_SuCCESS; // symbolc constant defined elsewhere 
}

对。由于变量
head
仅从
main
内部可见,因此会出现该错误。有两种解决方法:

  • 您可以在任何函数之外将
    head
    声明为全局变量;或
  • 您可以将
    head
    传递给任何需要它作为指针的函数
  • 让我们看看这些选项是如何工作的:

    使用全局变量 此方法要求我们将
    传递到每个可能需要它的函数中。这使函数接口稍微复杂化,但允许我们更灵活,因为我们不需要为程序中的许多列表设置许多全局变量

    但还有另一个问题。如果这些函数中的任何一个需要修改
    指针(例如,假设您正在删除列表中的第一个元素),那么您就有问题了。指针(与指向的对象不同)是函数的本地指针,因此对它所做的任何更改都将在函数外部不可见

    有两种方法可以解决这个问题:

  • 每个接受
    head
    作为参数并可能需要更改的函数都必须返回指向新head的指针。这是可行的,但是实现起来很麻烦,而且很容易出错
  • 每个接受
    head
    作为参数并可能需要更改的函数都将接受一个双指针:指向head的指针。这很好,但会使事情复杂化,可能会让一些新手程序员措手不及。它也有点容易出错,但不像前面的选项那样容易出错

  • 我希望这能回答你的问题,解释为什么你不能做你所做的事情,以及存在的变通办法。

    1。您不需要在C程序中强制转换
    malloc
    的返回值。2.请出示实际代码;您的第一个
    malloc
    调用甚至不在函数中。为什么我不需要返回它呢?这基本上是实际代码。什么需要改变?你需要看什么?一个编译的代码示例;还有错误是什么样子的?@PaulGriffiths的重复我不这么认为,我想知道更多关于这段代码如何与主文件一起工作的细节,以及如何使用特定的头调用其他函数。我不感兴趣向这个列表添加元素,我更感兴趣的是在列表中搜索元素。e是做什么的?我不明白。你说人头档案是什么意思?我现在一点都不在乎,我只是有点惊慌失措,想尽快把这件事做完,因为我的工作远远落后了。我今天必须这样做。我已经花了8个小时在这上面,但我没有取得任何进展。如果(first.data==0)int main(void){struct nodeTest*first=malloc(sizeof(struct nodeTest));first->data=0;return 0;}void addLL(int data){if(first.data=0),我将得到该行的第一个未声明项我有两个版本的代码,我正在处理,我不小心把其中的两个混在了一起。这是唯一的区别。看起来不会这样compile@ripDaddy69:嗯,这是你的函数;我刚刚调用了它。我不确定你想让它做什么,但我从名称猜它应该向链表中添加一个条目。它是如何做到的取决于对您的要求。如果您愿意,您可以就如何使
    addLL
    工作提出一个单独的问题,但我建议您先尝试用纸和铅笔,用箭头将节点表示为方框和指针。然后,如果您无法解决,请再次提问。@ripDaddy69如果您有多个inst在链表中,您需要多个变量来表示它们,因此需要多个函数(或者用某种方法来确定函数应该使用哪个列表)。如果您有多个列表,则需要使用选项2
    struct list {
      struct node *first;
      struct node *last;
      unsigned long length;
    };
    
    inline bool list_is_empty(struct list* l) {
      assert(l != NULL);
      return l->length;  
    }
    
     struct list *list1 = list_create(); // sets length to 0
     struct list *list2 = list_create(); // return a new list
     //...
     list_add(&list1, data); // you pass a pointer to the list to which you want to add
     //...
     struct node *e = list_search(&list1, data);
     if (e == NULL)
       printf("not found\n");
     //...
     list_remove(&list1, data);
     //
     list_destroy(&list1); 
    
    int list_add(struct list* l, int data) {
    
        if (l == NULL)
            return LIST_FAILURE; // or exit with an error message
    
        l->last->next = list_elem_create(data); // dynamically creates a new node
        l->last = l->last->next;
        l->length++;
        return LIST_SuCCESS; // symbolc constant defined elsewhere 
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "nodeTest.h"
    
    /* Declare a global variable. The initialization to NULL is redundant
     * since global variables are automatically initialized to zero. But
     * let's be thorough.
     */
    
    struct nodeTest* head = NULL;
    
    int main(void) {
       head = malloc(sizeof(struct nodeTest));
       /* check if head is NULL here. Just in case. */
       head->data = 0;
    
       addLL(1);
    
       return 0;
    }
    
    /* other functions here */
    void addLL(int data) {
       /* since we allocate head in main it should never be NULL and
        * if it is, something is wrong. So assert.
        */
       assert(head != NULL);
    
       /* Notice: in your original code you had: if (first.data = 0)
        * which is wrong. First of all, there's no variable named first
        * declared anywhere. If you meant head, that should have been
        * head->first since head is a pointer. And lastly, first.data = 0
        * would set first.data to 0, instead of comparing it for equivalency, 
        * and would then cause the if to never execute because the compiler
        * would first set first.data to zero, then check first.data, and never
        * enter the loop since it was zero.
        */
       if (head->data == 0)
       {
          printf("No head");
          return;
       }
    
       /* other code here */
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "nodeTest.h"
    
    int main(void) {
       struct nodeTest* head = malloc(sizeof(struct nodeTest));
       /* check if head is NULL here. Just in case. */
       head->data = 0;
    
       /* we call addLL, passing the head that we just allocated
        * to it.
        */
       addLL(1, head);
       return 0;
    }
    
    void addLL(int data, struct nodeTest *head) {
       if (head == NULL) || (head->data == 0))
       {
          printf("No head");
          return;
       }
    
       /* other code here */
    }