Skip to content

Commit 63082c0

Browse files
committed
Add syntax highlight for all files
- c for C language - makefile for Makefile - sh for shell script - r for R language
1 parent d8a63ea commit 63082c0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+227
-230
lines changed

ex1.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
这是你用C写的第一个简单的程序:
88

9-
```
9+
```c
1010
int main(int argc, char *argv[])
1111
{
1212
puts("Hello world.");
@@ -17,7 +17,7 @@ int main(int argc, char *argv[])
1717
1818
把它写进 `ex1.c` 并输入:
1919
20-
```
20+
```sh
2121
$ make ex1
2222
cc ex1.c -o ex1
2323
```
@@ -28,7 +28,7 @@ cc ex1.c -o ex1
2828

2929
现在你可以运行程序并看到输出。
3030

31-
```
31+
```c
3232
$ ./ex1
3333
Hello world.
3434
```
@@ -41,7 +41,7 @@ Hello world.
4141

4242
对于这个程序,打开所有编译警告重新构建它:
4343

44-
```
44+
```sh
4545
$ rm ex1
4646
$ CFLAGS="-Wall" make ex1
4747
cc -Wall ex1.c -o ex1
@@ -54,7 +54,7 @@ $
5454

5555
现在你会得到一个警告,说`puts`函数是隐式声明的。C语言的编译器很智能,它能够理解你想要什么。但是如果可以的话,你应该去除所有编译器警告。把下面一行添加到`ex1.c`文件的最上面,之后重新编译来去除它:
5656

57-
```
57+
```c
5858
#include <stdio.h>
5959
```
6060

@@ -64,4 +64,4 @@ $
6464

6565
+ 在你的文本编辑器中打开`ex1`文件,随机修改或删除一部分,之后运行它看看发生了什么。
6666
+ 再多打印5行文本或者其它比`"Hello world."`更复杂的东西。
67-
+ 执行`man 3 puts`来阅读这个函数和其它函数的文档。
67+
+ 执行`man 3 puts`来阅读这个函数和其它函数的文档。

ex10.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
这一章的有趣之处就是你的程序中已经有一个现成的字符串数组,`main`函数参数中的`char *argv[]`。下面这段代码打印出了所有你传入的命令行参数:
1010

11-
```
11+
```c
1212
include <stdio.h>
1313

1414
int main(int argc, char *argv[])
@@ -38,7 +38,7 @@ int main(int argc, char *argv[])
3838
3939
`for`循环的格式是这样的:
4040
41-
```
41+
```c
4242
for(INITIALIZER; TEST; INCREMENTER) {
4343
CODE;
4444
}
@@ -90,4 +90,4 @@ for(INITIALIZER; TEST; INCREMENTER) {
9090
+ 弄清楚在`for`循环的每一部分你都可以放置什么样的代码。
9191
+ 查询如何使用`','`(逗号)字符来在`for`循环的每一部分中,`';'`(分号)之间分隔多条语句。
9292
+ 查询`NULL`是什么东西,尝试将它用做`states`的一个元素,看看它会打印出什么。
93-
+ 看看你是否能在打印之前将`states`的一个元素赋值给`argv`中的元素,再试试相反的操作。
93+
+ 看看你是否能在打印之前将`states`的一个元素赋值给`argv`中的元素,再试试相反的操作。

ex11.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
现在用`while`循环来实现和上一个练习相同的函数。这会让你两种循环,看看两种循环是什么关系。
1212

13-
```
13+
```c
1414
#include <stdio.h>
1515

1616
int main(int argc, char *argv[])
@@ -42,7 +42,7 @@ int main(int argc, char *argv[])
4242
4343
你可以看到`while`循环的语法更加简单:
4444
45-
```
45+
```c
4646
while(TEST) {
4747
CODE;
4848
}
@@ -54,7 +54,7 @@ while(TEST) {
5454

5555
输出基本相同,所以我做了一点修改,你可以看到它运行的另一种方式。
5656

57-
```
57+
```sh
5858
$ make ex11
5959
cc -Wall -g ex11.c -o ex11
6060
$ ./ex11
@@ -88,4 +88,4 @@ $
8888
+ 让这些循环倒序执行,通过使用`i--``argc`开始递减直到0。你可能需要做一些算数操作让数组的下标正常工作。
8989
+ 使用`while`循环将`argv`中的值复制到`states`
9090
+ 让这个复制循环不会执行失败,即使`argv`之中有很多元素也不会全部放进`states`
91-
+ 研究你是否真正复制了这些字符串。答案可能会让你感到意外和困惑。
91+
+ 研究你是否真正复制了这些字符串。答案可能会让你感到意外和困惑。

ex12.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
`if`语句是每个编程语言中共有的特性,包括C语言。下面是一段代码,使用了`if`语句来确保只传入了一个或两个命令行参数:
88

9-
```
9+
```c
1010
#include <stdio.h>
1111

1212
int main(int argc, char *argv[])
@@ -32,7 +32,7 @@ int main(int argc, char *argv[])
3232
3333
`if`语句的格式为:
3434
35-
```
35+
```c
3636
if(TEST) {
3737
CODE;
3838
} else if(TEST) {
@@ -54,17 +54,17 @@ if(TEST) {
5454

5555
这段代码非常易于运行和尝试:
5656

57-
```
57+
```sh
5858
$ make ex12
5959
cc -Wall -g ex12.c -o ex12
6060
$ ./ex12
6161
You only have one argument. You suck.
6262
$ ./ex12 one
6363
Here's your arguments:
64-
./ex12 one
64+
./ex12 one
6565
$ ./ex12 one two
6666
Here's your arguments:
67-
./ex12 one two
67+
./ex12 one two
6868
$ ./ex12 one two three
6969
You have too many arguments. You suck.
7070
$
@@ -82,4 +82,4 @@ $
8282
+ 我已经向你简短地介绍了`&&`,它执行“与”操作。上网搜索与之不同的“布尔运算符”。
8383
+ 为这个程序编写更多的测试用例,看看你会写出什么。
8484
+ 回到练习10和11,使用`if`语句使循环提前退出。你需要`break`语句来实现它,搜索它的有关资料。
85-
+ 第一个判断所输出的话真的正确吗?由于你的“第一个参数”不是用户输入的第一个参数,把它改正。
85+
+ 第一个判断所输出的话真的正确吗?由于你的“第一个参数”不是用户输入的第一个参数,把它改正。

ex13.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
C中的`switch`语句与它们不同,实际上是一个“跳转表”。你只能够放置结果为整数的表达式,而不是一些随机的布尔表达式,这些整数用于计算从`swicth`顶部到匹配部分的跳转。下面有一段代码,我要分解它来让你理解“跳转表”的概念:
1010

11-
```
11+
```c
1212
#include <stdio.h>
1313

1414
int main(int argc, char *argv[])
@@ -89,7 +89,7 @@ int main(int argc, char *argv[])
8989
9090
下面是我运行它的一个例子,也演示了传入命令行参数的不同方法:
9191
92-
```
92+
```sh
9393
$ make ex13
9494
cc -Wall -g ex13.c -o ex13
9595
$ ./ex13
@@ -134,4 +134,4 @@ $
134134
+ 使用`','`(逗号)在`for`循环中初始化`letter`
135135
+ 使用另一个`for`循环来让它处理你传入的所有命令行参数。
136136
+ 将这个`switch`语句转为`if`语句,你更喜欢哪个呢?
137-
+ 在“Y”的例子中,我在`if`代码块外面写了个`break`。这样会产生什么效果?如果把它移进`if`代码块,会发生什么?自己试着解答它,并证明你是正确的。
137+
+ 在“Y”的例子中,我在`if`代码块外面写了个`break`。这样会产生什么效果?如果把它移进`if`代码块,会发生什么?自己试着解答它,并证明你是正确的。

ex14.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
到现在为止,你只使用了作为`stdio.h`头文件一部分的函数。在这个练习中你将要编写并使用自己的函数。
99

10-
```
10+
```c
1111
#include <stdio.h>
1212
#include <ctype.h>
1313

@@ -80,23 +80,23 @@ ex14.c:38-42
8080
8181
向这个程序传入不同的命令行参数来玩转它,这样会遍历你函数中的所有路径。这里演示了我和它的交互:
8282
83-
```
83+
```sh
8484
$ make ex14
8585
cc -Wall -g ex14.c -o ex14
8686
8787
$ ./ex14
88-
'e' == 101 'x' == 120
88+
'e' == 101 'x' == 120
8989
9090
$ ./ex14 hi this is cool
91-
'e' == 101 'x' == 120
92-
'h' == 104 'i' == 105
93-
't' == 116 'h' == 104 'i' == 105 's' == 115
94-
'i' == 105 's' == 115
95-
'c' == 99 'o' == 111 'o' == 111 'l' == 108
91+
'e' == 101 'x' == 120
92+
'h' == 104 'i' == 105
93+
't' == 116 'h' == 104 'i' == 105 's' == 115
94+
'i' == 105 's' == 115
95+
'c' == 99 'o' == 111 'o' == 111 'l' == 108
9696
9797
$ ./ex14 "I go 3 spaces"
98-
'e' == 101 'x' == 120
99-
'I' == 73 ' ' == 32 'g' == 103 'o' == 111 ' ' == 32 ' ' == 32 's' == 115 'p' == 112 'a' == 97 'c' == 99 'e' == 101 's' == 115
98+
'e' == 101 'x' == 120
99+
'I' == 73 ' ' == 32 'g' == 103 'o' == 111 ' ' == 32 ' ' == 32 's' == 115 'p' == 112 'a' == 97 'c' == 99 'e' == 101 's' == 115
100100
$
101101
```
102102

@@ -114,4 +114,4 @@ $
114114
+ 重新编写这些函数,使它们的数量减少。比如,你真的需要`can_print_it`吗?
115115
+ 使用`strlen`函数,让`print_arguments`知道每个字符串参数都有多长,之后将长度传入`print_letters`。然后重写`print_letters`,让它只处理固定的长度,不按照`'\0'`终止符。你需要`#include <string.h>`来实现它。
116116
+ 使用`man`来查询`isalpha``isblank`的信息。使用其它相似的函数来只打印出数字或者其它字符。
117-
+ 上网浏览不同的人喜欢什么样的函数格式。永远不要使用“K&R”语法,因为它过时了,而且容易使人混乱,但是当你碰到一些人使用这种格式时,要理解代码做了什么。
117+
+ 上网浏览不同的人喜欢什么样的函数格式。永远不要使用“K&R”语法,因为它过时了,而且容易使人混乱,但是当你碰到一些人使用这种格式时,要理解代码做了什么。

ex15.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
要想以一种我们可以谈论的方式来讲解指针,我会编写一个无意义的程序,它以三种方式打印了一组人的年龄:
1010

11-
```
11+
```c
1212
#include <stdio.h>
1313

1414
int main(int argc, char *argv[])
@@ -121,7 +121,7 @@ ex15.c:48-49
121121
122122
在你运行这个程序之后,尝试根据打印出的每一行追溯到代码中产生它们的那一行。在必要情况下,修改`printf`调用来确认你得到了正确的行号:
123123
124-
```
124+
```shell
125125
$ make ex15
126126
cc -Wall -g ex15.c -o ex15
127127
$ ./ex15
@@ -238,4 +238,4 @@ $
238238
+ 将获取值和获取地址组合到一起。
239239
+ 在程序末尾添加一个`for`循环,打印出这些指针所指向的地址。你需要在`printf`中使用`%p`
240240
+ 对于每一种打印数组的方法,使用函数来重写程序。试着向函数传递指针来处理数据。记住你可以声明接受指针的函数,但是可以像数组那样用它。
241-
+`for`循环改为`while`循环,并且观察对于每种指针用法哪种循环更方便。
241+
+`for`循环改为`while`循环,并且观察对于每种指针用法哪种循环更方便。

ex16.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
像往常一样,下面是我们将要讨论的程序,你应该把它打下来并且使它正常工作:
1010

11-
```
11+
```c
1212
#include <stdio.h>
1313
#include <assert.h>
1414
#include <stdlib.h>
@@ -137,7 +137,7 @@ int main(int argc, char *argv[])
137137
138138
在你使用描述性注释扩展程序之后,要确保它实际上能够运行,并且产生下面的输出:
139139
140-
```
140+
```sh
141141
$ make ex16
142142
cc -Wall -g ex16.c -o ex16
143143

ex17.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
像通常一样,输入下面整个程序,并且使之正常工作,之后我们会进行讨论:
1010

11-
```
11+
```c
1212
#include <stdio.h>
1313
#include <assert.h>
1414
#include <stdlib.h>
@@ -262,7 +262,7 @@ int main(int argc, char *argv[])
262262
263263
你应该为此花费大量时间,知道你可以测试它能正常工作了。并且你应当用`Valgrind`来确保你在所有地方都正确使用内存。下面是我的测试记录,并且随后使用了`Valgrind`来检查操作:
264264
265-
```
265+
```sh
266266
$ make ex17
267267
cc -Wall -g ex17.c -o ex17
268268
$ ./ex17 db.dat c
@@ -334,4 +334,4 @@ $
334334
+ 编写一个shell脚本来通过以正确顺序运行命令执行自动化测试。提示:在`bash`顶端使用使用`set -e`,使之在任何命令发生错误时退出。
335335
> 译者注:使用Python编写多行脚本或许更方便一些。
336336
+ 尝试重构程序,使用单一的全局变量来储存数据库连接。这个新版本和旧版本比起来如何?
337-
+ 搜索“栈数据结构”,并且在你最喜欢的语言中实现它,然后尝试在C中实现。
337+
+ 搜索“栈数据结构”,并且在你最喜欢的语言中实现它,然后尝试在C中实现。

ex18.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
函数指针的格式类似这样:
1010

11-
```
11+
```c
1212
int (*POINTER_NAME)(int a, int b)
1313
```
1414

@@ -20,7 +20,7 @@ int (*POINTER_NAME)(int a, int b)
2020

2121
这个方法的关键是,当你完成这些之后,指针的变量名称为`compare_cb`,而你可以将它用作函数。这类似于指向数组的指针可以表示所指向的数组。指向函数的指针也可以用作表示所指向的函数,只不过是不同的名字。
2222

23-
```
23+
```c
2424
int (*tester)(int a, int b) = sorted_order;
2525
printf("TEST: %d is same as %d\n", tester(2, 3), sorted_order(2, 3));
2626
```
@@ -33,7 +33,7 @@ printf("TEST: %d is same as %d\n", tester(2, 3), sorted_order(2, 3));
3333
3434
需要解决的下一个问题是使用函数指针向其它函数提供参数比较困难,比如当你打算向其它函数传递回调函数的时候。解决方法是使用`typedef`,它是C的一个关键字,可以给其它更复杂的类型起个新的名字。你需要记住的事情是,将`typedef`添加到相同的指针语法之前,然后你就可以将那个名字用作类型了。我使用下面的代码来演示这一特性:
3535
36-
```
36+
```c
3737
#include <stdio.h>
3838
#include <stdlib.h>
3939
#include <errno.h>
@@ -56,8 +56,8 @@ void die(const char *message)
5656
typedef int (*compare_cb)(int a, int b);
5757
5858
/**
59-
* A classic bubble sort function that uses the
60-
* compare_cb to do the sorting.
59+
* A classic bubble sort function that uses the
60+
* compare_cb to do the sorting.
6161
*/
6262
int *bubble_sort(int *numbers, int count, compare_cb cmp)
6363
{
@@ -102,7 +102,7 @@ int strange_order(int a, int b)
102102
}
103103
}
104104
105-
/**
105+
/**
106106
* Used to test that we are sorting things correctly
107107
* by doing the sort and printing it out.
108108
*/
@@ -217,21 +217,21 @@ ex18.c:109
217217

218218
运行这个程序非常简单,但是你要尝试不同的数字组合,甚至要尝试输入非数字来看看它做了什么:
219219

220-
```
220+
```sh
221221
$ make ex18
222222
cc -Wall -g ex18.c -o ex18
223223
$ ./ex18 4 1 7 3 2 0 8
224-
0 1 2 3 4 7 8
225-
8 7 4 3 2 1 0
226-
3 4 2 7 1 0 8
224+
0 1 2 3 4 7 8
225+
8 7 4 3 2 1 0
226+
3 4 2 7 1 0 8
227227
$
228228
```
229229

230230
## 如何使它崩溃
231231

232232
我打算让你做一些奇怪的事情来使它崩溃,这些函数指针都是类似于其它指针的指针,他们都指向内存的一块区域。C中可以将一种指针的指针转换为另一种,以便以不同方式处理数据。这些通常是不必要的,但是为了想你展示如何侵入你的电脑,我希望你把这段代码添加在`test_sorting`下面:
233233

234-
```
234+
```c
235235
unsigned char *data = (unsigned char *)cmp;
236236

237237
for(i = 0; i < 25; i++) {

0 commit comments

Comments
 (0)