1. 程式人生 > >整理:狀態機的C語言程式設計

整理:狀態機的C語言程式設計

有限狀態機的實現方式

有限狀態機(Finite State Machine或者Finite State Automata)是軟體領域中一種重要的工具,很多東西的模型實際上就是有限狀態機。
FSM
的實現方式:
1
 switch/case或者if/else
這無意是最直觀的方式,使用一堆條件判斷,會程式設計的人都可以做到,對簡單小巧的狀態機來說最合適,但是毫無疑問,這樣的方式比較原始,對龐大的狀態機難以維護。
2
狀態表維護一個二維狀態表,橫座標表示當前狀態,縱座標表示輸入,表中一個元素儲存下一個狀態和對應的操作。這一招易於維護,但是執行時間和儲存空間的代價較大。
3
使用State Pattern

使用State Pattern使得程式碼的維護比switch/case方式稍好,效能上也不會有很多的影響,但是也不是100%完美。不過Robert C. Martin做了兩個自動產生FSM程式碼的工具,for javafor C++各一個,在http://www.objectmentor.com/resources/index上有免費下載,這個工具的輸入是純文字的狀態機描述,自動產生符合State Pattern的程式碼,這樣developer的工作只需要維護狀態機的文字描述,每必要冒引入bug的風險去維護code
4
使用巨集定義描述狀態機一般來說,C++程式設計中應該避免使用#define,但是這主要是因為如果用巨集來定義函式的話,很容易產生這樣那樣的問題,但是巧妙的使用
,還是能夠產生奇妙的效果。MFC就是使用巨集定義來實現大的架構的。在實現FSM的時候,可以把一些繁瑣無比的if/else還有花括號的組合放在巨集中,這樣,在程式碼中可以3)中狀態機描述文字一樣寫,通過編譯器的預編譯處理產生1)一樣的效果,我見過產生C程式碼的巨集,如果要產生C++程式碼,己軟MFC可以,那麼理論上也是可行的。

二 狀態機的兩種寫法+例項

    有限狀態機FSM思想廣泛應用於硬體控制電路設計,也是軟體上常用的一種處理方法(軟體上稱為FMM--有限訊息機)。它把複雜的控制邏輯分解成有限個穩定狀態,在每個狀態上判斷事件,變連續處理為離散數字處理,符合計算機的工作特點。同時,因為有限狀態機具有有限個狀態,所以可以在實際的工程上實現。但這並不意味著其只能進行有限次的處理,相反,有限狀態機是閉環系統,有限無窮,可以用有限的狀態,處理無窮的事務。

    有限狀態機的工作原理如圖1所示,發生事件(event)後,根據當前狀態(cur_state),決定執行的動作(action),並設定下一個狀態號(nxt_state)。

                         -------------

                         |           |-------->執行動作action

     發生事件event ----->| cur_state |

                         |           |-------->設定下一狀態號nxt_state

                         -------------

                            當前狀態

                      圖1 有限狀態機工作原理

                               e0/a0

                              --->--

                              |    |

                   -------->----------

             e0/a0 |        |   S0   |-----

                   |    -<------------    | e1/a1

                   |    | e2/a2           V

                 ----------           ----------

                 |   S2   |-----<-----|   S1   |

                 ----------   e2/a2   ----------

                       圖2 一個有限狀態機例項

              --------------------------------------------

              當前狀態   s0        s1        s2     | 事件

              --------------------------------------------

                       a0/s0      --       a0/s0   |  e0

              --------------------------------------------

                       a1/s1      --        --     |  e1

              --------------------------------------------

                       a2/s2     a2/s2      --     |  e2

              --------------------------------------------

               表1 圖2狀態機例項的二維表格表示(動作/下一狀態)

    圖2為一個狀態機例項的狀態轉移圖,它的含義是:

        在s0狀態,如果發生e0事件,那麼就執行a0動作,並保持狀態不變;

                 如果發生e1事件,那麼就執行a1動作,並將狀態轉移到s1態;

                 如果發生e2事件,那麼就執行a2動作,並將狀態轉移到s2態;

        在s1狀態,如果發生e2事件,那麼就執行a2動作,並將狀態轉移到s2態;

        在s2狀態,如果發生e0事件,那麼就執行a0動作,並將狀態轉移到s0態;

    有限狀態機不僅能夠用狀態轉移圖表示,還可以用二維的表格代表。一般將當前狀態號寫在橫行上,將事件寫在縱列上,如表1所示。其中“--”表示空(不執行動作,也不進行狀態轉移),“an/sn”表示執行動作an,同時將下一狀態設定為sn。表1和圖2表示的含義是完全相同的。

    觀察表1可知,狀態機可以用兩種方法實現:豎著寫(在狀態中判斷事件)和橫著寫(在事件中判斷狀態)。這兩種實現在本質上是完全等效的,但在實際操作中,效果卻截然不同。

