c - 简单的 list 。主文件中的规范(方法、结构)不会在单独的文件(h 和 c)中编译。为什么?

标签 c list struct include

我有一个初学者问题,但它很令人费解。我要生成一个简单的链表。我知道这个概念,所以为该任务编写了标准代码。如果我在主文件的顶部包含此代码,它编译得很好,但我将它们分成一个自己的 c 文件(带有带有结构和方法签名的 h 文件)并包含此文件,我遇到了几个错误,全部正确回到问题,该结构突然未定义。我遇到的编译错误之一是:

slist.h:10: error: unnamed struct/union that defines no instances

注意第 10 行是敲击的末尾(我提供的第一个代码示例中的第 4 行)。 这是我的代码(正如所说,它在 main.c 中符合要求,但如果放在 slist.c/h 中则不然):

typedef struct slist{
    struct slist *nextElement;
    int value;
}slist;

/*
* Generate a list element. Used in append, initialize, insertAtIndex and prepend.
*/
slist* generateListElement(int value){
    slist* a=malloc(sizeof(slist));
    if(a==NULL){
        printf("Couldn't list element!\n");
        exit(EXIT_FAILURE);
    }
    a->value=value;
    a->nextElement=NULL;
    return a;
}

/*
* Intizialise the list.
*/
slist* initialize(int firstData){
    slist* a=generateListElement(1);
    slist* b=generateListElement(firstData);
    a->nextElement=b;
    return a;
}

/*
* Returns 1 if slist is empty 0 otherwise
*/
int isEmpty(slist* list){
    return !(list->value>0);
}

/*
* print the list to the console
*/
void printList(slist* list){
    if(isEmpty(list)){
        printf("List is empty.\n");
    }else{
        int i=1;
        list=list->nextElement;
        while(list->nextElement!=NULL){
            printf("%d: %d\n", i, list->value);
        }
    }
    return;
}

/*
* Append a element to the end of the list 
*/
void append(slist* list,int value){
    slist* z=generateListElement(value);
    while(list->nextElement!=NULL){
        list=list->nextElement;
    }
    list->nextElement=z;
    return;
}

/* 
* Prepend a element to the start of the list
*/
void prepend(slist* list,int value){
    slist* oldFirst=list->nextElement;
    list->value++;
    slist* a=generateListElement(value);
    a->nextElement=oldFirst;
    list->nextElement=a;
    return;
}

/*
* Returns pointer to value of element at given index, 0 if list empty or index out of range
*/
int elementAtIndex(slist* list, int index){
    index=abs(index);
    if(list->value==0 || list->value>=index){
        return 0;
    }
    for(int i=0; i<index && list->nextElement!=NULL; i++){
        list=list->nextElement;
    }
    return list->value;
}

/*
* Insert element at given index, generate elements with value 0 if needed
*/
void insertAtIndex(slist* list, int index, int value){
    index=abs(index);
    slist* a=generateListElement(value);
    if(list->value>index){
        list->value++;
    }else{
        list->value+=1+(index-list->value);
    }
    for(int j=0; j<index; j++){
        if(list->nextElement==NULL){
            slist* insertElement=generateListElement(0);
            list=insertElement;
        }else{
            list=list->nextElement;
        }
    }
    slist* nextToA=list->nextElement;
    list->nextElement=a;
    a->nextElement=nextToA;
    return; 
}

/*
* Remove Element at given index, returns 1 in case of success 0 otherwise (list empty, index out of range etc.)
*/
int removeElementAtIndex(slist* list,int index){
    index=abs(index);
    if(index>list->value){
        return 0;
    }
    slist* a=list;
    slist* b=list->nextElement;
    for(int i=0; i<index; i++){
        a=a->nextElement;
        b=b->nextElement;
    }
    slist* c=b;
    b=b->nextElement;
    a->nextElement=b;
    free(c);
    return 1;
}

/*
* Deletes the entire list.
*/
void deleteList(slist* list){
    slist* a=list;
    slist* b=list->nextElement;
    int index=a->value;
    free(a);
    for(int i=0; i<index; i++){
        a=b;
        b=b->nextElement;
        free(a);
    }
    return;
}

为了避免被说教包括分离我的文件,看起来像这样: slist.h:

#ifndef slist
#define slist

/*
* Starting point for slist is the next element the first element counts the elements in the list
*/
typedef struct slist{
    struct slist* nextElement;
    int value;
}slist;

/*
* Generate a list element. Used in append, initialize, insertAtIndex and prepend
*/
slist* generateListElement(int value);

//...

#endif

slist.c:

#include <stdlib.h>
#include <stdio.h>
#include "slist.h"

/*
* Generate a list element. Used in append, initialize, insertAtIndex and prepend.
*/
slist* generateListElement(int value){
//...

和main.c:

#include <stdio.h>
#include <stdlib.h>

#include "stack.h"

int main(void) { //...

最佳答案

#define slist 

这告诉预处理器用空标记替换头文件中出现的每个 slist 。具体来说,经过预处理后,typedef 变为:

typedef struct {
    struct * nextElement;
    int value;
};

对同一个关键字进行如此多的重载使用通常不是一个好主意。建议您更改头文件以使用不同的 #define 标记作为包含保护。常见的约定是使用大写的文件名。例如:

#ifndef SLIST_H
#define SLIST_H

...

#endif

关于c - 简单的 list 。主文件中的规范(方法、结构)不会在单独的文件(h 和 c)中编译。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36296435/

相关文章:

c - 在 Dev-C++ 中使用 pthreads - 奇怪的错误

java - Unmodifiable 可修改对象列表

c - 在链接链内动态分配和添加结构

c - 如何将焦点从 clutter_stage 转移到 clutter_actor?

c++ - 为什么在存在 typedef 时出现未解析的外部符号错误?

python - 如何在python中构造一组列表项?

c# - 通过 TCP C# 接收结构

go - 即使使用互斥锁,打印结构字段时也会出现竞争条件

c - GDB 打印 char 数组中的所有值

python - 使用 Ansible 从一行文本中提取两个字符串