『壹』 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,這個狀態標識了應用程序的一些運行信息。