# 練習3:格式化輸出
> 原文:[Exercise 3: Formatted Printing](http://c.learncodethehardway.org/book/ex3.html)
> 譯者:[飛龍](https://github.com/wizardforcel)
不要刪除Makefile,因為它可以幫你指出錯誤,以及當我們需要自動化處理一些事情時,可以向它添加新的東西。
許多編程語言都使用了C風格的格式化輸出,所以讓我們嘗試一下:
```c
#include <stdio.h>
int main()
{
int age = 10;
int height = 72;
printf("I am %d years old.\n", age);
printf("I am %d inches tall.\n", height);
return 0;
}
```
寫完之后,執行通常的`make ex3`命令來構建并運行它。一定要確保你處理了所有的警告。
這個練習的代碼量很小,但是信息量很大,所以讓我們逐行分析一下:
+ 首先你包含了另一個頭文件叫做`stdio.h`。這告訴了編譯器你要使用“標準的輸入/輸出函數”。它們之一就是`printf`。
+ 然后你使用了一個叫`age`的變量并且將它設置為10。
+ 接著你使用了一個叫`height`的變量并且設置為72。
+ 再然后你使用`printf`函數來打印這個星球上最高的十歲的人的年齡和高度。
+ 在`printf`中你會注意到你傳入了一個字符串,這就是格式字符串,和其它語言中一樣。
+ 在格式字符串之后,你傳入了一些變量,它們應該被`printf`“替換”進格式字符串中。
這些語句的結果就是你用`printf`處理了一些變量,并且它會構造出一個新的字符串,之后將它打印在終端上。
## 你會看到什么
當你做完上面的整個步驟,你應該看到這些東西:
```shell
$ make ex3
cc -Wall -g ex3.c -o ex3
$ ./ex3
I am 10 years old.
I am 72 inches tall.
$
```
不久之后我會停下來讓你運行`make`,并且告訴你構建過程是什么樣子的。所以請確保你正確得到了這些信息并且能正常執行。
## 外部研究
在附加題一節我可能會讓你自己查找一些資料,并且弄明白它們。這對于一個自我學習的程序員來說相當重要。如果你一直在自己嘗試了解問題之前去問其它人,你永遠都不會學到獨立解決問題。這會讓你永遠都不會在自己的技能上建立信心,并且總是依賴別人去完成你的工作。
打破你這一習慣的方法就是強迫你自己先試著自己回答問題,并且確認你的回答是正確的。你可以通過打破一些事情,用實驗驗證可能的答案,以及自己進行研究來完成它。
對于這個練習,我想讓你上網搜索`printf`的所有格式化占位符和轉義序列。轉義序列類似`\n`或者`\r`,可以讓你分別打印新的一行或者 tab 。格式化占位符類似`%s`或者`%d`,可以讓你打印字符串或整數。找到所有的這些東西,以及如何修改它們,和可設置的“精度”和寬度的種類。
從現在開始,這些任務會放到附加題里面,你應該去完成它們。
## 如何使它崩潰
嘗試下面的一些東西來使你的程序崩潰,在你的電腦上它們可能會崩潰,也可能不會。
+ 從第一個`printf`中去掉`age`并重新編譯,你應該會得到一大串的警告。
+ 運行新的程序,它會崩潰,或者打印出奇怪的年齡。
+ 將`printf`恢復原樣,并且去掉`age`的初值,將那一行改為`int age;`,之后重新構建并運行。
```shell
# edit ex3.c to break printf
$ make ex3
cc -Wall -g ex3.c -o ex3
ex3.c: In function 'main':
ex3.c:8: warning: too few arguments for format
ex3.c:5: warning: unused variable 'age'
$ ./ex3
I am -919092456 years old.
I am 72 inches tall.
# edit ex3.c again to fix printf, but don't init age
$ make ex3
cc -Wall -g ex3.c -o ex3
ex3.c: In function 'main':
ex3.c:8: warning: 'age' is used uninitialized in this function
$ ./ex3
I am 0 years old.
I am 72 inches tall.
$
```
## 附加題
+ 找到盡可能多的方法使`ex3`崩潰。
+ 執行`man 3 printf`來閱讀其它可用的'%'格式化占位符。如果你在其它語言中使用過它們,應該看著非常熟悉(它們來源于`printf`)。
+ 將`ex3`添加到你的`Makefile`的`all`列表中。到目前為止,可以使用`make clean all`來構建你所有的練習。
+ 將`ex3`添加到你的`Makefile`的`clean`列表中。當你需要的時候使用`make clean`可以刪除它。
- 笨辦法學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” 已死