5. 本章综合练习

1、编程读写一个文件test.txt,每隔1秒向文件中写入一行记录,类似于这样:

1,  2007-7-30 15:16:42
2,  2007-7-30 15:16:43

该程序应该无限循环,直到按Ctrl-C终止。下次再启动程序时在test.txt文件末尾追加记录,并且序号能够接续上次的序号,比如:

1,  2007-7-30 15:16:42
2,  2007-7-30 15:16:43
3,  2007-7-30 15:19:02
4,  2007-7-30 15:19:03
5,  2007-7-30 15:19:04

这类似于很多系统服务维护的日志文件,例如在我的机器上系统服务进程acpid维护一个日志文件/var/log/acpid,就像这样:

$ cat /var/log/acpid
[Sun Oct 26 08:44:46 2008] logfile reopened
[Sun Oct 26 10:11:53 2008] exiting
[Sun Oct 26 18:54:39 2008] starting up
...

每次系统启动时acpid进程就以追加方式打开这个文件,当有事件发生时就追加一条记录,包括事件发生的时刻以及事件描述信息。

获取当前的系统时间需要调用time(2)函数,返回的结果是一个time_t类型,其实就是一个大整数,其值表示从UTC(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数。然后调用localtime(3)time_t所表示的UTC时间转换为本地时间(我们是+8区,比UTC多8个小时)并转成struct tm类型,该类型的各数据成员分别表示年月日时分秒,具体用法请查阅Man Page。调用sleep(3)函数可以指定程序睡眠多少秒。

2、INI文件是一种很常见的配置文件,很多Windows程序都采用这种格式的配置文件,在Linux系统中Qt程序通常也采用这种格式的配置文件。比如:

;Configuration of http
[http]
domain=www.mysite.com
port=8080
cgihome=/cgi-bin

;Configuration of db
[database]
server = mysql
user = myname
password = toopendatabase

一个配置文件由若干个Section组成,由[]括号括起来的是Section名。每个Section下面有若干个key = value形式的键值对(Key-value Pair),等号两边可以有零个或多个空白字符(空格或Tab),每个键值对占一行。以;号开头的行是注释。每个Section结束时有一个或多个空行,空行是仅包含零个或多个空白字符(空格或Tab)的行。INI文件的最后一行后面可能有换行符也可能没有。

现在XML兴起了,INI文件显得有点土。现在要求编程把INI文件转换成XML文件。上面的例子经转换后应该变成这样:

<!-- Configuration of http -->
<http>
        <domain>www.mysite.com</domain>
        <port>8080</port>
        <cgihome>/cgi-bin</cgihome>
</http>

<!-- Configuration of db -->
<database>
        <server>mysql</server>
        <user>myname</user>
        <password>toopendatabase</password>
</database>

3、实现类似gcc-M选项的功能,给定一个.c文件,列出它直接和间接包含的所有头文件,例如有一个main.c文件:

#include <errno.h>
#include "stack.h"

int main()
{
	return 0;
}

你的程序读取这个文件,打印出其中包含的所有头文件的绝对路径:

$ ./a.out main.c
/usr/include/errno.h
/home/akaedu/stack.h: cannot find
/usr/include/features.h
/usr/include/bits/errno.h
/usr/include/linux/errno.h
......

如果有的头文件找不到,就像上面例子那样打印/home/akaedu/stack.h: cannot find。首先复习一下第 2.2 节 “头文件”讲过的头文件查找顺序,本题目不必考虑-I选项指定的目录,只在.c文件所在的目录以及系统目录/usr/include中查找。