利用C語言寫CGI的一些心得整理

關於利用C語言撰寫CGI程式的部分,這也是之前人家面試的時候,所詢問我的另外一個問題,經過這幾天上網找資料,並且撰寫之後,將一些心得整理出來,希望能幫助到有一些疑問的人。其實利用關鍵字『C語言、CGI、GET、POST』還是可以找到蠻多相關的網頁,大部分的資料都嫌老舊,並且都是由同一個作者撰寫而出(不過倒是有蠻多人複製在自己的網站上面–_____–”“),所以在此為各位整理一些概念,而繁瑣的程式碼(關於將STRING去spilit並且找出變數對應值)就不再詳述,可參考以下這個網址,在這裡只專注於觀念上的敘述,希望帶給大家一些基本的概念。

 

利用C語言撰寫CGI程式

CGI( Common Gateway Interface)

**1.放在可以執行的地方

**不論哪種網頁伺服器的主機(IISApache),對於檔案可否執行(execute)的權限管理相當嚴格,尤其是Apache,要由網路上執行某些檔案(通常是CGI),都必須透過,httpd.conf 這個檔案裡面的設定才行(通常預設是 cgi-bin/ ) 。另一方面,對於IIS的設定就方便多了,只要啟動IIS Service將該目錄可執行的權限打開,就可以執行CGI程式。

P.S. 算是FAQ的問題,請注意即便可以執行 C語言的請編譯好用修改權限為可以執行的檔案。

 

**2.C語言中CGI裡面的Hello World!!

**在這裡要跟大家講解對於網頁而言,其實與一般的C語言程式沒有兩樣,重點在於輸出與輸入的介面(UI)。相較於一般的C語言程式,利用C來撰寫的CGI其輸入與輸出都不一樣,首先在輸出方面,最不一樣的就是CGI有以下的輸出

printf (“Content-type: text/htmlnn”);

這個就是代表這是一個網頁的程式,記住”Content-type: text/htmlnn”這段文字儘量不要修改,並且連空白都要注意好(沒有注意好,網頁伺服器會誤認為其他可執行檔案而變成可以下載,而非當成CGI程式),所以根據這個,以下為一個基本的CGI程式