==================================

豎著寫(在狀態中判斷事件)C程式碼片段

cur_state = nxt_state;

switch(cur_state)

{                  //在當前狀態中判斷事件

        case s0:                        //在s0狀態

            if(e0_event)

{ //如果發生e0事件,那麼就執行a0動作,並保持狀態不變;

                執行a0動作;

              //nxt_state = s0; //因為狀態號是自身,所以可以刪除此句,以提高執行速度。

            }

            else if(e1_event)

{//如果發生e1事件,那麼就執行a1動作,並將狀態轉移到s1態;

                執行a1動作;

                nxt_state = s1;

            }

            else if(e2_event)

{ //如果發生e2事件,那麼就執行a2動作,並將狀態轉移到s2態;

                執行a2動作;

                nxt_state = s2;

            }

            break;

        case s1:                        //在s1狀態

            if(e2_event)

{    //如果發生e2事件,那麼就執行a2動作,並將狀態轉移到s2態;

                執行a2動作;

                nxt_state = s2;

            }

            break;

        case s2:                        //在s2狀態

            if(e0_event)

{ //如果發生e0事件,那麼就執行a0動作,並將狀態轉移到s0態;

                執行a0動作;

                nxt_state = s0;

            }

    }

==================================

橫著寫(在事件中判斷狀態)C程式碼片段

==================================

//e0事件發生時,執行的函式

void e0_event_function(int * nxt_state)

{

    int cur_state;

    cur_state = *nxt_state;

switch(cur_state)

{

        case s0:                        //觀察表1,在e0事件發生時,s1處為空

        case s2:

            執行a0動作;

            *nxt_state = s0;

    }

}

//e1事件發生時,執行的函式

void e1_event_function(int * nxt_state)

{

    int cur_state;

    cur_state = *nxt_state;

switch(cur_state)

{

        case s0:                        //觀察表1,在e1事件發生時,s1和s2處為空

            執行a1動作;

            *nxt_state = s1;

    }

}

//e2事件發生時,執行的函式

void e2_event_function(int * nxt_state)

