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