// // File Name test1.cpp // #include #include int main(int argc, char* argv[],char *envp[] ) { printf("Content-type: text/htmlnn"); printf("Hello___World"); } </td> </tr> </table> 各位可將此程式編譯(gcc -o test1.cgi test1.cpp)之後,放在可以執行的目錄下。   **3.CGI中參數的傳入** 如同之前所敘述,CGI程式與一般的程式最大的差別在於資料擷取的不同,網頁資料的擷取上主要有兩種,分別是透過GET與POST。這兩種可以透過表單函數
下去設定,在此引用[Form與CGI的綜合運用](http://www.cc.nctu.edu.tw/~claven/course/www/html_tutorial/formcgi.htm)中作者所畫的一張圖,可以清楚的瞭解變數在此轉換的差別。 [ ![使用C語言寫CGI變數輸入圖](http://www.evanlin.com/blog/archives/0520/img00003.gif) ](http://www.evanlin.com/blog/archives/0520/img00003.gif) 根據以上的圖,有兩一個系統參數可以辨別參數傳過來的方式,就是(REQUEST_METHOD),裡面會儲存傳入變的的方式,利用以下一個簡單的程式可以抓取所有的環境變數:
#include int main(int argc, char* argv[],char *envp[] ) { printf("Content-type: text/htmlnn"); for(int i = 0; envp[i] != NULL; ++i ){ printf(envp[i]); printf("
"); } } </td> </tr> </table> **傳值為GET的取值法:**大家亦可透過[範例程式](http://www.evanlin.com/cgi-bin/g1.cgi)去看,若是在網址列後面輸入變數(?aa=1&bb=2)即可觀察到變數QUERY_STRING裡面百的就是我們所輸入的變數值,在根據裡面的資料去PARSE即可瞭解。若要[使用表單的範例](http://www.evanlin.com/get.html)請看這裡,[若要看詳細CGI程式碼,請看這裡](http://www.evanlin.com/get.txt) **傳值為POST的取值法:**若是透過的方式所傳遞過來的參數,在CGI程式之中,會被當做是Standard_input也就是當成外在輸入(可用getch, gets來抓取),然後在一個個去變數去作PARSE的動作。以下會[有一個範例](http://www.evanlin.com/post.html)的表單傳遞到變數去。[若要看詳細CGI程式碼,請看這裡](http://www.evanlin.com/post.txt) 其實對於字串的PARSE部分,應該有許多寫好的函示可以應用,不過重點還是在於兩種輸入方式對於程式處理上的不同。(切記:GET=>Query_String; POST=>Std_Input)     **參考資料:** 1. [Form與CGI的綜合運用](http://www.cc.nctu.edu.tw/~claven/course/www/html_tutorial/formcgi.htm) 2. [用C語言進行CGI程序程式](http://moon-soft.com/e_commerce/soft/book/ccgi.htm) 3. **[Win32下apache,perl环境建立](http://www.csdn.net/develop/Read_Article.asp?Id=6568)**[ BigApple(原作)](http://www.csdn.net/develop/Read_Article.asp?Id=6568) 4. [CGI範例與寫作](http://www.cs.ntust.edu.tw/~huang/CGI/CGIbyC.htm)

研討會完畢,準備口試,工作確定

今天去真理大學參加研討會,算是第二次參加研討會吧,所以整個流程上算是有一定的瞭解.整個研討會下來,一個感受是,透過學術的交流,其實對於自己的論文品質信心度會增加,也可以間接瞭解到每間資管所在研究領域上有極大的差異與不同.

而在週五的下午也將論文的完搞寄送給每一位評審委員,等待著下週四的口試.而工作也算是確定好了.

不過隨著學生最後一段生涯的尾聲,慢慢的有一些小小的感嘆吧.

C語言相關探討,細究指標(pointer)與參照(reference)

感謝網友『阿仁』對於我BLOG裡面程式碼的訂正,在參考過『More Effective C++』中,對於指標使用上的補充順便加入Reference的一些資料。所以一併將這些資料整理在這裡,順便提一下今天侯捷老師講解一些關於Reference Counting 的概念。只能說很多東西要不斷的複習,不然真的都會遺忘,這幾次的面試有很多間公司都搞砸了也就是因為這個原因,原本五專時代都記得的東西,因為許久沒有使用,真的都忘的乾乾淨淨。

  1. **指標(Pointer)與參照(Reference)
**在C語言中,雖然指標與參照在使用上極為類似,但是實際上有許多地方式都是不同的。我將這些不同做成以下列表出來:  




  
  <table cellspacing="1" border="1" width="62%" >
    <tr >
  指標(Pointer) (type *p) 參照(Reference) (type &p)
    </tr>
    <tr >
記憶體配置 配置指標記憶體(4Byte) 不配置記憶體,本身為別名(Alias)
    </tr>
    <tr >
初始值給定 可以後來指定(不建議,但是允許這樣給值) 必須在變數成立的時候,直接給定初始值
    </tr>
    <tr >
內容值(p) 代表一個記憶體位置,指向給定的目標值 直接代表目標值
    </tr>
    <tr >
設定位置 (目標值Q) p=&Q p=Q (在此為將Q另外設定一個名字p)
    </tr>
    <tr >
給值 (目標值Q) *p=Q (將Q的值給*p) p=Q (在此為將Q另外設定一個名字p)
    </tr>
  </table>
  





  

根據以上的表格,順道提到一般課本常提到的Call by address與
Call by reference的參照方式,撰寫如下:





  
  <table cellspacing="1" border="1" width="57%" >
    <tr >
Call by Address (use Pointer) Call by Reference (use Reference)
    </tr>
  
  <tr >
#include void fun1(int * p, int * q) { *p=*p+*q; } void main() { int i=3,j=4,k; fun1(&i,&j); cout <<i; } </td> #include void fun1(int & p, int & q) { p=p+q; } void main() { int i=3,j=4,k; fun1(i,j); cout <<i; } </td> </tr> </table> 透過這個列表,可以清楚的兩者的差異,所以在之前文章所提到的錯誤為:
int x=10; int *v; *v=x;;
在此錯誤為,由於我的指標 *v 並沒有初始化指標,所以v的值是一個系統給的亂數(或是之前變數留下來的資料),其實這樣去指定是相當危險的一件事情。所以要設定v去指定x的時候,應該使用 v=&x 去設定一個位置在v之中。之前會這樣想也因為我對於字串指標的設定有一點混淆 char *s="test ~~~ string~~~"; 像這樣的句子,雖然也是起使一個指標,但是由於電腦會先根據字串"test ~~~ string~~~"去分配一個位置給他,然後再把位置指定給s ,所以不需要再配置一次位置(記得這個問題在趨勢與友立似乎也一直被問到~~) 但是這裡順道一提 char *s="test ~~~ string~~~"; 與 char s[]="test ~~~ string~~~"; 若要顯示整段文字,勢必得使用後者,因為cout <<*s; 只會顯示出第一個字元,而 cout <<sp[]; cout<<sp; 則會顯示整個字串,這也是字串與指標的一種混和運用。太久沒寫的人(像我),這邊也會有種混淆的感覺@﹍﹍﹍@ 2. **有效的參照與節省記憶體 (Reference Counting )** 同樣在『[More Effective C++](http://www.jjhou.com/jjtbooks-more-effective-cpp.htm)』的第30條之中,裡面有提到一個概念(Reference Counting ),主要是利用運算子多載(Operator Overloading)的概念,將 = (Assign給值)這個運算子,更改其用途,來節省記憶體的使用。一般而言,若是
String a,b,c,d,e; a=b=c=d=e="Hello";
在以上的程式之中,記憶體是會分配『五塊記憶體(大小為STRING)』,因為原來在String中的運算子『=』的定義是Assign by Copy的方式,也就是會同樣的分配一塊記憶體,然後複製其內容值到每一塊記憶體之中。所以若是針對 『=』加以更改其作用值,若是在參考的時候(也就是單純的String 互傳值)的話,應該是將記憶體節省下來,直接讓LHS(左手邊的變數)直接指向RHS(右手邊)的變數才對。並且還要可以計數所有有參照到該記憶體的變數個數(所以才叫Reference Counting),詳細說明,請看『[More Effective C++](http://www.jjhou.com/jjtbooks-more-effective-cpp.htm)』的P.183  

MT-管理許多鍊結時,就用Blogrolling吧?

Blogrolling蠻好用的鍊結管理唷

對於難以管理的友站鍊結,我也決定使用BlogRolling了,至於怎麼使用,我想憂鬱馬戲團上面的教學實在很詳細。此外,身邊的人也很多人這樣使用,不過規勸想使用的人~~~他對中文的支援實在鳥到受不了,每次輸入中文都得切換編碼到[UTF-8],仔細思考阿~~

就醬~~~

軟體試用-MyDriver您的驅動程式管理員

MyDriver很好用的驅動程式管理程式

百分之八十的完美這個BLOG所看到的一個軟體,MyDriver是一套很好用的試用軟體,基本上他算是一個簡單的Driver檔案總管的功能,在我用過裡面的一些功能之後,大家可以去原始網站下載試用版,一共有十五天的試用期,剛下載完安裝的時候語言版本請選「English」,等到執行程式的時候,會自動轉成「簡體中文」(對岸同胞真是厲害~~),MyDriver這個軟體主要功能敘述如下:

  • 自動搜尋系統所有設備的驅動程式

  • 備份系統設備驅動程式

  • 線上更新設備驅動程式

  • 安裝與恢復舊有的驅動程式

其實這些功能實在相當的好用,在這邊展示一下他線上更新Driver的功能給大家看,首先在執行程式之後,選擇第一個選項之後會出現以下的畫面:

1.進入管理畫面後,選擇更新驅動,他就會自動抓取電腦上所有的驅動程式

 按下看大圖形

2.之後列出所有的驅動程式(可能有些不太清楚),就選取可以更新的下載,然後在自行安裝到電腦上

 按下看大圖形

3.選取好設備之後的下載視窗

 按下看大圖形

 

結論:

使用過後來說,對於公司的MIS來說,這套軟體實在有購買的必要,不論是幫你備份驅動程式,或是尋找與更新相對應的驅動程式,若是沒有這個軟體,難保許多人員還要拆開電腦一個個設備去確認與尋找光碟片,有了這個軟體可以解決掉資訊人員在重灌電腦的慘痛經驗,並且也可以節省掉保存一大盒驅動程式的必要(網路卡還是需要,畢竟還是透過網路來更新驅動程式)

MT 整個單篇文章與匯出模版給大家參考

今日來學校加班論文,老師卻不在@﹍﹍﹍@”,但是看見酋長的部落格格式實在不錯,所以將自己的部落格也作了一些修改,修改如下:

  • 將本來主索引中「友站鍊結」整理成一個鍊結方便以後整理

  • 單篇文章的顯示模版(Individual Entry Archive)整合到主模版(main index)之中用來顯示

  • 將每個模版整理出來(詳細資料,請看以下介紹~~~)

依照酋長的部落格,我思考到雖然之前有波一些整合介面的文章,但是深怕大家不太會使用我所提出的一些MT調教的手則,但是雖然像所酋長的部落格所提到一樣可以匯出檔案,我也發現如果要正確的重建所有的檔案,所有的檔案還是需要恢復成原來的名稱(也就是『主索引』還是要改回為index.html)這點倒是讓我想不透,所以我後來的處理方式如下:

  • 將Blog下所有html 檔案(原來的模版檔案,複製到一個自製的目錄區)

  • 更改檔案內容為 txt

如果你的主機系統是在LINUX下面,有一個更方便的方式

  • 建立一個目錄為 template

  • 在 /template 建立 LINK ( ln -s 目的.txt 來源)

  • 比如說 『主索引模版』( ln -s ../index.html ./index.htm.txt )

  •  

雖然這個方法很麻煩,不過我還是將模版列出如下:

主索引::index

樣式表::styles-site.css

總彙整索引::archives

分類彙整

單篇彙整

按時彙整

要參考的請按滑鼠右鍵後,選取另存新檔即可打開