# 練習11:While循環和布爾表達式
> 原文:[Exercise 11: While-Loop And Boolean Expressions](http://c.learncodethehardway.org/book/ex11.html)
> 譯者:[飛龍](https://github.com/wizardforcel)
你已經初步了解C是如何處理循環的,但是你可能不是很清楚布爾表達式`i < argc`是什么。在學習`while`循環之前,讓我先來對布爾表達式做一些解釋。
在C語言中,實際上沒有真正的“布爾”類型,而是用一個整數來代替,0代表`false`,其它值代表`true`。上一個練習中表達式`i < argc`實際上值為1或者0,并不像Python是顯式的`Ture`或者`False`。這是C語言更接近計算機工作方式的另一個例子,因為計算機只把值當成數字。
現在用`while`循環來實現和上一個練習相同的函數。這會讓你兩種循環,看看兩種循環是什么關系。
```c
#include <stdio.h>
int main(int argc, char *argv[])
{
// go through each string in argv
int i = 0;
while(i < argc) {
printf("arg %d: %s\n", i, argv[i]);
i++;
}
// let's make our own array of strings
char *states[] = {
"California", "Oregon",
"Washington", "Texas"
};
int num_states = 4;
i = 0; // watch for this
while(i < num_states) {
printf("state %d: %s\n", i, states[i]);
i++;
}
return 0;
}
```
你可以看到`while`循環的語法更加簡單:
```c
while(TEST) {
CODE;
}
```
只要`TEST`為`true`(非0),就會一直運行`CODE`中的代碼。這意味著如果要達到和`for`循環同樣的效果,我們需要自己寫初始化語句,以及自己來增加`i`。
## 你會看到什么
輸出基本相同,所以我做了一點修改,你可以看到它運行的另一種方式。
```sh
$ make ex11
cc -Wall -g ex11.c -o ex11
$ ./ex11
arg 0: ./ex11
state 0: California
state 1: Oregon
state 2: Washington
state 3: Texas
$
$ ./ex11 test it
arg 0: ./ex11
arg 1: test
arg 2: it
state 0: California
state 1: Oregon
state 2: Washington
state 3: Texas
$
```
## 如何使它崩潰
在你自己的代碼中,應有限選擇`for`循環而不是`while`循環,因為`for`循環不容易崩潰。下面是幾點普遍的原因:
+ 忘記初始化`int i`,使循環發生錯誤。
+ 忘記初始化第二個循環的`i`,于是`i`還保留著第一個循環結束時的值。你的第二個循環可能執行也可能不會執行。
+ 忘記在最后執行`i++`自增,你會得到一個“死循環”,它是在你開始編程的第一個或前兩個十年中,最可怕的問題之一。
## 附加題
+ 讓這些循環倒序執行,通過使用`i--`從`argc`開始遞減直到0。你可能需要做一些算數操作讓數組的下標正常工作。
+ 使用`while`循環將`argv`中的值復制到`states`。
+ 讓這個復制循環不會執行失敗,即使`argv`之中有很多元素也不會全部放進`states`。
+ 研究你是否真正復制了這些字符串。答案可能會讓你感到意外和困惑。
- 笨辦法學C 中文版
- 前言
- 導言:C的笛卡爾之夢
- 練習0:準備
- 練習1:啟用編譯器
- 練習2:用Make來代替Python
- 練習3:格式化輸出
- 練習4:Valgrind 介紹
- 練習5:一個C程序的結構
- 練習6:變量類型
- 練習7:更多變量和一些算術
- 練習8:大小和數組
- 練習9:數組和字符串
- 練習10:字符串數組和循環
- 練習11:While循環和布爾表達式
- 練習12:If,Else If,Else
- 練習13:Switch語句
- 練習14:編寫并使用函數
- 練習15:指針,可怕的指針
- 練習16:結構體和指向它們的指針
- 練習17:堆和棧的內存分配
- 練習18:函數指針
- 練習19:一個簡單的對象系統
- 練習20:Zed的強大的調試宏
- 練習21:高級數據類型和控制結構
- 練習22:棧、作用域和全局
- 練習23:認識達夫設備
- 練習24:輸入輸出和文件
- 練習25:變參函數
- 練習26:編寫第一個真正的程序
- 練習27:創造性和防御性編程
- 練習28:Makefile 進階
- 練習29:庫和鏈接
- 練習30:自動化測試
- 練習31:代碼調試
- 練習32:雙向鏈表
- 練習33:鏈表算法
- 練習34:動態數組
- 練習35:排序和搜索
- 練習36:更安全的字符串
- 練習37:哈希表
- 練習38:哈希算法
- 練習39:字符串算法
- 練習40:二叉搜索樹
- 練習41:將 Cachegrind 和 Callgrind 用于性能調優
- 練習42:棧和隊列
- 練習43:一個簡單的統計引擎
- 練習44:環形緩沖區
- 練習45:一個簡單的TCP/IP客戶端
- 練習46:三叉搜索樹
- 練習47:一個快速的URL路由
- 后記:“解構 K&R C” 已死