{

    int cur_state;

    cur_state = *nxt_state;

switch(cur_state)

{

        case s0:                        //觀察表1,在e2事件發生時,s2處為空

        case s1:

            執行a2動作;

            *nxt_state = s2;

    }

}

    上面橫豎兩種寫法的程式碼片段,實現的功能完全相同,但是,橫著寫的效果明顯好於豎著寫的效果。理由如下:

    1、豎著寫隱含了優先順序排序(其實各個事件是同優先順序的),排在前面的事件判斷將毫無疑問地優先於排在後面的事件判斷。這種if/else if寫法上的限制將破壞事件間原有的關係。而橫著寫不存在此問題。

    2、由於處在每個狀態時的事件數目不一致,而且事件發生的時間是隨機的,無法預先確定,導致豎著寫淪落為順序查詢方式,結構上的缺陷使得大量時間被浪費。對於橫著寫,在某個時間點,狀態是唯一確定的,在事件裡查詢狀態只要使用switch語句,就能一步定位到相應的狀態,延遲時間可以預先準確估算。而且在事件發生時,呼叫事件函式,在函式裡查詢唯一確定的狀態,並根據其執行動作和狀態轉移的思路清晰簡潔,效率高,富有美感。

    總之,我個人認為,在軟體裡寫狀態機,使用橫著寫的方法比較妥帖。

    豎著寫的方法也不是完全不能使用,在一些小專案裡,邏輯不太複雜,功能精簡,同時為了節約記憶體耗費,豎著寫的方法也不失為一種合適的選擇。

    在FPGA類硬體設計中,以狀態為中心實現控制電路狀態機(豎著寫)似乎是唯一的選擇,因為硬體不太可能靠事件驅動(橫著寫)。不過,在FPGA裡有一個全域性時鐘,在每次上升沿時進行狀態切換,使得豎著寫的效率並不低。雖然在硬體裡豎著寫也要使用IF/ELSIF這類查詢語句(用VHDL開發),但他們對映到硬體上是組合邏輯,查詢只會引起門級延遲(ns量級),而且硬體是真正並行工作的,這樣豎著寫在硬體裡就沒有負面影響。因此,在硬體設計裡,使用豎著寫的方式成為必然的選擇。這也是為什麼很多搞硬體的工程師在設計軟體狀態機時下意識地只使用豎著寫方式的原因,蓋思維定勢使然也。

    TCP和PPP框架協議裡都使用了有限狀態機,這類軟體狀態機最好使用橫著寫的方式實現。以某TCP協議為例,見圖3,有三種類型的事件:上層下達的命令事件;下層到達的標誌和資料的收包事件;超時定時器超時事件。

                    上層命令(open,close)事件

            -----------------------------------

                    --------------------

                    |       TCP        |  <----------超時事件timeout

                    --------------------

            -----------------------------------

                 RST/SYN/FIN/ACK/DATA等收包事件

                    圖3 三大類TCP狀態機事件

    由圖3可知,此TCP協議棧採用橫著寫方式實現,有3種事件處理函式,上層命令處理函式(如tcp_close);超時事件處理函式(tmr_slow);下層收包事件處理函式(tcp_process)。值得一提的是,在收包事件函式裡,在各個狀態裡判斷RST/SYN/FIN/ACK/DATA等標誌(這些標誌類似於事件),看起來象豎著寫方式,其實,如果把包頭和資料看成一個整體,那麼,RST/SYN/FIN/ACK/DATA等標誌就不必被看成獨立的事件,而是屬於同一個收包事件裡的細節,這樣,就不會認為在狀態裡查詢事件,而是總體上看,是在收包事件裡查詢狀態(橫著寫)。

    在PPP裡更是到處都能見到橫著寫的現象,有時間的話再細說。我個人感覺在實現PPP框架協議前必須瞭解橫豎兩種寫法,而且只有使用橫著寫的方式才能比較完美地實現PPP。

用C語言實現有限狀態機--讀《C專家程式設計》

有限狀態機(finite state machine)是一個數學概念,如果把它運用於程式中,可以發揮很大的作用。它是一種協議,用於有限數量的子程式("狀態")的發展變化。每個子程式進行一些處理並選擇下一種狀態(通常取決於下一段輸入)。

         有限狀態機(FSM)可以用作程式的控制結構。FSM對於那些基於輸入的在幾個不同的可選動作中進行迴圈的程式尤其合適。投幣售貨機就是FSM的一個好例子。另外一個你可以想到的複雜的例子就是你正在用的東西,想到了嗎?沒錯,就是作業系統。在投幣售貨機的例子中,輸入是硬幣,輸出是待售商品,售貨機有"接受硬幣","選擇商品","傳送商品"和"找零錢"等幾種狀態。

它的基本思路是用一張表儲存所有可能的狀態,並列出進入每個狀態時可能執行的所有動作,其中最後一個動作就是計算(通常在當前狀態和下一次輸入字元的基礎上,另外再經過一次表查詢)下一個應該進入的狀態。你從一個"初始狀態"開始。在這一過程中,翻譯表可能告訴你進入了一個錯誤狀態,直到到達結束狀態。

