『壹』 linux 怎么查找一个数据结构在哪一个头文件里面 例如:
在抄Stat.h里面,要知道这个结构在哪,袭你得使用代码阅读器,才能快速方便的找到。
你会用Source Insight么?这个代码阅读器非常方便。你可以安装一个,然后新建linux内核的工程,然后在工程里面搜索就可以了。
『贰』 数据结构 二叉树的非递归遍历(用栈实现)
这是最近写过的
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
#define NULL 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
typedef int Status;
typedef char TElemType;
typedef struct BiTNode{
TElemType data;
struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree,*SElemType;
typedef struct{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
Status InitStack (SqStack &S)
{//构造空栈并初始化
S.base=(SElemType * )malloc(STACK_INIT_SIZE * sizeof(SElemType));
if(!S.base) exit(OVERFLOW);//存储分配失败
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}
Status StackEmpty(SqStack S)
{//判断是否为空栈,是返回TRUE,不是返回FALSE
if(S.base==S.top)
return TRUE;
else
return FALSE;
}
Status Push(SqStack &S,BiTree e)
{//将元素e压入栈顶
if(S.top-S.base>=S.stacksize)
{//栈满,追加存储空间
S.base=(SElemType *)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof (SElemType));
if(!S.base)exit(OVERFLOW);//存储分配失败
S.top=S.base+S.stacksize;
S.stacksize +=STACKINCREMENT;
}
*S.top++=e;
return OK;
}
Status Pop(SqStack &S,SElemType &e)
{//删除栈顶元素,用e返回其值,并返回OK,否则返回ERROR
if(S.top==S.base) return ERROR;//空栈情况
e=*--S.top;
return OK;
}
Status InitBiTree(BiTree &T)
{//构造空二叉树T
T=NULL;
return OK;
}
BiTree CreateBiTree(BiTree &T)
{//按先序次序输入二叉树中结点的值,空格字符表示空树
//构造二叉链表表示的二叉树T
char ch;
scanf("%c",&ch);
if (ch=='.') T=NULL;
else{
if(!(T=(BiTNode *)malloc(sizeof(BiTNode)))) exit(OVERFLOW);
T->data=ch;
CreateBiTree(T->lchild);
CreateBiTree(T->rchild);
}
return T;
}
Status PrintElement(TElemType e)
{//输出元素e的值
printf("%c",e);
return OK;
}
Status InOrderTraverse2(BiTree T, Status (*Visit)(TElemType)) {
// 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
// 中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit。
SqStack S;
BiTree p;
InitStack(S); p = T;
while (p || !StackEmpty(S)) { //P或stack不为空
if (p) {
Push(S, p);
p = p->lchild;
} // 非空指针进栈,继续左进
else { // 上层指针退栈,访问其所指结点,再向右进
Pop(S, p); //弹栈,将p指向被弹结点
if (!Visit(p->data)) //所访问结点不存在
return ERROR;
p = p->rchild;
}
}
return OK;
} // InOrderTraverse
void main()
{
BiTree T;
InitBiTree(T);
printf("创建二叉树T,空树用.代替:\n");
CreateBiTree(T);
printf("\n非递归算法中序遍历二叉树:");
InOrderTraverse2(T,PrintElement);
printf("\n");
}
『叁』 C++的头文件和实现文件分别写什么
在C++编程过程中,随着项目的越来越大,代码也会越来越多,并且难以管理和分析。于是,在C++中就要分出了头(.h)文件和实现(.cpp)文件,并且也有了Package 的概念。 对于以C 起步,C#作为“母语”的我刚开始跟着导师学习C++对这方面还是感到很模糊。虽然我可以以C 的知识面对C++的语法规范,用C#的思想领悟C++中类的使用。但是C#中定义和实现是都在一个文件中(其实都是在类里面),而使用C 的时候也只是编程的刚刚起步,所写的程序也只要一个文件就够了。因此对于C++的Package 理解以及.h 文件和.cpp 文件的总是心存纠结。 幸好导师有详细的PPT 让我了解,一次对于Package 的认识就明白多了。简单讲,一个Pack age 就是由同名的.h 和.cpp 文件组成。当然可以少其中任意一个文件:只有.h 文件的Packag e 可以是接口或模板(template)的定义;只有.cpp 文件的Package 可以是一个程序的入口。 当然更具体详细的讲解,欢迎下载导师的教学PPT-Package 来了解更多。 不过我在这里想讲的还是关于.h 文件和.cpp 文件 知道Package 只是相对比较宏观的理解:我们在项目中以Package 为编辑对象来扩展和修正我们的程序。编写代码时具体到应该把什么放到.h 文件,又该什么放在.cpp 文件中,我又迷惑了。 虽然Google 给了我很多的链接,但是大部分的解释都太笼统了:申明写在.h 文件,定义实现写在.cpp 文件。这个解释没有差错,但是真正下手起来,又会发现不知道该把代码往哪里打。 于是我又把这个问题抛给了导师,他很耐心地给我详详细细地表述了如何在C++中进行代码分离。很可惜,第一次我听下了,但是没有听太懂,而且本来对C++就了解不深,所以也没有深刻的印象。 经过几个项目的试炼和体验之后,我又拿出这个问题问导师,他又一次耐心地给我讲解了一遍(我发誓他绝对不是忘记了我曾经问过同样的问题),这次我把它记录了下来。 为了不再忘记,我将它们总结在这里。 概览 非模板类型(none-template) 模板类型(template) 头文件 (.h) 全局变量申明(带extern 限定符) 全局函数的申明 带inline 限定符的全局函数的 带inline 限定符的全局模板函数的申明和定义 非模板类型(none-template) 模板类型(template) 定义 类的定义 类函数成员和数据成员的申明(在类内部) 类定义内的函数定义(相当于i nline) 带static const 限定符的数据成员在类内部的初始化 带inline 限定符的类定义外的函数定义 模板类的定义 模板类成员的申明和定义(定义可以放在类内或者类外,类外不需要写inline) 实现文件 (.cpp) 全局变量的定义(及初始化) 全局函数的定义 (无) 类函数成员的定义 类带static 限定符的数据成员的初始化 *申明:declaration *定义:definitio 头文件 头文件的所有内容,都必须包含在 #ifndef {Filename} #define {Filename} //{Content of head file} #endif 这样才能保证头文件被多个其他文件引用(include)时,内部的数据不会被多次定义而造成错误 inline 限定符 在头文件中,可以对函数用inline 限定符来告知编译器,这段函数非常的简单,可以直接嵌入到调用定义之处。 当然inline 的函数并不一定会被编译器作为inline 来实现,如果函数过于复杂,编译器也会拒绝inline。 因此简单说来,代码最好短到只有3-5 行的才作为inline。有循环,分支,递归的函数都不要用做inline。 对于在类定义内定义实现的函数,编译器自动当做有inline 请求(也是不一定inline 的)。因此在下边,我把带有inline 限定符的函数成员和写在类定义体内的函数成员统称为“要inline 的函数成员” 非模板类型 全局类型 就像前面笼统的话讲的:申明写在.h 文件。 对于函数来讲,没有实现体的函数,就相当于是申明;而对于数据类型(包括基本类型和自定义类型)来说,其申明就需要用extern 来修饰。 然后在.cpp 文件里定义、实现或初始化这些全局函数和全局变量。 不过导师一直反复强调:不许使用全局函数和全局变量。用了之后造成的后果,目前就是交上去的作业项目会扣分。当然不能用自有不能用的理由以及解决方案,不过不在目前的讨论范围内。 自定义类型 对于自定义类型,包括类(class)和结构体(struct),它们的定义都是放在.h 文件中。其成员的申明和定义就比较复杂了,不过看上边的表格,还是比较清晰的。 函数成员 函数成员无论是否带有static 限定符,其申明都放在.h 文件的类定义内部。 对于要inline 的函数成员其定义放在.h 文件;其他函数的实现都放在.cpp 文件中。 数据成员 数据成员的申明与定义都是放在.h 文件的类定义内部。对于数据类型,关键问题是其初始化要放在什么地方进行。 对于只含有static 限定符的数据成员,它的初始化要放在.cpp 文件中。因为它是所有类对象共有的,因此必须对它做合适的初始化。 对于只含有const 限定符的数据成员,它的初始化只能在构造函数的初始化列表中完成。因为它是一经初始化就不能重新赋值,因此它也必须进行合适的初始化。 对于既含有static 限定符,又含有const 限定符的数据成员,它的初始化和定义同时进行。它也是必须进行合适的初始化 对于既没有static 限定符,又没有const 限定符的数据成员,它的值只针对本对象可以随意修改,因此我们并不在意它的初始化什么时候进行。 模板类型 C++中,模板是一把开发利器,它与C#,Java 的泛型很相似,却又不尽相同。以前,我一直只觉得像泛型,模板这种东西我可能一辈子也不可能需要使用到。但是在导师的强制逼迫使用下,我才真正体会到模板的强大,也真正知道要如何去使用模板,更进一步是如何去设计模板。不过这不是三言两语可以讲完的,就不多说了。 对于模板,最重要的一点,就是在定义它的时候,编译器并不会对它进行编译,因为它没有一个实体可用。 只有模板被具体化(specialization)之后(用在特定的类型上),编译器才会根据具体的类型对模板进行编译。 所以才定义模板的时候,会发现编译器基本不会报错(我当时还很开心的:我写代码尽然会没有错误,一气呵成),也做不出智能提示。但是当它被具体用在一个类上之后,错误就会大片大片的出现,却往往无法准确定位。 因此设计模板就有设计模板的一套思路和方式,但是这跟本文的主题也有偏。 因为模板的这种特殊性,它并没有自己的准确定义,因此我们不能把它放在.cpp 文件中,而要把他们全部放在.h 文件中进行书写。这也是为了在模板具体化的时候,能够让编译器可以找到模板的所有定义在哪里,以便真正的定义方法。 至于模板类函数成员的定义放在哪里,导师的意见是放在类定义之外,因为这样当你看类的时候,一目了然地知道有那些方法和数据;我在用Visual Studio 的时候查看到其标准库的实现,都是放在类内部的。 可能是我习惯了C#的风格,我比较喜欢把它们都写在类内部,也因为在开发过程中,所使用的编辑器都有一个强大的功能:代码折叠。 当然还有其他原因就是写在类外部,对于每一个函数成员的实现都需要把模板类型作为限定符写一遍,把类名限定符也要写一遍。
『肆』 C语言中exit();怎么用
exit() 结束当前进程/当前程序/,在整个程序中,只要调用 exit ,就结束。
return() 是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如果不是,那就是退回上一层调用。
在多个进程时.如果有时要检测上进程是否正常退出的.就要用到上个进程的返回值。
exit(1)表示进程正常退出. 返回 1;
exit(0)表示进程非正常退出. 返回 0.
操作:
1、进程的开始:
C程序是从main函数开始执行, 原型如下:int main(int argc, char *argv[]),通常main的返回值是int型, 正确返回0.如果main的返回值为void或者无, 某些编译器会给出警告, 此时main的返回值通常是0.
2、进程终止:
C程序的终止分为两种: 正常终止和异常终止.正常终止分为: return, exit, _exit, _Exit, pthreade_exit异常中指分为: abort, SIGNAL, 线程响应取消。正常终止的前4种, 即exit系列函数.
3、 atexit终止处理程序:
ISO C规定, 一个进程最对可登记32个终止处理函数, 这些函数由exit按登记相反的顺序自动调用. 如果同一函数登记多次, 也会被调用多次.
原型如下:
#include
int atexit(void (*func)(void));
其中参数是一个函数指针, 指向终止处理函数, 该函数无参无返回值.
(4)数据结构非递归用哪个头文件扩展阅读
exit函数和return函数的主要区别:
1)exit用于在程序运行的过程中随时结束程序,exit的参数是返回给OS的。main函数结束时也会隐式地调用exit函数。
exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流、关闭所有打开的流并且关闭通过标准I/O函数tmpfile()创建的临时文件。
exit是结束一个进程,它将删除进程使用的内存空间,同时把错误信息返回父进程;而return是返回函数值并退出函数。
通常情况:exit(0)表示程序正常, exit(1)和exit(-1)表示程序异常退出,exit(2)表示表示系统找不到指定的文件。在整个程序中,只要调用exit就结束(当前进程或者在main时候为整个程序)。
2)return是语言级别的,它表示了调用堆栈的返回;return( )是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如果不是,那就是退回上一层调用。
在多个进程时。如果有时要检测上个进程是否正常退出。就要用到上个进程的返回值,依次类推。而exit是系统调用级别的,它表示了一个进程的结束。
3)exit函数是退出应用程序,并将应用程序的一个状态返回给OS,这个状态标识了应用程序的一些运行信息。