我有三個檔案:link_list_test.c,它具有 main() 函式。test_lib.h, 和test-lib.c
我在 test_lib.h 中定義了結構指標,并在 test_lib.c 中使用了相同的結構指標。但是,它不允許我編譯。
我得到的抱怨是
# test_lib.c, on this line `first_node = malloc(sizeof(struct node_lib));`
conflicting types for 'first_node'; have 'int'
# test_lib.c, struct node_lib *first_node;
previous declaration of 'first_node' with type 'struct node_lib *'
# test_lib.c, if (first_node == NULL) {
expected identifier or '(' before 'if'
# test_lib.c, line first_node->value = 0;
expected '=', ',', ';', 'asm' or '__attribute__' before '->' token
# test_lib.c, first_node = malloc(sizeof(struct node_lib));
data definition has no type or storage class
# test_lib.c, first_node = malloc(sizeof(struct node_lib));
type defaults to 'int' in declaration of 'first_node' [-Wimplicit-int]
這是什么意思?
我使用 VScode 和 GDB。
內容test_lib.h:
#ifndef TEST_LIB_H
#define TEST_LIB_H
#include <stdio.h>
struct node_lib {
int value;
struct node_lib *next;
};
extern struct node_lib *first_node;
extern struct node_lib *current_node;
#endif
內容test_lib.c
#include "test_lib.h"
#include <stdlib.h>
#include <stdio.h>
struct node_lib *first_node;
first_node = malloc(sizeof(struct node_lib));
if (first_node == NULL) {
printf("Unable to allocate memory for new node_lib\n");
exit(EXIT_FAILURE);
}
first_node->value = 0;
// every time calling create_new_node(new_value),
// expect first_node to append a new node with new_value.
void create_new_node(int value) {
struct node_lib *new_list, *p;
new_list = malloc(sizeof(struct node_lib));
if (new_list == NULL) {
printf("Unable to allocate memory for new node_lib\n");
exit(EXIT_FAILURE);
}
new_list->value = value;
new_list->next = NULL;
p = first_node;
while (p->next != NULL) {
p = p->next;
}
p->next = new_list;
printf("%n\n", value);
}
內容link_list_test.c
#include "test_lib.h"
#include <stdio.h>
#include <stdlib.h>
int main() {
create_new_node(1);
create_new_node(2);
create_new_node(3);
return 0;
}
uj5u.com熱心網友回復:
編譯代碼的第一條訊息是
link_list_test.c(7,5): warning C4013: 'create_new_node' undefined; \
assuming extern returning int
線條在create_new_node()哪里?就在浮線下方
struct node_lib *first_node;
first_node = malloc(sizeof(struct node_lib));
if (first_node == NULL) {
printf("Unable to allocate memory for new node_lib\n");
exit(EXIT_FAILURE);
}
first_node->value = 0;
在link_list_test.c
如其他答案所述,您不能在函式之外使用此代碼。將那些錯位的行包裝在一個函式中,讓我們說first_code()
void first_code()
{
first_node = malloc(sizeof(struct node_lib));
if (first_node == NULL)
{
printf(
"Unable to allocate memory for new node_lib\n");
exit(EXIT_FAILURE);
}
first_node->value = 0;
return;
}
使編譯器可以使用代碼,并且仍然存在 2 個錯誤:
test_lib.c(41,12): warning C4477: 'printf' : format string '%n' \
requires an argument of type 'int *', but \
variadic argument 1 has type 'int'
test_lib.c(41,12): warning C4313: 'printf': '%n' in format string \
conflicts with argument 1 of type 'int'
這里
printf("%n\n", value);
并通過更改%n為正常%d您的代碼可以編譯。
我會繼續寫一些你可能覺得有用也可能沒用的東西,所以你可以在這里停止閱讀。
鏈表是一種資料結構。一些東西的容器。在您的情況下,您正在嘗試構建int.
但是串列是節點的集合,并且是指向(或包含)應該進入串列的事物單元的節點。
您應該以這種方式撰寫代碼,您的生活會更輕松:您的下一個串列可能是不可避免的書籍串列,然后是播放串列,它們是一些 Person struct;)
你也不應該使用全域變數。Globals 是一種維護災難,在可能的地方、商業和學院中是被禁止的。
- 由于串列是動態的,請考慮僅使用指標。
- 為了幫助測驗,首先撰寫一個導航串列的函式。
extern盡可能避免。這可能會導致您在鏈接程式時出現許多錯誤。你在這里不需要這個- 始終按照您的方式撰寫代碼:標頭和函式,以及
main()在單獨檔案中的程式。這樣,您可以使用 10s 撰寫許多測驗,main而無需更改 main.js 中的代碼。永遠不要將所有內容都寫在一個檔案中:測驗是一團糟,您將無法在其他程式中使用相同的代碼......
我將更改您的代碼作為示例:
這里我們可以有節點和串列:
typedef struct st_node
{
int value;
struct st_node* next;
} Node;
typedef struct
{
size_t size;
Node* start;
} List;
而且你看到的串列有一個方便size的,就是size_t無符號的。并且該串列僅包含一個指向Node
讓生活更輕松:創造和破壞List
List* create();
List* destroy(List*);
使用指標。指標在C. 我們也需要
int show(List*, const char*);
int insert(int, List*);
現在test_lib.h也是
#ifndef TEST_LIB_H
#define TEST_LIB_H
#include <stdio.h>
typedef struct st_node
{
int value;
struct st_node* next;
} Node;
typedef struct
{
size_t size;
Node* start;
} List;
List* create();
List* destroy(List*);
int show(List*, const char*);
int insert_end(int, List*);
int insert_start(int, List*);
#endif
實作4個功能
create()
List* create()
{
List* one = (List*) malloc(sizeof(List));
if ( one == NULL ) return NULL;
one->size = 0;
one->start = NULL;
return one;
};
以這種方式回傳一個新串列更容易,每個新串列List都有size0 和指標以及您可能需要的任何元資料。可能是名字?創建日期?
destroy()
因為我們知道size它只是一個回圈。
List* destroy(List* L)
{ // here you write the code to
// delete the `size` nodes and
// free them
if (L == NULL) return NULL;
Node* p = L->start; // the 2nd or NULL
Node* temp = NULL;
for (size_t i = 0; i < L->size; i = 1)
{ // delete a node
temp = p->next;
free(p);
p = temp;
} // for
free(L);
return NULL;
}
為什么要回來NULL?為了安全。這段代碼:
#include <stdio.h>
#include <stdlib.h>
#include "test_lib.h"
int main(void)
{
List* one = create();
show(one, "still empty");
one = destroy(one);
return 0;
}
跑步和表演
still empty
List: 0 elements
所以你看到指向串列的指標可以設定NULL在串列被銷毀的同一行:使用無效List指標的機會為零。
show()
也很簡單,因為每個List都有一個size內部(封裝)。并且msg非常方便測驗,如上例所示
int show(List* L, const char* msg)
{
if (L == NULL) return -1; // no list
if (msg != NULL) printf("%s\n", msg);
Node* p = L->start; // can be NULL
printf("List: %d elements\n", (int)L->size);
for (size_t i = 0; i < L->size; i = 1, p = p->next)
printf(" %d", p->value);
printf("\n"); // all in one line: just a test
return 0;
}
在串列末尾插入insert_end()
這與 show 非常相似,因為我們只有前向指標
int insert_end(int value, List* l)
{ // the list has `size` elements
// to insert at the end the last one
// will point to this new one
// the code is similar to show()
if (l == NULL) return -1; // no list
Node* new = (Node*)malloc(sizeof(Node));
new->value = value;
new->next = NULL; // will be the last
Node* p = l->start;
Node* last = NULL;
for (size_t i = 0; i<l->size; i = 1,p=p->next)
last = p;
// so `last` points to the last
// even if the list was empty
l->size = 1;
if (l->size == 1)
{ // ok: was empty
l->start = new; // new start
return 1;
}
last->next = new;
return (int) l->size;
}
在開頭插入更容易insert_start()
int insert_start(int value, List* l)
{
if (l == NULL) return -1; // no list
Node* new = (Node*)malloc(sizeof(Node));
new->value = value;
new->next = NULL;
// list may be empty
if (l->size == 0)
{
l->start = new;
l->size = 1;
return 1;
}
new->next = l->start;
l->start = new;
l->size = 1;
return (int) l->size;
}
一個測驗:在開頭插入 1 到 5 到結尾插入 10 到 6
#include <stdio.h>
#include <stdlib.h>
#include "test_lib.h"
int main(void)
{
List* one = create();
show(one, "still empty");
for (int i = 5; i >= 1; i -= 1) insert_start(i, one);
show(one, "1 to 5");
for (int i = 6; i <= 10; i = 1) insert_end(i, one);
show(one, "\n1 to 10 if ok...");
one = destroy(one);
return 0;
}
這表明
still empty
List: 0 elements
1 to 5
List: 5 elements
1 2 3 4 5
1 to 10 if ok...
List: 10 elements
1 2 3 4 5 6 7 8 9 10
如果您仍在閱讀,您可能會發現以這種方式撰寫更容易閱讀和維護。
代碼test_lib.c
這與上面相同,但如果您想測驗更容易復制
#include <stdio.h>
#include <stdlib.h>
#include "test_lib.h"
List* create()
{
List* one = (List*)malloc(sizeof(List));
if (one == NULL) return NULL;
one->size = 0;
one->start = NULL;
return one;
}
List* destroy(List* L)
{
if (L == NULL) return NULL;
Node* p = L->start; // the 2nd or NULL
Node* temp = NULL;
for (size_t i = 0; i < L->size; i = 1)
{ // delete a node
temp = p->next;
free(p);
p = temp;
} // for
free(L);
return NULL;
}
int show(List* L, const char* msg)
{
if (L == NULL) return -1; // no list
if (msg != NULL) printf("%s\n", msg);
Node* p = L->start; // can be NULL
printf("List: %d elements\n", (int)L->size);
for (size_t i = 0; i < L->size; i = 1)
{
printf(" %d", p->value);
p = p->next;
}
printf("\n"); // all in one line: just a test
return 0;
}
int insert_end(int value, List* l)
{ // the list has `size` elements
// to insert at the end the last one
// will point to this new one
// the code is similar to show()
if (l == NULL) return -1; // no list
Node* new = (Node*)malloc(sizeof(Node));
new->value = value;
new->next = NULL; // will be the last
Node* p = l->start;
Node* last = NULL;
for (size_t i = 0; i<l->size; i = 1,p=p->next)
last = p;
// so `last` points to the last
// even if the list was empty
l->size = 1;
if (l->size == 1)
{ // ok: was empty
l->start = new; // new start
return 1;
}
last->next = new;
return (int) l->size;
}
int insert_start(int value, List* l)
{
if (l == NULL) return -1; // no list
Node* new = (Node*)malloc(sizeof(Node));
new->value = value;
new->next = NULL;
// list may be empty
if (l->size == 0)
{
l->start = new;
l->size = 1;
return 1;
}
new->next = l->start;
l->start = new;
l->size = 1;
return (int) l->size;
}
uj5u.com熱心網友回復:
您不能在函式之外擁有代碼。將您的 3 個檔案合并為 1 個,因為它更容易談論。 如果您使用指向要插入新節點的create_new_node()指標 ( ) 的指標,則變得更加緊湊:n
#include <stdio.h>
#include <stdlib.h>
struct node_lib {
int value;
struct node_lib *next;
};
struct node_lib *first_node = NULL;
void create_new_node(int value) {
struct node_lib **n;
for(n = &first_node; (*n); n = &(*n)->next);
*n = malloc(sizeof(**n));
if(!*n) {
printf("Unable to allocate memory for new node_lib\n");
exit(EXIT_FAILURE);
}
(*n)->value = value;
(*n)->next = NULL;
}
void print_nodes() {
for(struct node_lib *n = first_node; n; n = n->next) {
printf("value=%d\n", n->value);
}
}
int main() {
create_new_node(1);
create_new_node(2);
create_new_node(3);
print_nodes();
return 0;
}
它列印:
1
2
3
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/507327.html
上一篇:c中的switch陳述句數字范圍