在C語言中,有好幾種方法可以用來表達FSM,但它們絕大多數都是基於函式指標陣列。一個函式指標陣列可以像下面這樣宣告:

void (*state[MAX_STATES]) ();

如果知道了函式名,就可以像下面這樣對陣列進行初始化。

extern int a(),b(),c(),d();

int (*state[]) ()={a,b,c,c};

可以通過陣列中的指標來呼叫函式:

(*state[i]) ();

所有函式必須接受同樣的引數,並返回同種型別的返回值(除非你把陣列元素做成一個聯合)。函式指標是很有趣的。注意,我們可以去掉指標形式,把上面的呼叫寫成:

state[i] ();

甚至

(******state[i]) ();

這是一個在ANSI C中流行的不良方法:呼叫函式和通過指標呼叫函式(或任意層次的指標間接引用)可以使用同一種語法。

如果你想幹得漂亮一點,可以讓狀態函式返回一個指向通用後續函式的指標,並把它轉換為適當的型別。這樣,就不需要全域性變量了。如果你不想搞得太花哨,可以使用一個switch語句作為一種簡樸的狀態機,方法是賦值給控制變數並把switch語句放在迴圈內部。關於FSM還有最後一點需要說明:如果你的狀態函式看上去需要多個不同的引數,可以考慮使用一個引數計數器和一個字串指標陣列,就像main函式的引數一樣。我們熟悉的int argc,char *argv[]機制是非常普遍的,可以成功地應用在你所定義的函式中。

例項:密碼鎖:以思維密碼校驗作為狀態機的例子,連續輸入2479就可以通過密碼測試。

程式碼一:

#include <stdio.h>

#include<stdlib.h>

#include<string.h>

typedef enum

{

        STATE0 = 0,

        STATE1,

        STATE2,

        STATE3,

        STATE4,

}STATE;

typedef enum

{

        INPUT1 = '2',

        INPUT2 = '4',

        INPUT3 = '7',

        INPUT4 = '9',

}INPUT;

int main()

{

        char ch;

        STATE current_state = STATE0;

        while(1)

        {

                printf("please input number to decode:");

                while((ch = getchar())!='/n')

                {

                        if((ch<'0')||(ch>'9'))

                        {

                                printf("not number, please input again!/n");

                                break;

                        }

                        switch(current_state)

                        {

                                case STATE0:

                                        if(ch == '2') current_state = STATE1;

                                        break;

                                case STATE1:

                                        if(ch == '4') current_state = STATE2;

                                        break;

                                case STATE2:

                                        if(ch == '7') current_state = STATE3;

                                        break;

                                case STATE3:

                                        if(ch == '9') current_state = STATE4;

                                        break;

                                default:

                                        current_state = STATE0;

                                        break;

                        }

                }

                if(current_state == STATE4)

                {

                        printf("corrent, lock is open!/n");

                        current_state = STATE0;

                }

                else

                {

                        printf("wrong, unlocked!/n");

                        current_state = STATE0;

                }

        }

        return 0;

}

程式碼二:

//FSMstate.h

typedef enum{

        STATE0 = 0,

        STATE1,

        STATE2,

        STATE3,

        STATE4,

}STATE;

typedef enum{

        INPUT1 = '2',

        INPUT2 = '4',

        INPUT3 = '7',

        INPUT4 = '9',

}INPUT;

typedef struct

{

        STATE cur_state;

        INPUT input;

        STATE next_state;

}STATE_TRANS;

//FSMstate.c

#include<stdio.h>

#include"FSMstate.h"

/*typedef enum

{

        STATE0 = 0,

        STATE1,

        STATE2,

        STATE3,

        STATE4,

}STATE;

typedef enum

{

        INPUT1 = '2',

        INPUT2 = '4',

        INPUT3 = '7',

        INPUT4 = '9',

}INPUT;

typedef struct

{

        STATE cur_state;

        INPUT input;

        STATE next_state;

}STATE_TRANS;

*/

