Linux_C編之(3)語句

(三)語句

從程序流程的角度來看,程序可以分爲三種基本結構,即順序結構、分支結構和循環結構,這三種基本結構可以組成所有的各種複雜程序。C語言提供了多種語句來實現這些結構,例如,通過if、switch、for、while、continue、break、return語句來實現,用來控制程序的執行。不同的控制語句有各自的規則,在不同的情況下要選擇最合適的語句來進行流程控制。

1、空語句

只有分號“;” 組成的語句稱爲空語句。空語句是什麼也不執行的語句。在程序中空語句可用作空循環體。例如:

while(getchar() != '\n');

本條語句的功能是,只要從鍵盤輸入的字符不是回車則重新輸入,這裏的循環體爲空語句,空語句一般有以下的幾個用途:
(1)純粹消耗CPU時間,起到延時的作用;
(2)爲了程序的結構清楚,可讀性好,以後擴充新功能方便。
例如:

if(xxx)
{
	xxxx
}

但是企業編碼規範要求

if(xxx)
{
	xxxx
}
else
{
	;
}

對於某些大型的軟件項目,特別是一些嵌入式項目,處於自動化測試的需要,要求必須進行語句的配對。
在進行代碼靜態解析,單體測試case抽出的時候,爲了保證全路徑覆蓋,很多專業的高端自動測試工具,會建議進行語句配對,此時對於一些不完備的分支,就會用空語句補全。

2、基礎語句

(1)表達式語句
表達式語句由表達式加上分號“;”組成,其一般形式爲

表達式;

執行表達式語句就是計算表達式的值。例如:

x = y + z; a = 520; //賦值語句
y + z;				//加法運算語句,但是計算結果不能保留,無實際意義
i ++; 				//自增語句,i值自增1

(2)函數調用語句
由函數名,實際參數加上分號“;”組成,其一般形式爲
函數名(實際參數值);

3、語句if

目前我們寫的簡單函數中可以有多條語句,但是這些語句總是從前到後順序執行的,除了順序執行外,有時候我們需要檢查一個條件,然後根據檢查的結果執行不同的後續代碼。在C語言中可以用分支語句(Selection Statement)實現。例如:

if (x != 0)
{
	printf("X is nonzero.\n");
}

其中,“x!=0”表示x不等於0的條件,這個表達式稱爲控制表達式,如果條件成立,則執行{}中的語句,否則不執行{}中的語句,直接跳到{}後面,if和控制表達式改變了程序的控制流程,不再按照從前向後順序執行,而是根據不同的條件執行不同的語句,這種控制流程稱爲分支。
(1)布爾變量與零值比較
不可將布爾變量直接與TRUE、FALSE或者0、1進行比較
根據布爾類型的語義,零值爲“假”,記作(FALSE),任何非零值都是“真”,記作(TRUE)。
假設布爾變量名字爲flag,它與零值比較的標準if語句爲

if(flag)  //表示flag爲真
if(!flag)  //表示flag爲假

其他的用法都屬於不良風格

if(flag == TRUE)
if(flag == 1)
if(flag == FALSE)
if(flag == 0)

(2)整型變量與零值比較
應當將整型變量用“==”或者“!=”直接與0比較
假設整型變量的名字爲value,它與零值比較的標準if語句爲

if( 0 == value)
if(0 != value)

不能布爾類型一樣。
(3)浮點變量與零值比較
不可將浮點變量用“==”或者“!=”和任何數字進行比較
千萬要留意、無論是float還是double類型的變量,都有精度限制,所以一定要避免將浮點變量用" == "或者“!=”與數字進行比較,應該設法轉換爲“>=”或者“<=”形式。
假設浮點變量的名字爲x,應當將

if ( 0.0 == x) //隱含錯誤的比較

轉化爲


#define EPSINON 0.000001
if ((x>=-EPSINON)&&(x<=EPSINON))

其中,EPSINON是允許的誤差(即精度)
(ps:EPSINON是一個宏,它的值可以改成你想要的精度,通過這種方式也可以進行其他任何值的精度比較。)
(pps:由於浮點型變量的存儲機制最好不要進行很大的浮點數與很小的浮點數之間進行運算,比如11111111111.000+0.00000000000001這個運算結果可能會很奇葩!)

(4)指針變量與零值比較
應當將指針變量用“==”或“!=”與NULL比較。
指針變量的零值是“空”(記作NULL)。儘管NULL的值與0相同,但是兩者意義不同,假設指針變量的名字是p,它與零值比較的標準if爲

if (p  == NULL)  //p與NULL顯式比較,強調p是指針變量
if ( p != NULL)   

不要寫成

if(p == 0) // 容易讓人誤解爲p是整型變量
if(p != 0)

或者

if(p)  //容易讓人誤會p是布爾變量
if(!p)

(5)對if語句的補充說明
有時候我們可能看見"if(NULL == p)"這樣的格式,這樣是爲了程序員不小心寫漏了一個等號,變成賦值語句,這樣程序不會報語法錯誤,而是邏輯錯誤,左右倒一下,就給常量賦值,這樣在C語言中是不允許的,就會報語法錯誤。

4、跳轉語句:goto

