Skip to content
This repository has been archived by the owner on May 6, 2021. It is now read-only.

Commit

Permalink
Add syntax highlight for all files
Browse files Browse the repository at this point in the history
- c for C language
- makefile for Makefile
- sh for shell script
- r for R language
  • Loading branch information
kemchenj committed Jun 24, 2016
1 parent d8a63ea commit 63082c0
Show file tree
Hide file tree
Showing 45 changed files with 227 additions and 230 deletions.
12 changes: 6 additions & 6 deletions ex1.md
Expand Up @@ -6,7 +6,7 @@
这是你用C写的第一个简单的程序:

```
```c
int main(int argc, char *argv[])
{
puts("Hello world.");
Expand All @@ -17,7 +17,7 @@ int main(int argc, char *argv[])
把它写进 `ex1.c` 并输入:
```
```sh
$ make ex1
cc ex1.c -o ex1
```
Expand All @@ -28,7 +28,7 @@ cc ex1.c -o ex1

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

```
```c
$ ./ex1
Hello world.
```
Expand All @@ -41,7 +41,7 @@ Hello world.

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

```
```sh
$ rm ex1
$ CFLAGS="-Wall" make ex1
cc -Wall ex1.c -o ex1
Expand All @@ -54,7 +54,7 @@ $

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

```
```c
#include <stdio.h>
```

Expand All @@ -64,4 +64,4 @@ $

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

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

```
```c
include <stdio.h>

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

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

```
```c
#include <stdio.h>

int main(int argc, char *argv[])
Expand Down Expand Up @@ -42,7 +42,7 @@ int main(int argc, char *argv[])
你可以看到`while`循环的语法更加简单:
```
```c
while(TEST) {
CODE;
}
Expand All @@ -54,7 +54,7 @@ while(TEST) {

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

```
```sh
$ make ex11
cc -Wall -g ex11.c -o ex11
$ ./ex11
Expand Down Expand Up @@ -88,4 +88,4 @@ $
+ 让这些循环倒序执行,通过使用`i--``argc`开始递减直到0。你可能需要做一些算数操作让数组的下标正常工作。
+ 使用`while`循环将`argv`中的值复制到`states`
+ 让这个复制循环不会执行失败,即使`argv`之中有很多元素也不会全部放进`states`
+ 研究你是否真正复制了这些字符串。答案可能会让你感到意外和困惑。
+ 研究你是否真正复制了这些字符串。答案可能会让你感到意外和困惑。
12 changes: 6 additions & 6 deletions ex12.md
Expand Up @@ -6,7 +6,7 @@
`if`语句是每个编程语言中共有的特性,包括C语言。下面是一段代码,使用了`if`语句来确保只传入了一个或两个命令行参数:

```
```c
#include <stdio.h>

int main(int argc, char *argv[])
Expand All @@ -32,7 +32,7 @@ int main(int argc, char *argv[])
`if`语句的格式为:
```
```c
if(TEST) {
CODE;
} else if(TEST) {
Expand All @@ -54,17 +54,17 @@ if(TEST) {

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

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

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

```
```c
#include <stdio.h>

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

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

```
```c
#include <stdio.h>
#include <ctype.h>

Expand Down Expand Up @@ -80,23 +80,23 @@ ex14.c:38-42
向这个程序传入不同的命令行参数来玩转它,这样会遍历你函数中的所有路径。这里演示了我和它的交互:
```
```sh
$ make ex14
cc -Wall -g ex14.c -o ex14
$ ./ex14
'e' == 101 'x' == 120
'e' == 101 'x' == 120
$ ./ex14 hi this is cool
'e' == 101 'x' == 120
'h' == 104 'i' == 105
't' == 116 'h' == 104 'i' == 105 's' == 115
'i' == 105 's' == 115
'c' == 99 'o' == 111 'o' == 111 'l' == 108
'e' == 101 'x' == 120
'h' == 104 'i' == 105
't' == 116 'h' == 104 'i' == 105 's' == 115
'i' == 105 's' == 115
'c' == 99 'o' == 111 'o' == 111 'l' == 108
$ ./ex14 "I go 3 spaces"
'e' == 101 'x' == 120
'I' == 73 ' ' == 32 'g' == 103 'o' == 111 ' ' == 32 ' ' == 32 's' == 115 'p' == 112 'a' == 97 'c' == 99 'e' == 101 's' == 115
'e' == 101 'x' == 120
'I' == 73 ' ' == 32 'g' == 103 'o' == 111 ' ' == 32 ' ' == 32 's' == 115 'p' == 112 'a' == 97 'c' == 99 'e' == 101 's' == 115
$
```

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

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

```
```c
#include <stdio.h>

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

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

```
```c
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
Expand Down Expand Up @@ -137,7 +137,7 @@ int main(int argc, char *argv[])
在你使用描述性注释扩展程序之后,要确保它实际上能够运行,并且产生下面的输出:
```
```sh
$ make ex16
cc -Wall -g ex16.c -o ex16
Expand Down
6 changes: 3 additions & 3 deletions ex17.md
Expand Up @@ -8,7 +8,7 @@

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

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

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

```
```c
int (*POINTER_NAME)(int a, int b)
```

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

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

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

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

```
```sh
$ make ex18
cc -Wall -g ex18.c -o ex18
$ ./ex18 4 1 7 3 2 0 8
0 1 2 3 4 7 8
8 7 4 3 2 1 0
3 4 2 7 1 0 8
0 1 2 3 4 7 8
8 7 4 3 2 1 0
3 4 2 7 1 0 8
$
```

## 如何使它崩溃

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

```
```c
unsigned char *data = (unsigned char *)cmp;

for(i = 0; i < 25; i++) {
Expand Down

0 comments on commit 63082c0

Please sign in to comment.