STATE_TRANS state_trans_array[]=

{

        {STATE0,INPUT1,STATE1},

        {STATE1,INPUT2,STATE2},

        {STATE2,INPUT3,STATE3},

        {STATE3,INPUT4,STATE4},

};

#define STATE_TRANS_CNT (sizeof(state_trans_array)/sizeof(state_trans_array[0]))

int main()

{

        int i;

        char ch;

        STATE state_machine = STATE0;

        while(ch!= 'e')

        {

          ch = getchar();

            if((ch>= '0')&&(ch<='9'))

            {

              for(i = 0;i<STATE_TRANS_CNT ;i++)

                {

                 if((ch==state_trans_array[i].input)&&(state_machine==state_trans_array[i].cur_state))

                {

                                     state_machine = state_trans_array[i].next_state;

                                        //continue;

                                        break;

                                }

                                else if(i==(STATE_TRANS_CNT-1))

                                {

                                        state_machine = STATE0;

                                }

                        }

                        if(state_machine == STATE4)

                                printf("Password correct,state transfer machine pass!/n");

                }

        }

        return 0;

}

四 有限狀態機自動機

狀態圖--一個圖的資料結構!

1.while + switch;

2.狀態機:就是指定系統的所有可能的狀態及狀態間跳轉的條件,然後設一個初始狀態輸入給這臺機器,機器就會自動運轉,或最後處於終止狀態,或在某一個狀態不斷迴圈。

遊戲中狀態切換是很頻繁的。 可能以前要切換狀態就是if~else,或者設標誌,但這些都不太結構化, 如果把它嚴格的設為一種標準的狀態機,會清楚的多。

比如控制一扇門的運動, 初始時門是關的, 當有力作用在門上時, 門開始慢慢開啟,力的作用完後,門漸漸停止不動, 當有反向的力時,門又漸漸關上, 知道回到初始關的狀態。 這個你會怎麼來程式設計實現呢。 似乎很麻煩, 的確,沒有狀態機的思想時會很煩,設很多標誌,一堆if條件。

用狀態機的話,不只是程式碼更清晰, 關鍵是更符合邏輯和自然規律, 不同狀態不同處理, 滿足條件則跳轉到相關狀態。

偽碼如下:

enum 

{  

 CLOSED, // 關上狀態  

 CLOSING, // 正在關狀態  

 OPENED, // 開啟狀態  

 OPENING, // 正在開的狀態  

}doorState = CLOSED; // 初始為關  

Update()  

{  

     switch(doorState)  

     case CLOSED:  

          if (有人推門)  

               doorState = OPENING; // 跳轉到正在開狀態  

     break;  

     case OPENING:  

          door.Rotation += DeltaAngle; // 門的旋轉量遞增  

          if (門的速度為零) / / 力的作用已去  

               doorState = OPENED; // 跳轉到開狀態  

    break;  

    case OPENED:  

         if (有人關門)  

              doorState = CLOSING;  

   break;  

   case CLOSING:  

         door.Rotation -= DeltaAngle; // 門的旋轉量遞減  

         if (門的旋轉角度減為零)  

              doorState = CLOSED; // 門已關上  

    break;   

}  

  // 而繪製程式碼幾乎不用怎麼變, 門就是會嚴格按照狀態機的指示去運動, 該停就會停  

Render()  

