hac*_*atu 0 c binary-tree struct function-pointers header-files
所以,我正在尝试用C创建这个二进制树程序,它只是不断抛出最糟糕的编译错误.每当我更改某些内容以找到导致错误的内容时,它就会发生变化!我没有忘记我的包含守卫,我曾经使用过#pragma.如果我将结构放在标题中,我会得到不兼容的类型,如果我把它放在.c中,我会重新定义pretty_print,当我重命名pretty_print时,它会消失.当我修剪bintree.c中的其他函数和标题时,错误更改为intTree未定义.如果我然后将intTree更改为int,则它变为不兼容的类型.如果我将标头合并到.c中,这就消失了.现在它已经消失了.我认为这些可能是单独的错误,而且变化的错误可能是我的坏事,但它正在发生,我不知道为什么.我将展示代码,演示尽可能多的这些,但每当我尝试复制我所做的时,它会抛出不同的错误.但我并不沮丧.我希望能够发布一个格式正确的问题和有用的信息,但我没有,尽管在这个程序上花了几个小时.
bintree.cxx
#include "bintree.h"
int add(intTree* root,int key,void* val){
if(!root){
root=malloc(sizeof(intTree));
if(!root){
return 1;
}
root->key=key;
root->val=val;
root->left=0;
root->right=0;
return 0;
}
if(key>root->key){
if(root->right){
return add(root->right,key,val);
}else{
root->right=(intTree*) malloc(sizeof(intTree));
if(!root->right){
return 1;
}
root->right->key=key;
root->right->val=val;
root->right->left=0;
root->right->right=0;
return 0;
}
}
if(key<root->key){
if(root->left){
return add(root->left,key,val);
}else{
root->left=malloc(sizeof(intTree));
if(!root->left){
return 1;
}
root->left->key=key;
root->left->val=val;
root->left->left=0;
root->left->right=0;
return 0;
}
}
return 2;
}
void* get(intTree* root,int key){
if(!root){
return 0;
}
if(key>root->key){
return get(root->right,key);
}
if(key<root->key){
return get(root->left,key);
}
return root->val;
}
int remove_root(intTree* root){
if(!root){
return 1;
}
if(root->right){
root->key=root->right->key;
root->val=root->right->val;
return remove_root(root->right);
}
if(root->left){
root->key=root->left->key;
root->val=root->left->val;
return remove_root(root->left);
}
free(root);
return 0;
}
int remove_node(intTree* root,int key){
if(!root){
return 1;
}
if(key>root->key){
return remove_node(root->right,key);
}
if(key<root->key){
return remove_node(root->left,key);
}
return remove_root(root);
}
void delete(intTree* root){
if(root){
delete(root->right);
delete(root->left);
free(root);
}
}
void pretty_print(intTree* root,int ws,int wso,void (*print_val)(void*)){
if(!root) return;
printf("%*s",ws,"");
print_val(root->val);
pretty_print(root->left,ws+wso,wso,print_val);
pretty_print(root->right,ws+wso,wso,print_val);
}
Run Code Online (Sandbox Code Playgroud)
bintree.h
#pragma once
#include <stdlib.h>
typedef struct intTree_s{
int key;
void* val;
struct intTree_s* left;
struct intTree_s* right;
} intTree;
int add(intTree*,int,void*);
void* get(intTree*,int);
int remove_root(intTree*);
int remove_node(intTree*,int);
void delete(intTree*);
void pretty_print(intTree*,int,int,void(*)(void*));
Run Code Online (Sandbox Code Playgroud)
这些抛出了数百个关于intTree的错误类型的错误.对于我用来定义intTree的typedef/struct格式,这仍然存在.
bintree.c
#include "pretty_print.h"
void pretty_print(void){return;}
Run Code Online (Sandbox Code Playgroud)
pretty_print.h
void pretty_print(void);
Run Code Online (Sandbox Code Playgroud)
抛出"pretty_print"的冲突类型,但如果我重命名为"p",内联标题或将参数更改为"int v"则不会.这也适用于参数"int*a,void()(void)",就像在原始程序中一样.
最终的"错误":警告有关malloc,free,printf和puts的隐式重新定义.
bintree.cxx
struct intTree_s{
int key;
void* val;
struct intTree_s* left;
struct intTree_s* right;
};
typedef struct intTree_s intTree;
int add(intTree* root,int key,void* val){
if(!root){
root=malloc(sizeof(intTree));
if(!root){
return 1;
}
root->key=key;
root->val=val;
root->left=0;
root->right=0;
return 0;
}
if(key>root->key){
if(root->right){
return add(root->right,key,val);
}else{
root->right=(intTree*) malloc(sizeof(intTree));
if(!root->right){
return 1;
}
root->right->key=key;
root->right->val=val;
root->right->left=0;
root->right->right=0;
return 0;
}
}
if(key<root->key){
if(root->left){
return add(root->left,key,val);
}else{
root->left=malloc(sizeof(intTree));
if(!root->left){
return 1;
}
root->left->key=key;
root->left->val=val;
root->left->left=0;
root->left->right=0;
return 0;
}
}
return 2;
}
void* get(intTree* root,int key){
if(!root){
return 0;
}
if(key>root->key){
return get(root->right,key);
}
if(key<root->key){
return get(root->left,key);
}
return root->val;
}
int remove_root(intTree* root){
if(!root){
return 1;
}
if(root->right){
root->key=root->right->key;
root->val=root->right->val;
return remove_root(root->right);
}
if(root->left){
root->key=root->left->key;
root->val=root->left->val;
return remove_root(root->left);
}
free(root);
return 0;
}
int remove_node(intTree* root,int key){
if(!root){
return 1;
}
if(key>root->key){
return remove_node(root->right,key);
}
if(key<root->key){
return remove_node(root->left,key);
}
return remove_root(root);
}
void delete(intTree* root){
if(root){
delete(root->right);
delete(root->left);
free(root);
}
}
void pretty_print(intTree* root,int ws,int wso,void (*print_val)(void*)){
if(!root) return;
printf("%*s",ws,"");
print_val(root->val);
pretty_print(root->left,ws+wso,wso,print_val);
pretty_print(root->right,ws+wso,wso,print_val);
}
Run Code Online (Sandbox Code Playgroud)
我似乎无法再生成原始错误,这是关于pretty_print的重新定义.我很少知道我对这个问题知之甚少(基本上就是这样).
隐式重新定义malloc,free,printf和puts.
这意味着您没有包含正确的头文件.将这些添加到调用这些函数的每个C文件中.
#include <stdio.h> // printf, puts and friends
#include <stdlib.h> // malloc/free
Run Code Online (Sandbox Code Playgroud)
不要将它们放在一些常见的头文件中 - 只有在它们暴露您在头文件本身中使用的类型时才这样做.
您正在获得"隐式重新定义",因为如果您不包含正确的头文件,编译器将根据您的使用情况隐式定义其签名(C,IMO的最愚蠢的特征).
人们似乎很难知道.c文件和头文件中的内容.这很简单:
开始将与此组件相关的所有内容(例如,您的intTree实现)放在一个.c文件中.(包括structs).标记所有功能static,这意味着文件外的任何人都看不到它们.
确定哪些功能是您可公开访问的API的一部分.static从这些函数中删除,并将其原型复制/粘贴到该.c文件的附带.h文件中.(例如int add(intTree* root,int key,void* val);).
确定是否struct需要显示任何内容,或者是否可以隐藏它们.最好将实际struct定义隐藏在.C文件中.您的公共API函数将仅指向这些结构,因此外部代码永远不需要知道这些结构的大小/偏移量struct.所以只需添加struct foo;到头文件中,将其定义保留在.C文件中.
例:
foo.c的
#include "foo.h"
/** Definition of struct foo - hidden to consumers of foo **/
struct foo
{
int a;
int b;
int c;
}; /* This always gets forgotten :-) */
/** "private" internal function, marked static to hide from consumers **/
static void _foo_internal(struct foo *f)
{
// ... internal function ****
}
/** Foo Public API **/
struct foo *new_foo(int a, int b, int c)
{
struct foo* f;
f = malloc(sizeof(*f));
if (f == NULL)
return NULL;
_foo_internal(f);
f->a = a;
f->b = b;
f->c = c;
}
int foo_get_a(struct foo *f)
{
_foo_internal(f);
return f->a;
}
void foo_set_a(struct foo *f, int val)
{
_foo_internal(f);
f->a = val;
}
Run Code Online (Sandbox Code Playgroud)
foo.h中
#ifndef FOO_H
#define FOO_H
/**
* Consumers need to know only that struct foo exists,
* not its size of member offsets.
*/
struct foo;
/** Prototypes for foo public API **/
struct foo *new_foo(int a, int b, int c);
int foo_get_a(struct foo *f);
void foo_set_a(struct foo *f, int val);
#endif /* FOO_H */
Run Code Online (Sandbox Code Playgroud)
test.c的
#include "foo.h"
int main(void)
{
/**
* No static instances of foo allowed!
* test.c does not know the size of struct foo!
*/
//struct foo my_foo;
struct foo *pFoo;
pFoo = new_foo(1,2,3);
if (pFoo == NULL)
return 1;
set_foo_a(pFoo, 42);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
133 次 |
| 最近记录: |