C 语言实现 Linux cat 命令

用 C 语言模拟实现 Linux 的 cat 命令,支持查看单个或多个文件内容。 代码实现 /* * 模拟 Linux cat 命令 * 用法:./mycat file1 [file2 ...] */ #include <stdio.h> #include <stdlib.h> /* 将文件内容复制到输出流 */ void file_copy(FILE *in, FILE *out) { int c; while ((c = getc(in)) != EOF) putc(c, out); } int main(int argc, char *argv[]) { FILE *fp; if (argc == 1) { /* 无参数时,从标准输入读取(与 cat 行为一致) */ file_copy(stdin, stdout); } else { while (--argc > 0) { if ((fp = fopen(*++argv, "r")) == NULL) { fprintf(stderr, "cat: %s: 无法打开文件\n", *argv); return 1; } file_copy(fp, stdout); fclose(fp); } } return 0; } 要点 getc / putc 逐字符读写,适合小文件;大文件建议用 fread / fwrite 按块读写 argc == 1 时从 stdin 读取,使程序支持管道:echo hello | ./mycat 错误信息输出到 stderr,不会混入正常输出 编译运行 gcc -o mycat mycat.c ./mycat file1.txt file2.txt

2015年3月13日 · 1 分钟 · Jid

值得阅读源码的开源项目推荐

学习优秀的代码风格和架构设计,是提升编程能力的有效途径。以下是几个代码质量高、适合阅读学习的开源项目: C 语言项目 项目 特点 适合学习 nginx 高性能 Web 服务器 事件驱动架构、内存池、模块化设计 Linux Kernel 操作系统内核 数据结构、并发控制、底层编程 SQLite 嵌入式数据库 SQL 解析、B 树实现、事务管理 Redis 内存数据库 数据结构、网络编程、单线程高性能 mxml 小型 XML 解析库 代码精简、接口设计 lighttpd 轻量 Web 服务器 网络编程、事件处理 C++ 项目 项目 特点 适合学习 LLVM 编译器基础设施 现代 C++、编译原理、架构设计 Chromium 浏览器引擎 大型项目组织、多进程架构 阅读建议 从小项目开始(mxml、lighttpd),再读大项目 先理解整体架构,再深入具体模块 带着问题读代码:它怎么解决某个问题的?

2015年3月11日 · 1 分钟 · Jid

C/C++ 安全释放指针的方法

代码如下: #include <stdio.h> #include <stdlib.h> #define SAFE_FREE(ptr) do { free(ptr); ptr = NULL; } while(0) #define SAFE_DEL(ptr) do { delete ptr; ptr = NULL; } while(0) #define SAFE_DELARR(ptr) do { delete [] ptr; ptr = NULL; } while(0) int main(int argc, char **argv) { char* p = new char[100]; SAFE_DELARR(p); //system("pause"); return 0; } 实现安全释放指针的机制正是上面的三个宏,其本质就是在释放了指针后,一定要及时地把指针置为NULL。宏体用 do { ... } while(0) 包裹,避免在 if/else 语句中使用时出现编译错误。 注意:上面的代码包括了delete, delete[], 因此是段 C++代码。C的话只要第一个宏即可。

2015年3月10日 · 1 分钟 · Jid

获取整数的最大值最小值的宏定义及可能出现的问题

在C/C++编程中时常需要使用整数的最大值最小值,通常这两个常用是跟平台和操作系统有关的,不同的平台会有不同的值,因此可移植的办法就是使用库函数提供的常量定义。 (1)类似的常量定义在limits.h和float.h头文件中,可以查看源文件获取类似常量的使用办法。在头文件中,整数的最值通常是这样的名字:INT_MAX, INT_MIN,直接使用即可。 (2)当然这两个最值完全可以通过编程实现: #define MAX_INT ((unsigned)(-1)>>1) #define MIN_INT (~MAX_INT) 但是,这两个宏仅仅是没有类别的符号,在使用的时候会陷入困境。看下面这段C++程序,输出结果出乎意料。 #include <iostream> #include <limits> #define MAX_INT ((unsigned)(-1)>>1) #define MIN_INT (~MAX_INT) int main() { std::cout << "max_int: " << MAX_INT << "\n" << "min_int: " << MIN_INT << std::endl; } 输出结果是 max_int: 2147483647 min_int: 2147483648 结果怎么会是这样呢? 问题出在类型上:~MAX_INT 中 MAX_INT 是 unsigned 表达式,对 unsigned 取反得到的还是 unsigned,值为 0x80000000(即无符号的 2147483648)。cout 按 unsigned 输出,所以显示的不是 -2147483648。正确的办法是强制转换: cout << "max_int: " << (int)MAX_INT << "\n" << "min_int: " << (int)MIN_INT << endl; 当然最好的办法还是不要使用#define这个宏,不安全。 (3)针对上面的问题,一个比较好的解决办法是,直接定义常量: const int MAX_INT = ((unsigned)(-1))>>1; const int MIN_INT = ~MAX_INT; 注意:这里的 MAX_INT 是 const int(有符号),与方案 (2) 中 #define 展开后的 unsigned 表达式不同。~MAX_INT 对有符号 int 取反,结果为 -2147483648,printf 用 %d 输出即可正确显示。 ...

2015年3月3日 · 1 分钟 · Jid

最大公约数(GCD)的两种 C 语言实现

一、辗转相除法(欧几里得算法) 数学原理 定理: gcd(a, b) = gcd(b, a % b),其中 a ≥ b。 证明: 设 a = k * b + r(其中 k = a / b,r = a % b),则: 若 d 能整除 a 和 b,则 d 也能整除 r = a - k * b 若 d 能整除 b 和 r,则 d 也能整除 a = k * b + r 因此 (a, b) 和 (b, a % b) 的公约数完全相同,最大公约数也相同。不断递归直到余数为 0,此时的除数即为 GCD。 ...

2015年1月15日 · 2 分钟 · Jid