鍍金池/ 教程/ C/ 練習10:字符串數(shù)組和循環(huán)
練習9:數(shù)組和字符串
練習6:變量類型
練習3:格式化輸出
練習4:Valgrind 介紹
練習28:Makefile 進階
練習14:編寫并使用函數(shù)
練習21:高級數(shù)據(jù)類型和控制結構
練習20:Zed的強大的調(diào)試宏
練習18:函數(shù)指針
練習0:準備
練習15:指針,可怕的指針
練習27:創(chuàng)造性和防御性編程
練習22:棧、作用域和全局
練習10:字符串數(shù)組和循環(huán)
練習8:大小和數(shù)組
練習16:結構體和指向它們的指針
練習7:更多變量和一些算術
練習23:認識達夫設備
練習12:If,Else If,Else
練習2:用Make來代替Python
練習1:啟用編譯器
練習11:While循環(huán)和布爾表達式
練習5:一個C程序的結構
練習24:輸入輸出和文件
練習25:變參函數(shù)
練習13:Switch語句
練習19:一個簡單的對象系統(tǒng)
練習26:編寫第一個真正的程序
導言:C的笛卡爾之夢
練習17:堆和棧的內(nèi)存分配

練習10:字符串數(shù)組和循環(huán)

你現(xiàn)在可以創(chuàng)建不同類型的數(shù)組,并且也知道了“字符串”和“字節(jié)數(shù)組”是相同的東西。接下來,我們要更進一步,創(chuàng)建一個包含字符串的數(shù)組。我也會介紹第一個循環(huán)結構,for循環(huán)來幫我們打印出這一新的數(shù)據(jù)結構。

這一章的有趣之處就是你的程序中已經(jīng)有一個現(xiàn)成的字符串數(shù)組,main函數(shù)參數(shù)中的char *argv[]。下面這段代碼打印出了所有你傳入的命令行參數(shù):

include <stdio.h>

int main(int argc, char *argv[])
{
    int i = 0;

    // go through each string in argv
    // why am I skipping argv[0]?
    for(i = 1; i < argc; i++) {
        printf("arg %d: %s\n", i, argv[i]);
    }

    // let's make our own array of strings
    char *states[] = {
        "California", "Oregon",
        "Washington", "Texas"
    };
    int num_states = 4;

    for(i = 0; i < num_states; i++) {
        printf("state %d: %s\n", i, states[i]);
    }

    return 0;
}

for循環(huán)的格式是這樣的:

for(INITIALIZER; TEST; INCREMENTER) {
    CODE;
}

下面是for循環(huán)的工作機制:

  • INITIALIZER中是用來初始化循環(huán)的代碼,這個例子中它是i = 0
  • 接下來會檢查TEST布爾表達式,如果為false(0)則跳過CODE,不做任何事情。
  • 執(zhí)行CODE,做它要做的任何事情。
  • CODE執(zhí)行之后會執(zhí)行INCREMENTER部分,通常情況會增加一些東西,比如這個例子是i++。
  • 然后跳到第二步繼續(xù)執(zhí)行,直到TESTfalse(0)為止。

例子中的for循環(huán)使用argcargv,遍歷了命令行參數(shù),像這樣:

  • OS將每個命令行參數(shù)作為字符串傳入argv數(shù)組,程序名稱./ex10在下標為0的位置,剩余的參數(shù)緊隨其后。
  • OS將argc置為argv數(shù)組中參數(shù)的數(shù)量,所以你可以遍歷它們而不會越界。要記住如果你提供了一個參數(shù),程序名稱是第一個,參數(shù)應該在第二個。
  • 接下來程序使用i < argc測試i是否使用argc,由于最開始1 < 2,測試通過。
  • 之后它會執(zhí)行代碼,輸出i,并且將i用做argv的下標。
  • 然后使用i++來運行自增語句,它是i = i + 1的便捷形式。
  • 程序一直重復上面的步驟,直到i < argc值為false(0),這時退出循環(huán)但程序仍然繼續(xù)執(zhí)行。

你會看到什么

你需要用兩種方法運行它來玩轉這個程序。第一種方法是向命令行參數(shù)傳遞一些東西來設置argcargv。第二種是不傳入任何參數(shù),于是你可以看到第一次的for循環(huán)沒有被執(zhí)行,由于i < argc值為false。

理解字符串數(shù)組

你應該可以從這個練習中弄明白,你在C語言中通過混合char *str = "blah"char str[] = {'b','l','a','h'}語法構建二維數(shù)組來構建字符串數(shù)組。第十四行的char *states[] = {...}語法就是這樣的二維混合結構,其中每個字符串都是數(shù)組的一個元素,字符串的每個字符又是字符串的一個元素。

感到困惑嗎?多維的概念是很多人從來都不會去想的,所以你應該在紙上構建這一字符串數(shù)組:

  • 在紙的左邊為每個字符串畫一個小方格,帶有它們的下標。
  • 然后在方格上方寫上每個字符的下標。
  • 接著將字符串中的字符填充到方格內(nèi)。
  • 畫完之后,在紙上模擬代碼的執(zhí)行過程。

理解它的另一種方法是在你熟悉的語言,比如Python或Ruby中構建相同的結構。

如何使它崩潰

  • 使用你喜歡的另一種語言,來寫這個程序。傳入盡可能多的命令行參數(shù),看看是否能通過傳入過多參數(shù)使其崩潰。
  • i初始化為0看看會發(fā)生什么。是否也需要改動argc,不改動的話它能正常工作嗎?為什么下標從0開始可以正常工作?
  • num_states改為錯誤的值使它變大,來看看會發(fā)生什么。

附加題

  • 弄清楚在for循環(huán)的每一部分你都可以放置什么樣的代碼。
  • 查詢?nèi)绾问褂?code>','(逗號)字符來在for循環(huán)的每一部分中,';'(分號)之間分隔多條語句。
  • 查詢NULL是什么東西,嘗試將它用做states的一個元素,看看它會打印出什么。
  • 看看你是否能在打印之前將states的一個元素賦值給argv中的元素,再試試相反的操作。