goto語句是一種無條件轉移語句,與BASIC中的goto語句相似。goto語句的使用格式爲:

goto 語句標號;

其中標號是一個有效的標識符,這個標識符加上一個“:”一起出現在函數內某行,執行goto語句後,程序將跳轉到該標號處並執行後面的語句。另外標號必須和goto語句同處於一個函數中,但可以不在一個循環層中。通常goto語句與if條件連用,當滿足某一條件時,程序跳到標號處運行。
但是goto一直一來都有爭議,由於goto語句可以靈活跳轉,如果不加限制,它的確會破壞結構化設計風格,goto也經常帶來錯誤或者隱患。
使用goto時要慎重!

5、循環語句

循環結構是程序中一種很重要的結構。其特點是:在給定條件成立時,反覆執行某程序段,直到條件不成立爲止。給定的條件稱爲循環條件,反覆執行的程序段稱爲循環體。C語言提供了很多循環語句,可以組成各種不同形式的循環結構:

  • 用goto語句和if語句構成循環;
  • 用while語句;
  • 用do-while語句;
  • 用for語句;

while語句的一般形式爲

while(表達式) 語句

其中表達式是循環條件,語句爲循環體。
while語句的語義是:計算表達式的值,當值爲真時,執行循環體語句。

do-while語句的一般形式爲

do
	語句
while(表達式);

這個循環與while循環的不同在於:它先執行循環體中的與,然後判斷表達式是否爲真,如果爲真則繼續循環,如果爲假終止循環,因此,do-while循環至少要執行一次循環語句。

for語句的一般形式爲

for(表達式1;表達式2;表達式3)語句

它的執行過程如下:
(1)先求解表達式1。
(2)求解表達式2,若其值爲真,則執行for語句中指定的內嵌語句,然後執行下面第(3)步;若其值爲假,則結束循環,直接轉到第(5)步。
(3)求解表達式3。
(4)轉回上面第(2)步繼續執行。
(5)循環結束,執行for語句下面的一個語句。
注意:
(1)for循環中的“表達式1(循環變量賦初值)”、“表達式2(循環條件)”和“表達式3(循環變量遞增)”都是選擇項,即可以默認,但“;”不能默認。
(2)省略了“表達式1(循環變量賦初值)”,表示不對循環控制變量賦值。
(3)省略了“表達式2(循環條件)”,則不作其他處理時變成死循環。例如:

for(i = 1;;i++)
{
	sum = sum + i;
}

相當於

i = 1;
while1{
	sum = sum + i;
	i++;
}

(4)省略了“表達式3(循環變量遞增)”,則不對循環變量進行控制,這時候可以在循環體中修改控制變量,例如:

for(i = 1;i<10;)
{
	sum = sum + i;
	i++;
}

(5)省略了“表達式1和表達式3”。例如:

for(;i<=100;)
{
	sum = sum + i;
	i++;
}

(6)3個表達式全部省略:
例如:

for(;;)

分號不能省略
相當於

while(1)

(7)表達式1可以是循環變量的初值賦值,也可以是其他表達式:

for(sum = 0;i<10;i++)
{
	sum = sum +i ;
}

(8)表達式1和表達式3可以是一個簡單的表達式也可以是逗號表達式:
for(sum = 0,i = 1;i<100;i++)
{
sum = sum + i;
}
或者
for(i = 0,j = 100;i<100;i++,j–)
{
k = i+j;
}
(9)表達式2一般是關係表達式或者邏輯表達式,但也可以是數值表達式或字符表達式,只要其值非零,就執行循環體。

for(i = 0;(c= getchar())! = '\n';i+=c);

又如:

for(;(c = getchar())!='\n';)
{
	printf("%c",c);
}

循環語句的效率

C語言循環語句中,for語句使用頻率最高,while語句其次,do語句很少用,本節重點講循環體的效率,通過循環體效率的基本方法是降低循環體的複雜性。
在多重循環中,應該將最長的循環放在最內層中,最短的循環體放在最外層中,以減少CPU跨切循環層的次數。

6、break和continue

1、break語句
break語句通常在循環語句和開關語句中,當break用於開關語句switch時,可使程序跳出switch而執行switch以後的語句;如果沒有break語句,則成爲一個死循環而無法退出。
當break語句用於do-while、for、while循環語句時,可使得程序終止循環而執行循環後的的語句,通常break語句總是與if語句聯繫在一起,即滿足條件時便可以跳出循環。
注意:

  • break語句對if-else 的條件語句不起作用;
  • 在多層循環中,一個break語句只向外跳一層。
    2、continue語句
    continue語句的作用是跳過循環體中剩餘的語句而強行執行下一次循環。continue語句只用在for、while、do-while等循環體中,當與if條件語句一起使用,用來加速循環。

7、switch語句

switch語句是多分支選擇語句,而if語句只有兩個分支可以選擇,雖然if可以嵌套,但是那樣的程序比較冗長。
switch的格式爲:

switch (value)
{
	case 1:
	{
		break;
	}
	case 2:
	{
		break;
	}
	default:
	{	
		break;
	}
}

(1)每個case語句的結尾不要忘記加break,不然會繼續執行下一個case;
(2)不要忘記加default分支。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章