- 浏览: 83667 次
文章分类
- 全部博客 (136)
- 我的技术资料收集 (98)
- 具体技术 (1)
- 的技术资料收集 (4)
- All Articles (1)
- 机器学习 Machine Learning (1)
- 网络编程 (1)
- java (2)
- ava (1)
- 零散技术 (1)
- C# (3)
- 技术资料收集 (1)
- CQRS (1)
- 数据库技术(MS SQL) (1)
- .Net微观世界 (1)
- Oracle SQL学习之路 (1)
- C/C++ (1)
- JS/JQ (1)
- Js封装的插件/实例/方法 (2)
- 敏捷个人 (2)
- Javascript (1)
- 程序设计---设计模式 (1)
- Bug (1)
- 未知分类 (1)
- 程序设计 (1)
- Sharepoint (1)
- Computer Graphic (1)
- IT产品 (1)
- [06]JS/jQuery (1)
- [07]Web开发 (1)
- .NET Solution (1)
- Android (3)
- 机器学习 (1)
- 系统框架设计 (1)
- Others (1)
- 算法 (1)
- 基于Oracle Logminer数据同步 (1)
- 网页设计 (1)
- 原创翻译 (1)
- EXTJS (1)
- Jqgrid (1)
- 云计算 (1)
最新评论
在前面编写简单的c运行库(一)中主要实现了调用main函数前的初始化、获取参数和环境变量、退出程序等工作。接下来我们真正实现c标准库中的一些函数(主要是文件操作、字符串操作函数)。不过我们对这些函数的实现力争简单,对于效率方面考虑的不是很多,因为目的主要还是学习神秘的库是怎么实现的。
1 文件操作
c中的标准I/O库都是带有缓存的,我们在这里为了实现的简单,将缓存省略了,直接包装了有关文件操作的系统调用。现在我们直接看文件打开的函数:
1 static int open(const char *pathname, int flags, int mode)
2 {
3 int ret;
4
5 __asm__ volatile(
6 "int $0x80"
7 :"=a"(ret)
8 :"0"(5),"b"(pathname),"c"(flags),"d"(mode)
9 );
10 if (ret >= 0)
11 return ret;
12 return -1;
13 }
open函数中直接调用了嵌入汇编调用了系统调用。对于系统调用的返回值,如果是负数,直接返回-1,否则直接返回。这个函数是系统调用的一个包装,本质其实就是个系统调用。然后我们在open函数的基础上实现c标志库函数中的fopen函数。
1 FILE *fopen(const char *path, const char *mode)
2 {
3 int fd = -1;
4 int flags = 0;
5 int access = 00700; /*创建文件的权限*/
6
7 if (strcmp(mode, "w") == 0)
8 flags |= O_WRONLY | O_CREAT | O_TRUNC;
9 if (strcmp(mode, "w+") == 0)
10 flags |= O_RDWR | O_CREAT | O_TRUNC;
11 if (strcmp(mode, "r") == 0)
12 flags |= O_RDONLY;
13 if (strcmp(mode, "r+") == 0)
14 flags |= O_RDWR | O_CREAT;
15 fd = open(path, flags, access);
16 return (FILE *)fd;
17 }
由于我没有像标志I/O库那样实现缓存,所以我直接把FILE定义为int型,这样我们用FILE就相当于用了文件描述符。从上面的代码中可以知道我设置了文件的创建权限只有文件创建者有读写执行的权限,还有就是我只实现了以只读、只写、读写方式打开文件,对于追加等方式没有实现。然后函数read、fread和write、fwrite都可以用相同的方式实现,还有fputc,fputs也是已一样的。
2 输出函数
I/O函数中比较麻烦的要属实现printf、fprintf这些可变参数的函数,当然这些函数都是调用vfprintf函数实现的,所以只要实现了vfprintf函数,其它的函数实现就比较简单了。
首先来看下我实现的vfprintf函数代码:
1 int vfprintf(FILE *stream, const char *format, va_list ap)
2 {
3 int n = 0, flag = 0, ret;
4 char str[20];
5
6 while (*format)
7 {
8 switch (*format)
9 {
10 case '%':
11 if (flag == 1)
12 {
13 fputc('%', stream);
14 flag = 0;
15 n ++;
16 }
17 else
18 flag = 1;
19 break;
20 case 'd':
21 if (flag == 1)
22 {
23 itoa((int)va_arg(ap, int), str, 10);
24 ret = fputs(str, stream);
25 n += ret;
26 }
27 else
28 {
29 fputc('d', stream);
30 n ++;
31 }
32 flag = 0;
33 break;
34 case 's':
35 if (flag == 1)
36 {
37 ret = fputs((char *)va_arg(ap, char *), stream);
38 n += ret;
39 }
40 else
41 {
42 fputc('s', stream);
43 n ++;
44 }
45 flag = 0;
46 break;
47 case '\n':
48 /*换行*/
49 fputc(0x0d, stream);
50 n ++;
51 fputc(0x0a, stream);
52 n ++;
53 break;
54 default:
55 fputc(*format, stream);
56 n ++;
57 }
58 format ++;
59 }
60 return n;
61 }
vfprintf主要麻烦的是对格式化字符串的分析,我们在这里使用一种比较简单的算法:
(1)定义模式:翻译模式/普通模式
(2)循环整个格式字符串
a) 如果遇到%
i 普通模式:进入翻译模式
ii 翻译模式: 输出%, 退出翻译模式
b) 如果遇到%后面允许出现的特殊字符(如d和s)
i 翻译模式:从不定参数中取出一个参数输出,退出翻译模式
ii 普通模式:直接输出该字符串
c) 如果遇到其它字符(除\n):无条件退出翻译模式并输出字符
d) 如果遇到'\n'字符,如果直接输出是不能达到换行的效果的,必须要同时输出回车换行才行
从上面的实现vfprintf的代码中可以看出,并不支持特殊的格式控制符,例如位数、进度控制等,仅支持%d与%s这样的简单转换。真正的vfprintf格式化字符串实现比较复杂,因为它支持诸如“%f”、“%x”已有的各种格式、位数、精度控制等。我觉得上面实现的代码已经充分的展示了vfprintf的实现原理和它的关键技巧,所以没有必要一个一个的都实现。现在来实现printf的就简单多了,下面是printf的实现代码:
1 int printf(const char *format, ...)
2 {
3 int n;
4 va_list ap;
5
6 va_start(ap, format);
7 n = vfprintf(stdout, format, ap);
8 va_end(ap);
9 return n;
10 }
对于可变参数的编程,我已经在c语言中的可变参数编程中详细的讲过了,包括它的实现原理。所以只要了解了可变参数的编程,对于实现printf函数来说就真的没什么难度了,纯粹就是调用vfprintf函数而已。如果实现了printf函数,那么对于实现scanf、fscanf也是同样的原理。
发表评论
-
C#WebBrowser控件使用教程与技巧收集--苏飞收集 - sufeinet
2013-06-28 12:07 1067原帖地址:http://www.cnblogs.com/suf ... -
我要喷一个自认为很垃圾的网站架构 - 老赵【苏州】
2013-06-28 12:01 1126原帖地址:http://www.cnblogs.com/lao ... -
[翻译] Oracle Database 12c 新特性Multitenant - Cheney Shue
2013-06-28 11:43 620原帖地址:http://www.cnblogs.com/ese ... -
memcahd 命令操作详解 - 阿正-WEB
2013-06-28 11:37 469原帖地址:http://www.cnblogs.com/azh ... -
面向过程的代码符合大众的思维方式吗? - 史蒂芬.王
2013-06-27 10:28 593原帖地址:http://www.cnblogs.com/ste ... -
面向过程的代码符合大众的思维方式吗? - 史蒂芬.王
2013-06-27 10:28 558原帖地址:http://www.cnblogs.com/ste ... -
RPG游戏之组队测试 - zthua
2013-06-27 10:22 557原帖地址:http://www.cnblogs.com/zth ... -
IT人们给个建议 - SOUTHER
2013-06-26 14:06 523原帖地址:http://www.cnblogs.com/sou ... -
Java向前引用容易出错的地方 - 银河使者
2013-06-26 14:00 492原帖地址:http://www.cnblogs.com/nok ... -
使用Func<T1, T2, TResult> 委托返回匿名对象 - 灰身
2013-06-26 13:54 799原帖地址:http://www.cnblo ... -
【web前端面试题整理03】来看一点CSS相关的吧 - 叶小钗
2013-06-25 10:45 783原帖地址:http://www.cnblogs.com/yex ... -
Windows 8 动手实验系列教程 实验6:设置和首选项 - zigzagPath
2013-06-25 10:27 618原帖地址:http://www.cnblogs.com/zig ... -
闲聊可穿戴设备 - shawn.xie
2013-06-25 10:21 562原帖地址:http://www.cnblo ... -
CentOS下Mysql安装教程 - 小学徒V
2013-06-23 15:24 608原帖地址:http://www.cnblogs.com/xia ... -
vmware安装ubuntu12.04嵌套安装xen server(实现嵌套虚拟化) - skyme
2013-06-23 15:18 836原帖地址:http://www.cnblogs.com/sky ... -
之前专门为IE6、7开发的网站如何迁移到IE10及可能遇到的问题和相应解决方案汇总 - 海之澜
2013-06-23 15:12 949原帖地址:http://www.cnblogs.com/wuz ... -
Android学习笔记--解析XML之SAX - 承香墨影
2013-06-23 15:01 407原帖地址:http://www.cnblo ... -
SQL Server 性能优化之——T-SQL TVF和标量函数
2013-06-19 09:32 670原帖地址:http://www.cnblogs.com/Boy ... -
Nginx学习笔记(二) Nginx--connection&request
2013-06-19 09:26 665原帖地址:http://www.cnblogs.com/cod ... -
从郭美美霸气侧漏看项目管理之项目经理防身术
2013-06-19 09:20 499原帖地址:http://www.cnblogs.com/had ...
相关推荐
1. Microsoft Visual C++ Redistributable: 这是由微软开发的一系列运行库,用于支持使用Visual C++编写的程序。每个版本的VC++运行库都有自己的DLL文件,例如msvcr90.dll、msvcr100.dll等,这些文件包含了运行C++...
《微软官方日文版Visual C++ 2005 SP1运行库详解》 在IT领域,系统工具是不可或缺的一部分,它们为各种应用程序提供必要的支持环境。微软的Visual C++运行库就是这样的一个关键组件,尤其对于那些依赖于特定编程...
4. **CRT (C Run-Time Library)**:这是C语言的基础运行库,提供诸如内存分配、字符串处理、错误处理等基本服务。 5. **OpenMP**:这是一种并行编程模型,允许开发者通过简单的API来利用多核处理器的并行计算能力。...
这些运行库包含了VB和VC编译器在生成可执行文件时依赖的各种动态链接库(DLLs),使得没有安装相应开发环境的用户也能正常运行由VB或VC编写的应用程序。 在VB(Visual Basic)中,运行库主要包含VB运行时组件,这些...
### C运行时库详解 #### 引言 C运行时库是编程中不可或缺的一部分,它在程序执行过程中扮演着至关重要的角色。...理解C运行时库的工作原理及其不同版本间的差异,对于高效编写和优化C语言程序至关重要。
运行库,简单来说,就是一组预编译的代码库,当应用程序运行时,它们会调用这些库中的函数和服务。对于Windows系统而言,常见的运行库有Microsoft Visual C++ Redistributable、Microsoft .NET Framework、Visual ...
在本项目中,我们关注的是一个使用C语言编写的简单月历查询程序。C语言是一种广泛应用的编程语言,以其高效、灵活和接近机器级的特点深受程序员喜爱。在"rili.c"这个源代码文件中,我们可以预期找到实现月历查询功能...
这些运行库包括了动态链接库(DLLs),如msvcr100.dll等,它们是许多软件运行所必需的,尤其是那些使用C或C++编写的程序,例如PHPStudy和AutoCAD。 “无任何冲突”意味着这些运行库之间进行了优化,避免了因版本不...
在Visual Studio 2005 (VS2005)中编写、运行和调试C语言程序,你需要了解一些基本步骤和工具。以下是一份详细指南: ### 前言:关于C/C++编译器的简单介绍 VS2005是微软推出的集成开发环境,不仅支持C++,也支持...
"OpenGL运行库"可能包括了这些DLL文件,如glew32.dll、libglew32.dll等,它们为开发者提供了运行OpenGL应用程序所必需的支持。 另一方面,GLUT(OpenGL Utility Toolkit)是一个用于创建OpenGL程序的开源库,它提供...
《Microsoft Visual C++ 6.0运行库参考手册》是一本深入探讨Microsoft Visual C++ 6.0编程环境中的运行库功能和用法的重要参考资料。该手册覆盖了开发者在使用这个经典版本的编译器和集成开发环境(IDE)时可能会遇到...
**C语言运行环境详解** C语言是一种广泛应用的编程语言,以其高效、简洁和强大的系统级编程能力而闻名。在计算机科学领域,学习和使用C语言是基础技能之一。要运行C语言程序,需要一个合适的开发环境,其中"Win-TC...
C语言函数库是C编程中不可或缺的部分,它们包含了一系列预先编写好的函数,供程序员在编写程序时调用,以实现特定的功能。C语言函数库包括标准库和其他自定义库。标准库提供了大量的基本操作,如输入输出、数学计算...
标题 "C语言编写的DOS环境下运行的音频播放器" 描述了一款专为DOS操作系统设计的音频播放软件。这款播放器具有简洁的用户界面,并且能够支持多种音频格式,使得用户在早期的DOS系统中也能享受到音乐播放的便利。 在...
全国计算机二级C语言等级考试是针对计算机编程初学者和专业人士的一项资格认证,旨在评估考生对C语言编程基础知识、程序设计方法以及问题解决能力的理解。这个考试通常包括理论知识和实践编程两部分,全面覆盖了...
### 在VS2005上编写运行调试C语言 #### 关于C/C++编译器的简单介绍 C/C++编译器是用于将高级语言(C或C++)源代码转换为机器可执行代码的工具。对于学习C语言而言,选择合适的编译器尤为重要。在历史上,Turbo C ...
二、静态库的编写 静态库的编写需要遵循一定的步骤,首先,我们需要创建一个源文件,例如 lib.c,然后在这个文件中编写我们想要的函数代码。例如,在 lib.c 文件中,我们可以编写两个函数,一个是打开 QQ 的函数,...
在这个“RSA加密源代码 c语言编写 可运行”的项目中,我们可以深入理解RSA算法的实现细节。 1. RSA算法原理: RSA基于大数因子分解的困难性。其主要步骤包括: - 密钥生成:选择两个大素数p和q,计算它们的乘积n=...
标题和描述中提到的“如何用C语言编写游戏”,涉及到了编程语言C在游戏开发中的应用。知识点可以从以下几个方面来阐述: 1. 游戏开发的通用概念: 游戏开发是一种高度综合性的艺术形式,它融合了计算机科学、艺术...
TC2.0,全称Turbo C 2.0,是 Borland 公司在上个世纪80年代末90年代初推出的一款经典C语言编译器,它以其高效、小巧、易用的特点,成为了当时许多程序员学习C语言的首选工具。这款编译器在个人计算机普及初期扮演了...