{  

     RotateView(door.Rotation);  

     DrawDoor(door.Position);  

這是一個簡單但很典型的例子, 狀態機的應用太多了。

就說一個基本遊戲的運轉: (用到了一個狀態然後還有子狀態)

UpdateGame()  

BEGIN;  

   switch(gameState)  

   case 等待選擇選單: //它有三個子狀態。  

   if (選擇選單項 == 開始)  

   {  

       遊戲初始;  

      gameState = 開始遊戲  

   }  

   if (選擇選單項 == 選項)  

      gameState = 設定  

   if (選擇選單項 == 退出)  

       gameState = 退出  

   case 開始:  

     遊戲執行;  

 if (使用者按退出鍵)  

 gameState = 等待選擇選單 ;  

 ...其他的狀態跳轉處理;  

 case 退出:  

 釋放資源;  

 退出;  

 case 設定:  

 分別處理不同的選項, 跳轉不同的子狀態;  

 case .... // 其他狀態的處理  

    END; 

某一個狀態可以包含更多的子狀態, 這樣最好是同一層次的狀態設為一個列舉, 並分到另一個switch處理如 enum STATES{state1, state2, state3}; state2又包含若干狀態則再定義enum SUB_STATE2{sub_state2_1, sub_state2_2, sub_state2_3,};

想很多基本的渲染效果, 如淡入淡出, 閃爍等等, 用狀態的思想會事半功倍, 思路也更清晰。

其實像Opengl, Direct3D這樣的渲染引擎本身就是狀態機, 當你設定渲染的狀態, 這臺機器就保持這個狀態進行渲染工作,如保持光照位置,保持片元顏色, 直到你再次改變它的狀態。

狀態機的應用實在太廣, 相關理論也很多, 最近上課學的隨機過程裡也講到一些, 數字電路里的時序邏輯器件也是用狀態機來描述。 這些不必多說了。

總之, 用狀態機的角度去看待問題, 往往能把比較複雜的系統分解為能單獨處理的眾多子狀態, 處理也會得心應手。希望大家多用它, 很好的東西。

五.用C語言實現一個狀態機,這是一位好心的網友的畢業設計,用nRF24L01組建了一個簡單的網路,做的一個小的狀態機,網路中三個節點,開始拓撲為網狀,後來為星型。

#include <stdio.h> 

#include <stdlib.h> 

#include <string.h>  

  //Finite state machine declaration  

//state declaration 

#define IDLE 0 //idle state in rx mode 

#define M_BROADCAST 1 //broadcast state in tx mode,broadcast to be a master point 

#define M_WAIT_BROADCAST_ACK 2 //wait for broadcast ack state in rx mode,wait for the point ack in a specific time window 

#define M_WAIT_COMMAND 3 //wait for command state,wait for PC command via UART 

#define M_BROADCAST_CANCEL 4 //broadcast cancel state,broadcast to cancel master point 

#define S_BROADCAST_ACK 5 //slave mode,send back self physical address 

#define S_WAIT_COMMAND 6 //slave mode, wait for command from the master point  

//state transition trig  

//used in master mode  

int isReqBeMaster = 0;//Is PC request the point to be master?  

int isTimeout = 0;//Is time out?  

int isReqCancelMaster = 0;//Is request to cancel master?  

//used in slave mode  

int isRxBroadcast = 0;//Is there a point broadcast to be master?  

int isRxBroadcastCancel = 0;//Is receive broadcast cancel master?  

typedef struct fsmtag  

{  

    int state; //state  

    int timeouttime; //time out time in milliseconds  

}fsm;  

  //function prototype  

  int main()  

{  

    fsm f;  

      f.state = IDLE;  

    f.timeouttime = 0;  

      while(1)  

    {  

        switch(f.state)  

        {  

        case IDLE:  

            puts("IDLE/nWait for isReqBeMaster(1/0) isRxBroadcast(1/0):");  

            scanf("%d %d",&isReqBeMaster,&isRxBroadcast);  

            if(isReqBeMaster)  

            {  

                f.state = M_BROADCAST;  

                break;  

            }  

            else if(isRxBroadcast)  

            {  

                f.state = S_BROADCAST_ACK;  

                break;  

            }  

            else 

                break;  

        case M_BROADCAST:   

            puts("M_BROADCAST/nBroadcasting.../n");  

            f.state = M_WAIT_BROADCAST_ACK;  

        case M_WAIT_BROADCAST_ACK:  

            puts("M_WAIT_BROADCAST_ACK/nWaiting for isTimeout(1/0):");  

            scanf("%d",&isTimeout);  

            if(isTimeout)  

            {  

                f.state = M_WAIT_COMMAND;  

                break;  

            }  

            else 

                break;  

        case M_WAIT_COMMAND:  

            puts("M_WAIT_COMMAND/nWaiting for isReqCancelMaster(1/0):");  

            scanf("%d",&isReqCancelMaster);  

            if(isReqCancelMaster)  

            {  

相關推薦

整理狀態C語言程式設計

一有限狀態機的實現方式 有限狀態機(Finite State Machine或者Finite State Automata)是軟體領域中一種重要的工具,很多東西的模型實際上就是有限狀態機。 FSM

整理狀態的兩種寫法對比

    狀態機可以用兩種方法實現:豎著寫(在狀態中判斷事件)和橫著寫(在事件中判斷狀態)。這兩種實現在本質上是完全等效的,但在實際操作中,效果卻截然不同。 ====================

狀態C語言程式設計(轉)

一有限狀態機的實現方式 有限狀態機(Finite State Machine或者Finite State Automata)是軟體領域中一種重要的工具,很多東西的模型實際上就是有限狀態機。 FSM的實現方式: 1) switch/case或者if/else這無意是最直觀

課上補做C語言程式設計實現ls命令

課上補做:用C語言程式設計實現ls命令 一、有關ls ls :用來列印當前目錄或者制定目錄的清單,顯示出檔案的一些資訊等。 ls -l:列出長資料串,包括檔案的屬性和許可權等資料 ls -R:連同子目錄一同顯示出來,也就所說該目錄下所有檔案都會顯示出來 ls -a:可以將目錄下的全部檔案

《我的第①本c語言程式設計C語言從入門到精通》掃描版.pdf

書籍簡介: 《C語言從入門到精通》以零基礎講解為宗旨,用例項引導讀者深入學習,採取“基礎知識→核心技術→趣味題解→專案實戰”的講解模式,深入淺出地講解C語言的各項技術及實戰技能。《C語言從入門到精通》第1篇【基礎知識】主要講解步入C的世界、常量與變數、資料型別、運算子和表示式、程式控制結構

Linux C程式設計之一Linux下c語言的開發環境

—恢復內容開始— 今天開始根據Linux C程式設計相關視訊的學習所做的筆記,希望能一直堅持下去。。。 1、開發環境的構成 編輯器:VI; 編譯器:選擇GNU C/C++編譯器gcc; 偵錯程式:應用廣泛的gdb; 函式庫:glibc ; 系統標頭檔案:glibc_header; 2、在安裝L

c語言程式設計用strcpy比較陣列(銀行卡密碼程式設計),strcpy(複製陣列內容)和getchar()(敲鍵盤字元,統計不想要的字元的個數)

統計從鍵盤輸入一行字元的個數:   1 //用了getchar() 語句 2 //這裡的\n表示回車 1 #include <stdio.h> 2 #include <stdlib.h> 3 int main() 4 { 5 int n =

C語言程式設計現代方法(第2版)(K.N.King 著)》學習筆記一C語言概述

1.1 C語言的歷史 1.1.1 起源 C語言是美國貝爾實驗室的 Dennis Ritchie、Ken Thompson 等人為開發 UNIX 作業系統而於 1972 年設計的一種計算機程式語言。

C語言程式設計現代方法(第2版)(K.N.King 著)》學習筆記三C語言基本概念(2)

2.3 註釋 每一個程式都應該包含識別資訊,即程式名、編寫日期、作者、程式的用途以及其他相關資訊。C語言把這類資訊放在註釋(comment)中。 符號 /* 標記註釋的開始,而符號 */ 則標記註釋

C語言程式設計現代方法(第2版)(K.N.King 著)》學習筆記四C語言基本概念(3)

2.5 讀入輸入 為了獲取輸入,就要用到 scanf 函式。它是C函式庫中與 printf 相對應的函式。scanf 中的字母 f 和 printf 中的字母 f 含義相同,都是表示“格式化”的意思

C語言程式設計現代方法(第2版)(K.N.King 著)》學習筆記五C語言基本概念(4)

2.7 識別符號 在編寫程式時,需要對變數、函式、巨集和其他實體進行命名。這些名字稱為識別符號(identifier)。在C語言中,識別符號可以含有字母、數字和下劃線,但是必須以字母或者下劃線開頭。

C語言程式設計現代方法(第2版)(K.N.King 著)》學習筆記六C語言基本概念(5)

問與答 GCC 最初是 GNU C Compiler 的簡稱。現在指 GNU Compiler Collection,這是因為最新版本的 GCC 能夠編譯用 Ada、C、C++、Fortran、Ja

C語言程式設計圖書管理系統(超詳細有登入系統,附程式碼和試驗報告)

C課程設計——圖書管理系統 1、題目意義 圖書館,作為文獻的聚集地和展示平臺,常常扮演著引領文化前進的角色,是每個大學不可或缺的基礎設施,而圖書管理系統則是一個圖書館能夠正常運轉的關鍵。本次課程設計使用C語言製作程式來實現圖書的登記,刪除,查詢,瀏覽以及讀者的借

C語言程式設計現代方法(第2版)(K.N.King 著)》學習筆記九格式化輸入/輸出(2)

3.2 scanf 函式 就如同 printf 函式用特定的格式顯示輸出一樣,scanf 函式也根據特定的格式讀取輸入。像 printf 函式的格式串一樣,scanf 函式的格式串也可以包含普通字元

KST-51微控制器c語言程式設計實現數碼管動態顯示秒錶的倒計時

/*60S倒計時*/ /*個位每1S變一次,從0~9*/ /*十位,個位為0的下一秒十位發生變化*/ #include<reg52.h> sbit ADDR0=P1^0; sbit ADDR1=P1^1; sbit ADDR2=P1^2; sbit ADDR3

大學生學程式設計(六)如何學習C語言

現在很多人初學者直接選擇C語言的人已經變得越來越少了,主要原因還是在招聘崗位數量上無法和java,php等高階語言想媲美,但並不代表C語言已經窮途末路沒有前景了,C語言的角色從前臺變成了後臺服務,在一些關鍵領域還承擔著不可替代的作用,並且,雖然目前C語言的學習熱度大不如從前,但他的市場需求仍

MOOC北京理工《C語言程式設計(上)》第5周第3題求最小m值

題目內容: 求滿足下列不等式的最小 m。     1 + 2 + 3 + 4 + ...... + m ≥ n 例如:n=100,當 m =14 時,滿足:1+2+3+4+...+13=91<100,而 1+2+3+4+......+14=105>100

MOOC北京理工《C語言程式設計(上)》第6周第3題郵票組合

題目內容: 我們寄信都要貼郵票,在郵局有一些小面值的郵票,通過這些小面值郵票中的一張或幾張的組合,可以滿足不同郵件的不同的郵資。 現在,郵局有4種不同面值的郵票。在每個信封上最多能貼5張郵票,面值可相同,可不同。 輸入格式: 四種郵票的面值。 輸出格式: 用這四

MOOC北京理工《C語言程式設計(上)》第5周第1題鍛鍊身體吧

題目內容: 沫沫,灰灰和渣渣去鍛鍊身體,如果對他們跑步的距離分別只計整數 a、 b、 c,由於他們身高的差距,造成了 a<=b<=c,並且渣渣跑了N米之後就再也跑不動了。但是,按照他們事先的約定: 只有當 c*c==a*a+b*b 時,他們的鍛鍊才有效果。

C語言程式設計把一個分數分解成n個埃及分數 的和形式,n最小

1.題目分析:把真分數表示為埃及分數之和的形式,所謂的埃及分數是指分子為1的分數例如:7/8=1/2+1/3+1/24;要求用最少的埃及分數來表示解析:設a、b為互質正整數,a<b 分數a/b 可用以下的步驟分解成若干個單位分數之和:步驟一: 用b 除以a,得商數q1