Archive for March, 2010
本文通过一个文件拷贝程序的三个不同实现,来说明标准库fread/fwrite、系统调用read/write在缓冲机制上的不同。系统调用没有缓冲(这里不考虑内核缓冲),拿write来说,它的原型int write(int fd, char *buf, size)。write将buf处的size个字节立即写入文件描述符fd指名的文件,而不经过任何缓冲。而C标准库中的f系列函数(fwrite/fread/fgetc/fputc)在FILE结构中内部维护了一个缓冲区(大小是多少?),通常情况下只有当这个缓冲区被写满时才会调用write将其真正地写入文件,fflush(FILE* stream)会强制将缓冲区内容写出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | int main (int argc, char **argv) { int c; //~ fgetc()返回int FILE* fdin = fopen("51.tar.gz", "r"); FILE* fdout = fopen("51.tar.gz.bak", "w"); if (!fdout || !fdin) { fprintf(stderr, "open failure\n"); exit(1); } while ((c = fgetc(fdin)) != EOF) { fputc(c, fdout); } fclose(fdout); fclose(fdin); return 0; } |
| 命令 | 描述 |
|---|---|
| backtrace(或bt) | 查看各级函数调用及参数 |
| finish | 连续运行到当前函数返回为止,然后停下来等待命令 |
| frame(或f) 帧编号 | 选择栈帧 |
| info(或i) locals | 查看当前栈帧局部变量的值 |
| list(或l) | 列出源代码,接着上次的位置往下列,每次列10行 |
| list 行号 | 列出从第几行开始的10行源代码 |
| list 函数名 | 列出某个函数的源代码 |
| next(或n) | 执行下一行语句 |
| print(或p) | 打印表达式的值,通过表达式可以修改变量的值或者调用函数 |
| quit(或q) | 退出gdb调试环境 |
| set var | 修改变量的值 |
| start | 开始执行程序,停在main函数第一行语句前面等待命令 |
| step(或s) | 执行下一行语句,如果有函数调用则进入到函数中 |
| break(或b) 行号 | 在某一行设置断点 |
一个演示脚本
下面的这个脚本修改自《A Practical Guide to Linux Command, Editions, and Shell Programming》。不提供参数时,它将标准输入输出到标准输出;提供一个文件名参数时,将该文件输出到标准输出;提供两个文件名参数时,它将提一个文件复制到第二个文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #! /bin/sh case $# in 0) exec 3<&0 4>&1 ;; 1) exec 3<$1 4<&1 ;; 2) exec 3<$1 4>$2 ;; *) echo "Usage: `basename $0` [source [dest]]" exit 1 ;; esac cat <&3 >&4 exec 3<&- 4>&- exit 0 |
好久没写C++没用STL了,今天在STLChina泡了一下午。完整的代码只写了这么一个,贴上来吧。
写了两个类,Max_Heap和Min_Heap,以他们特例化priority_queue,可以方便地实现最大、最小堆。写完了忽然又觉得这俩类似乎是多此一举了,完全可以用greater
最后还写了测试用例:找出n个数中最大的k个。
1 2 3 4 5 6 7 8 9 10 11 | /*
template < class T, class Container = vector<T>,
class Compare = less<typename Container::value_type> > class priority_queue;
explicit priority_queue ( const Compare& x = Compare(),
const Container& y = Container() );
template <class InputIterator>
priority_queue ( InputIterator first, InputIterator last,
const Compare& x = Compare(),
const Container& y = Container() );
*/ |
Youtube走了,走吧,我用的不多。
Blogger走了,走吧,我才刚开始用。
Sites走了,走吧,我有自己的site。
Facebook走了,走吧,我讨厌SNS。
Twitter走了,走吧,我只是看客,忠实点罢了。
Groups走了,走吧,我偶尔才去TL。
Picasa走了,走吧,又不是非用不可。
G.cn走了,走吧,我用.com。
GReader也走了,走吧,我疯了。
低调;
我还是得低调,低调地做一个屁民,什么游行我都不参与。
我还要感谢国家,是它给了我低调的自由,沉默的权利。
I’m feeling fucky.
对,我就是疯了。
我家住在一个工厂的职工家属大院里,小时候一大帮年纪差不多大的孩子经常在一起玩。在我们这些人里面,有一个孩子比我们大好几岁,长得又高又壮,我们都得喊他老大,有什么好东西都得先孝敬他,有什么好事情都得先感谢他。他看谁不顺眼就经常骂几句踹两脚,因为我们打不过他,谁也不敢吭声,甚至还得在一旁叫好。不过老大也并不一直是这样,有时心情好了还是挺和善的。虽然也经常有人心里犯嘀咕,觉得这个老大不怎么样,但是据说是他保卫了我们的正常生活,而且据说以前的老大特别凶狠霸道,还有外面的更狠的老大们总来找麻烦,是我们现在这个老大把他们全都赶跑了,我们才有今天来之不易的幸福生活,想到这些,我们就觉得我们为他做些事,偶尔被他欺负一下,这些也都是理所当然的了。
要说作为一个普通孩子的我看法,我是支持古哥的,我支持他是因为这么长时间以来终于出现了一个敢向老大挑战的人,无论他是阴谋家还是慈善家,我们总需要这样的变化,游戏才能玩得下去。不然的话,我们只能在老大的看管下日复一日地无知和愚昧下去。有人说,因为我们还很无知,所以不能什么都让我们知道,不然会出乱子,但我觉得恰恰是不让我们知道,才导致我们无知。所以我不接受这个倒果为因的解释,我不想在一段时间以后,外面的孩子看我们的眼光,就像我们现在看东北角那个邻居院子里的孩子们一样。
没有什么能够阻挡 你对自由的向往 天马行空的生涯 你的心了无牵挂 穿过幽暗的岁月 也曾感到彷徨 当你低头的瞬间 才发觉脚下的路 心中那自由的世界 如此的清澈高远 盛开着永不凋零 蓝莲花
当然,我不会一行行的粘贴复制。有一个叫做的tac的命令似乎能完成这个工作,但它只能将整个文件反转。更好的选择是sed:
sed -e '4,240G;3,240h;3,239d' sample.js > reverse.js |
这样就搞定了!
简单解释一下。sed内部维护着两个缓冲区,模式缓冲和保留缓冲。通常,sed每每从文件读入一行就放入模式缓冲,由-e选项指定的各个命令依次处理这个缓冲内的文本,所有命令都执行完后,sed就把模式缓冲的内容输出的标准输出(如果没有指定-n选项的话)。保留缓冲是一个由用户显式使用的缓冲区。-e ’4,240G;3,240h;3,239d’中,G将保留缓冲取的内容附加到(append)模式缓冲,h将模式缓冲复制(copy)到保留缓冲,d将模式缓冲区的内容清除,各个命令前由逗号分割的数字指名了后面的命令在哪些行上执行,各命令由分号进行分割。
具体地:
- 1、2行被读入(模式缓冲)时,-e列出各命令都没有动作,直接输出;
- 第3行被读入时,G不执行,h将该行复制到保留缓冲,d将模式缓冲清除,没有输出;
- 第4行被读入模式缓冲,然后G将保留缓冲的内容(第三行)附加到模式缓冲,h又将模式缓冲复制到保留缓冲,d又将模式缓冲清除,没有输出;
- 重复3,直到第239行;
- 第240行被读入,G将第239到3行附加到第240行后面,h又将其复制到保留缓冲,d不执行,240到3行被输出;
- 241到243行被原样输出,至此,3~240行被反转
两周前,从家里往学校寄了10本书。今天接到通知去邮局取邮件。第一眼看到装书的纸箱子时差点没认出来,原来是一个装葡萄酒的方方正正的箱子,现在俨然一个大冬瓜了!心想箱子坏就坏了吧,书怎么着也不会坏吧,而且里面还塞着许多泡沫板呢,签完字就拿走了。回到宿舍打开一看就傻眼了。年前刚刚买的《Unix网络编程》失去了两周前的光鲜,成了半老徐娘,更惨的是和它一起入住的《算法导论》封面+扉页掉了一半,其他书也都有不同程度的损伤。娘的,看来空投了不止一次啊!邮政的全体员工,在这里,我默默地诅咒你们。