歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> Linux C 編程技巧

Linux C 編程技巧

日期:2017/3/3 11:50:49   编辑:Linux技術
我們知道,一般編寫程序時都要畫出流程圖,按照流程圖結構來編程,如果編寫一個比較繁瑣,容易思維混亂的程序時,我們可以利用有限狀態機模型畫出一個狀態轉移圖,這樣便可以利用畫出的邏輯圖來編寫程序,簡潔且不易出錯。
那什麼是有限狀態機是什麼意思呢?百度百科上這樣解釋:
有限狀態機,(英語:Finite-state machine, FSM),又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動作等行為的數學模型。

常見的計算機就是使用有限狀態機作為計算模型的:對於內存的不同狀態,CPU通過讀取內存值進行計算,更新內存中的狀態。CPU還通過消息總線接受外部輸入設備(如鍵盤、鼠標)的指令,計算後更改內存中的狀態,計算結果輸出到外部顯示設備(如顯示器),以及持久化存儲在硬盤。
電腦游戲設計中也經常使用有限狀態機模型。以水果忍者游戲為例,游戲中水果的狀態是有限狀態,其運行軌跡是由模擬物理運動規律的計算公式運算而成的,一個香蕉拋起來後會按照拋物線運行,其每一幀位置變化都是一個狀態的改變,狀態改變通過計算公式來決定。當然作為游戲不會僅僅這麼簡單,如果這麼簡單就是動畫了,游戲還有復雜的人機交互事件,比如用手在屏幕上“切”了水果,水果感知到這個事件後,會按照程序邏輯進入爆炸狀態。
簡單知道其定義是沒有用的,在C編程中我們改如何應用呢?
例題1:去除一個字符串中連續的空格,即 H__el___lo 變成 H_el_lo;
我們拿到這道題時,可能會想到用getchar()依次取字符,當遇到空格時,繼續下一個字符是否為空格,如果是則刪除,如果不是則繼續;那麼問題來了,如果空格後面還有空格呢?如果還有很多空格呢?如果還有其他要求呢?這樣很容易造成思維混亂,所以這時我們可以用到有限狀態機模型,好像這樣說很模糊啊,該怎麼使用呢?利用這種方式,最後的就是利用好flag,即標識符;這樣吧,我們來畫一下這個模型:

這樣看好像有點抽象,我來解釋一下:
狀態0 (flag = 1)若當前字符是空格,輸出並跳轉到狀態1(flag = 1),如果是非空格,則打印字符;
狀態1 (flag = 1) 若當前字符為非空格,則輸出並跳轉到狀態0,若是空格,則不打印;
下面幾個例題我盡量寫得清楚;
我們按照這種邏輯來寫程序,看看是不是比較方便,代碼如下:
[cpp] view
plain copy
#include <stdio.h>
int main(int argc, char *argv[])
{
char flag = 0;
int ch;
while((ch = getchar()) != EOF)
{
switch(flag)
{
case 0:
if(ch == ' ')
flag = 1;
putchar(ch);
break;
case 1:
if(ch == ' ')
continue;
flag = 0;
putchar(ch);
break;
default:
break;
}
}
return 0;
}
程序執行結果如下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/char1$ gcc -o test test.c
fs@ubuntu:~/qiang/char1$ ./test
H el lo
H el lo
效果很明顯;
上面的例題還算簡單吧,好像不用這個模型也可以是吧,那好,我們再來一題
例題2:除連續的空格但字符串中的連續空格不變,比如H_ _el__"wor___ld"___lo;
大家看看,如果直接寫程序是不是很煩,一會就亂掉了,那我們還用這個模型來編寫,還是先畫圖:

[cpp] view
plain copy
#include <stdio.h>
int main(int argc, char *argv[])
{
char flag = 0;
int ch;
while((ch = getchar()) != EOF){
switch(flag){
case 0:
if(ch == ' ')
flag = 1;
if(ch == '"')
flag = 2;
putchar(ch);
break;
case 1:
if(ch != ' '){
flag = 0;
if(ch == '"')
flag = 2;
putchar(ch);
}
break;
case 2:
if(ch == '"')
flag = 0;
if(ch == '\"')
ch = '"';
putchar(ch);
break;
default:
printf("error!\n");
break;
}
}
return 0;
}
執行結果如下:
[cpp] view
plain copy
fs@ubuntu:~/qiang/char1$ ./char3
H el "wor ld" lo
H el "wor ld" lo
來個實際點的問題:
例題3::除單行注釋
示例程序:
[cpp] view
plain copy
/*****This is a program!*****/
#include <stdio.h>
int main()
{
printf("Hello world!\n");//Hello world!
}
將這段程序中的單行注釋去掉,繼續畫圖:

編寫程序如下:
[cpp] view
plain copy
#include <stdio.h>
int main(void)
{
char flag = 0;
char ch;
while((ch = getchar()) != EOF)
{
switch(flag)
{
case 0:
if(ch == '/')
flag = 1;
else
putchar(ch);
break;
case 1:
if(ch == '/'){
flag = 2;
}
else{
putchar('/');
putchar(ch);
}
break;
case 2:
if(ch == '\n')
{
flag = 0;
putchar(ch);
}
break;
default:
break;
}
}
}
執行命令:
[cpp] view
plain copy
fs@ubuntu:~/qiang/char1$ ./quzhushi1 < test.c >result.c
注意命令中用到的重定向,將test.c文件重定向到quzhushi1 中,輸出結果重定向到 result.c中
可查看result.c中:
[cpp] view
plain copy
/*****This is a program!*****/
#include <stdio.h>
int main()
{
printf("Hello world!\n");
}
單行注釋被刪除。
例題4:去除單行注釋和多行注釋
還是這個測試程序:
[cpp] view
plain copy
/*****This is a program!*****/
#include <stdio.h>
int main()
{
printf("Hello world!\n");//Hello world!
}
好吧,繼續畫圖,圖上比較抽象,大家可以自己思考一下
這次比較復雜,要有5個標識符

測試代碼如下:
[cpp] view
plain copy
#include <stdio.h>
int main()
{
char ch;
int flag = 0;
while((ch = getchar()) != EOF)
{
switch(flag)
{
case 0:
if(ch == '/')
flag = 1;
else
putchar(ch);
break;
case 1:
if(ch == '/')
flag = 2;
else if(ch == '*')
flag = 3;
else
{
flag = 0;
putchar('/');
putchar(ch);
}
break;
case 2:
if(ch == '\n')
{
putchar(ch);
flag = 0;
}
break;
case 3:
if(ch == '*')
flag = 4;
break;
case 4:
if(ch == '/')
flag = 0;
else
flag = 3;
break;
}
}
}
執行命令:
[cpp] view
plain copy
fs@ubuntu:~/qiang/char1$ ./quzhushi < test.c >result.c
執行結果:
result.c
[cpp] view
plain copy
#include <stdio.h>
int main()
{
printf("Hello world!\n");
}
大家可以比較畫的圖與所寫程序,這種方法可以使我們編寫程序時有個很好的思路!
Copyright © Linux教程網 All Rights Reserved