随笔 - 40, 文章 - 0, 评论 - 9, 引用 - 0
数据加载中……

C++文件读写函数介绍

http://www.zxbc.cn/html/cjjhs/1413524521078.html

今天给大家介绍一下C++中常用到的读写函数,新手可以收藏一下,方便以后查找。 
  1.fopen()
  fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen实现三个功能:为使用而打开一个流,把一个文件和此流相连接,给此流返回一个FILR指针。
  参数filename指向要打开的文件名,mode表示打开状态的字符串,其取值如下:
  字符串 含义
  "r" 以只读方式打开文件
  "w" 以只写方式打开文件
  "a" 以追加方式打开文件
  "r+" 以读/写方式打开文件,如无文件出错
  "w+" 以读/写方式打开文件,如无文件生成新文件
一个文件可以以文本模式或二进制模式打开,这两种的区别是:在文本模式中回车被当成一个字符’\n’,而二进制模式认为它是两个字符 0x0D,0x0A;如果在文件中读到0x1B,文本模式会认为这是文件结束符,也就是二进制模型不会对文件进行处理,而文本方式会按一定的方式对数据作 相应的转换。
  系统默认的是以文本模式打开,可以修改全部变量_fmode的值来修改这个设置,例如_fmode=O_TEXT;就设置默认打开方式为文本模式;而_fmode=O_BINARY;则设置默认打开方式是二进制模式。
  我们也可以在模式字符串中指定打开的模式,如"rb"表示以二进制模式打开只读文件,"w+t"或"wt+"表示以文本模式打开读/写文件。
  此函数返回一个FILE指针,所以申明一个FILE指针后不用初始化,而是用fopen()来返回一个指针并与一个特定的文件相连,如果成败,返回NULL,中国自学编程网,www.zxbc.cn
  例:
   以下是引用片段:
FILE *fp; 
  if(fp=fopen("123.456","wb")) 
  puts("打开文件成功"); 
  else 
  puts("打开文件成败");
  2.fclose()
  fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF。
  在程序结束时一定要记得关闭打开的文件,不然可能会造成数据丢失的情况,我以前就经常犯这样的错误。
  例:fclose(fp);
  3.fputc()
  向流写一个字符,原型是int fputc(int c, FILE *stream); 成功返回这个字符,失败返回EOF。
  例:fputc(’X’,fp);
  4.fgetc()
  从流中读一个字符,原型是int fputc(FILE *stream); 成功返回这个字符,失败返回EOF。
  例:char ch1=fgetc(fp);
  5. fseek()
此函数一般用于二进制模式打开的文件中,功能是定位到流中指定的位置,原型是 int fseek(FILE *stream, long offset, int whence);如果成功返回0,参数offset是移动的字符 数,whence是移动的基准,取值是:
  符号常量 值 基准位置
  SEEK_SET 0 文件开头
  SEEK_CUR 1 当前读写的位置
  SEEK_END 2 文件尾部
  例:fseek(fp,1234L,SEEK_CUR);//把读写位置从当前位置向后移动1234字节(L后缀表示长整数)
  fseek(fp,0L,2);//把读写位置移动到文件尾
  6.fputs()
  写一个字符串到流中,原型int fputs(const char *s, FILE *stream);
    例:fputs("I Love You",fp);
  7.fgets()
  从流中读一行或指定个字符,原型是char *fgets(char *s, int n, FILE *stream); 从流中读取n-1个字符,除非读完一行,参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。
  例:如果一个文件的当前位置的文本如下:
  Love ,I Have
  But ……..
  如果用
  fgets(str1,4,file1);
  则执行后str1="Lov",读取了4-1=3个字符,而如果用
  fgets(str1,23,file1);
  则执行str="Love ,I Have",读取了一行(不包括行尾的’\n’)。
  8.fprintf()
  按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, …]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了。
  例:fprintf(fp,"%2d%s",4,"Hahaha");
  9.fscanf()
  从流中按格式读取,其原型是int fscanf(FILE *stream, const char *format[, address, …]);其用法和scanf()相同,不过不是从控制台读取,而是从流读取罢了。
  例:fscanf(fp,"%d%d" ,&x,&y);
  10.feof()
  检测是否已到文件尾,是返回真,否则返回0,其原型是int feof(FILE *stream);
  例:if(feof(fp))printf("已到文件尾");
  11.ferror()
  原型是int ferror(FILE *stream);返回流最近的错误代码,可用clearerr()来清除它,clearerr()的原型是void clearerr(FILE *stream);
  例:printf("%d",ferror(fp));
  12.rewind()
  把当前的读写位置回到文件开始,原型是void rewind(FILE *stream);其实本函数相当于fseek(fp,0L,SEEK_SET);
  例:rewind(fp);
  12.remove()
  删除文件,原型是int remove(const char *filename); 参数就是要删除的文件名,成功返回0。
  例:remove("c:\\io.sys");
  13.fread()
从流中读指定个数的字符,原型是 size_t fread(void *ptr, size_t size, size_t n, FILE *stream);参数ptr是保存读取的 数据,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是读取的块数,如果成功,返回实际读 取的块数(不是字节数),本函数一般用于二进制模式打开的文件中。
  例:
   以下是引用片段:
char x[4230]; 
  FILE *file1=fopen("c:\\msdos.sys","r"); 
  fread(x,200,12 ,file1);//共读取200*12=2400个字节
  14.fwrite()
与fread对应,向流中写指定的数据,原型是 size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);参数 ptr是要写入的数据指针,void*的指针可用任何类型的指针来替换,如char*、int *等等来替换;size是每块的字节数;n是要写的块数, 如果成功,返回实际写入的块数(不是字节数),本函数一般用于二进制模式打开的文件中。
    例:
   以下是引用片段:
  char x[]="I Love You"; 
  fwire(x, 6,12,fp);//写入6*12=72字节 
  将把"I Love"写到流fp中12次,共72字节
  15.tmpfile()
  其原型是FILE *tmpfile(void); 生成一个临时文件,以"w+b"的模式打开,并返回这个临时流的指针,如果失败返回NULL。在程序结束时,这个文件会被自动删除。
  例:FILE *fp=tmpfile();
  16.tmpnam();
  其原型为char *tmpnam(char *s); 生成一个唯一的文件名,其实tmpfile()就调用了此函数,参数s用来保存得到的文件名,并返回这个指针,如果失败,返回NULL。
  例:tmpnam(str1);

posted @ 2008-09-12 17:07 茶 阅读(747) | 评论 (0)编辑 收藏

C++解析XML(From:C++ front)

http://blog.csdn.net/wangqis/archive/2006/05/17/743039.aspx
http://blog.csdn.net/amidiot/archive/2005/09/11/477335.aspx

用mingw32-make前修改一下makefile文件,改为如下

# DEBUG can be set to YES to include debugging info, or NO otherwise(不是DEBUG)
DEBUG          := NO

# PROFILE can be set to YES to include profiling info, or NO otherwise
PROFILE        := NO

# TINYXML_USE_STL can be used to turn on STL support. NO, then STL
# will not be used. YES will include the STL files.(使用STL,选择的话,则可以使用std::string)
TINYXML_USE_STL := YES


张弛<zhangchi(at)china.com>

注:本文的最新版本可以在下面的地址找到
       http://amidiot.512j.com/article/tinyxml/tinyxml_note.htm

一、      TinyXml的特点

TinyXml是一个基于DOM模型的、非验证的轻量级C++解释器。

1.      SAXDOM

目前XML的解析主要有两大模型:SAXDOM

其中SAX是基于事件的,其基本工作流程是分析XML文档,当发现了一个新的元素时,产生一个对应事件,并调用相应的用户处理函数。这种方式占用内存少,速度快,但用户程序相应得会比较复杂。

DOM(文档对象模型),则是在分析时,一次性的将整个XML文档进行分析,并在内存中形成对应的树结构,同时,向用户提供一系列的接口来访问和编辑该树结构。这种方式占用内存大,速度往往慢于SAX,但可以给用户提供一个面向对象的访问接口,对用户更为友好。

另据说,一些同时提供了SAXDOM接口的库,是在底层先实现SAX,再在SAX的基础上实现DOM

目前我知道的XML解析库有下面几个:

名称

访问接口

是否支持验证

备注

Expat

SAX/Local

不清楚

Local指它还有一套自己访问模型

LibXML2

SAX/DOM

 

 

 

TinyXml

DOM

 

 

 

XML4C

SAX/DOM

Xerces-C是一家,不过用了ICU,国际化似乎更好

Xerces-C

SAX/DOM

 

 

 

XML Booster

Local

不清楚

这个库不是特别了解,好像是类似yacc那样,可以生成一个特定的解析器,估计效率应该很高(看名字也像)。

 

 

 

2.      验证和非验证

对于一个特定的XML文档而言,其正确性分为两个层次。首先是其格式应该符合XML的基本格式要求,比如第一行要有声明,标签的嵌套层次必须前后一致等等,符合这些要求的文件,就是一个合格的XML文件,称作well-formatted。但除此之外,一个XML文档因其内容的不同还必须在语义上符合相应的标准,这些标准由相应的DTD文件或者Schema文件来定义,符合了这些定义要求的XML文件,称作valid

因此,解析器也分为两种,一种是验证的,即会跟据XML文件中的声明,用相应的DTD文件对XML文件进行校验,检查它是否满足DTD文件的要求。另一种是忽略DTD文件,只要基本格式正确,就可以进行解析。

就我所知,验证的解析器通常都是比较重量级的。TinyXml不支持验证,但是体积很小,用在解析格式较为简单的XML文件,比如配置文件时,特别的合适。

 

二、      TinyXml的构建和使用

1.      获取

TinyXml首页在http://www.grinninglizard.com/tinyxml/index.html,从这里可以找到最新版本的源代码,目前的版本是2.3.4

2.      构建

TinyXml在构建时可以选择是否支持STL,选择的话,则可以使用std::string,所以通常应该打开这个选项。

Windows上,TinyXml的源码包里提供了VC6的工程文件,直接用它就可以生成两个静态库(带STL和不带STL),非常容易。唯一需要注意的是,默认生成的库是单线程的,如果用在多线程的项目中,需要改动一下配置,生成相应的多线程库。

Unix平台上,TinyXml的源码包里只提供了一个Makefile,对于典型的Linux系统,或装了gccgmake的其他Unix,这个Makefile足够用了,我在RH9RHEL4上测试,简单的make就成功了。需要注意的有以下几点:默认的编译是不支持STL的,可以通过编辑MakefileTINYXML_USE_STL := NO那一行,把NO改成YES就可以支持STL了;还有默认只生成了一个测试程序,没有生成任何库,如果要生成静态库的话,可以用ar命令,将生成的几个目标文件打包就行了,如果要生成动态库,则需要加上-fpic参数重新编译。

3.      使用

构建了相应的库之后,在使用了它们的工程中,只要在连接时把他们连上就行了。需要注意的是,如果需要STL支持,在编译用到了TinyXml的文件时,需要定义一个宏TIXML_USE_STL,对gcc,可以使用参数-DTIXML_USE_STL,对cl.exeVC),可以使用参数/DTIXML_USE_STL,如果嫌麻烦,可以直接定义在 tinyxml.h文件里。

 

 

 

三、      TinyXml的编程模型

1.      类之间的关系

TinyXml实现的时DOM访问模型,因此提供了一系列的类对应XML文件中的各个节点。主要类间的关系如下图所示:

类结构图

TiXmlBase:其他类的基类,是个抽象类

TiXmlNode:表示一个节点,包含节点的一般方法,如访问自节点、兄弟节点、编辑自身、编辑子节电

TiXmlDocument:表示整个XML文档,不对应其中某个特定的节点。

TiXmlElement:表示元素节点,可以包含子节点和TiXmlAttribute

TiXmlComment:表示注释

TiXmlDeclaration:表示声明

TiXmlText:表示文本节点

TiXmlUnknown:表示未知节点,通常是出错了

TiXmlAttribute:表示一个元素的属性

下面是一个简单的例子:

<?xml version="1.0" encoding="utf-8" ?>
        <!-This is only a sample-->

    <book>

        <name>TinyXml How To</name>

       <price unit=”RMB”>20</price>

        <description>Some words…</description>

 </ book >

 
        整个文档,对应TiXmlDocument

book,name,price, description,都对应TiXmlElement

第一行对应一个TiXmlDeclaration

第二行对应一个TiXmlComment

“TinyXml How To”对应一个TiXmlText

unit则是price的一个TiXmlAttribute

这些类与XML文件中的相应元素都有很好的对应关系,因此相信参照TinyXml的文档,可以很容易的掌握各个方法的使用。

 

2.      需要注意的问题

各类之间的转换

由于各个节点类都从TiXmlNode继承,在使用时常常需要将TiXmlNode*类型的指针转换为其派生类的指针,在进行这种转换时,应该首先使用由TiXmlNode类提供的一系列转换函数,如ToElement(void),而不是c++dynamic_cast

 检查返回值

 由于TinyXml是一个非校验的解析器,因此当解析一个文件时,很可能文件并不包含我们预期的某个节点,在这种情况下,TinyXml将返回空指针。因此,必须要对返回值进行检查,否则将很容易出现内存访问的错误。

 如何重头建立一个XML文件

 先建立一个TiXmlDocument对象,然后,载入某个模板,或者直接插入一个节点作为根节点,接着就可以像打开一个已有的XML文件那样对它进行操作了。

 

四、      总结

TinyXml最大的特点就是它很小,可以很方便的静态连接到程序里。对于像配置文件、简单的数据文件这类文件的解析,它很适合。但是由于它是非验证的,因此需要在程序里做许多检查工做,加重了程序编写的负担。因此对于复杂的XML文件,我觉得最好还是用验证的解析器来处理。


posted @ 2008-09-12 14:12 茶 阅读(779) | 评论 (0)编辑 收藏

C++各大有名库的介绍(作者 armman)

http://hi.baidu.com/chendeping/blog/item/ff0de518418aecb24bedbc6f.html

C++各大有名库的介绍——GUI

  在众多C++的库中,GUI部分的库算是比较繁荣,也比较引人注目的。在实际开发中,GUI库的选择也是非常重要的一件事情,下面我们综述一下可选择的GUI库,各自的特点以及相关工具的支持。

1、MFC

  大名鼎鼎的微软基础类库(Microsoft Foundation Class)。大凡学过VC++的人都应该知道这个库。虽然从技术角度讲,MFC是不大漂亮的,但是它构建于Windows API 之上,能够使程序员的工作更容易,编程效率高,减少了大量在建立 Windows 程序时必须编写的代码,同时它还提供了所有一般 C++ 编程的优点,例如继承和封装。MFC 编写的程序在各个版本的Windows操作系统上是可移植的,例如,在Windows 3.1下编写的代码可以很容易地移植到 Windows NT 或 Windows 95 上。但是在最近发展以及官方支持上日渐势微。

2、QT

参考网站:http://www.trolltech.com

  Qt是Trolltech公司的一个多平台的C++图形用户界面应用程序框架。它提供给应用程序开发者建立艺术级的图形用户界 面所需的所用功能。Qt是完全面向对象的很容易扩展,并且允许真正地组件编程。自从1996年早些时候,Qt进入商业领域,它已经成为全世界范围内数千种 成功的应用程序的基础。Qt也是流行的Linux桌面环境KDE 的基础,同时它还支持Windows、Macintosh、Unix/X11等多种平台。

3、WxWindows

参考网站:http://www.wxwindows.org

  跨平台的GUI库。因为其类层次极像MFC,所以有文章介绍从MFC到WxWindows的代码移植以实现跨平台的功能。通过 多年的开发也是一个日趋完善的GUI库,支持同样不弱于前面两个库。并且是完全开放源代码的。新近的C++ Builder X的GUI设计器就是基于这个库的。

4、Fox

参考网站:http://www.fox-toolkit.org/

  开放源代码的GUI库。作者从自己亲身的开发经验中得出了一个理想的GUI库应该是什么样子的感受出发,从而开始了对这个库的开发。有兴趣的可以尝试一下。

5、WTL

  基于ATL的一个库。因为使用了大量ATL的轻量级手法,模板等技术,在代码尺寸,以及速度优化方面做得非常到位。主要面向的使用群体是开发COM轻量级供网络下载的可视化控件的开发者。

6、GTK

参考网站:http://gtkmm.sourceforge.net/

  GTK是一个大名鼎鼎的C的开源GUI库。在Linux世界中有Gnome这样的杀手应用。而Qt就是这个库的C++封装版本。

C++各大有名库的介绍——网络通信

1、ACE

参考网站:http://www.cs.wustl.edu/~schmidt/ACE.html

  C++库的代表,超重量级的网络通信开发框架。ACE自适配通信环境(Adaptive Communication Environment)是可以自由使用、开放源代码的面向对象框架,在其中实现了许多用于并发通信软件的核心模式。ACE提供了一组丰富的可复用C++ 包装外观(Wrapper Facade)和框架组件,可跨越多种平台完成通用的通信软件任务,其中包括:事件多路分离和事件处理器分派、信号处理、服务初始化、进程间通信、共享内 存管理、消息路由、分布式服务动态(重)配置、并发执行和同步,等等。

2、StreamModule

参考网站:http://www.omnifarious.org/StrMod

  设计用于简化编写分布式程序的库。尝试着使得编写处理异步行为的程序更容易,而不是用同步的外壳包起异步的本质。

3、SimpleSocket

参考网站:http://home.hetnet.nl/~lcbokkers/simsock.htm

  这个类库让编写基于socket的客户/服务器程序更加容易。

4、A Stream Socket API for C++

参考网站:http://www.pcs.cnu.edu/~dgame/sockets/socketsC++/sockets.html

  又一个对Socket的封装库。

C++各大有名库的介绍——XML

1、Xerces

参考网站:http://xml.apache.org/xerces-c/

  Xerces-C++ 是一个非常健壮的XML解析器,它提供了验证,以及SAX和DOM API。XML验证在文档类型定义(Document Type Definition,DTD)方面有很好的支持,并且在2001年12月增加了支持W3C XMLSchema 的基本完整的开放标准。

2、XMLBooster

参考网站:http://www.xmlbooster.com/

  这个库通过产生特制的parser的办法极大的提高了XML解析的速度,并且能够产生相应的GUI程序来修改这个parser。在DOM和SAX两大主流XML解析办法之外提供了另外一个可行的解决方案。

3、Pull Parser

参考网站:http://www.extreme.indiana.edu/xgws/xsoap/xpp

  这个库采用pull方法的parser。在每个SAX的parser底层都有一个pull的parser,这个xpp把这层暴露出来直接给大家使用。在要充分考虑速度的时候值得尝试。

4、Xalan

参考网站:http://xml.apache.org/xalan-c/

  Xalan是一个用于把XML文档转换为HTML,纯文本或者其他XML类型文档的XSLT处理器。

5、CMarkup

参考网站:http://www.firstobject.com/xml.htm

  这是一种使用EDOM的XML解析器。在很多思路上面非常灵活实用。值得大家在DOM和SAX之外寻求一点灵感。

6、libxml++

http://libxmlplusplus.sourceforge.net/

  libxml++是对著名的libxml XML解析器的C++封装版本。

C++各大有名库的介绍——科学计算

1、Blitz++

参考网站:http://www.oonumerics.org/blitz

  Blitz++ 是一个高效率的数值计算函数库,它的设计目的是希望建立一套既具像C++ 一样方便,同时又比Fortran速度更快的数值计算环境。通常,用C++所写出的数值程序,比 Fortran慢20%左右,因此Blitz++正是要改掉这个缺点。方法是利用C++的template技术,程序执行甚至可以比Fortran更快。

  Blitz++目前仍在发展中,对于常见的SVD,FFTs,QMRES等常见的线性代数方法并不提供,不过使用者可以很容易地利用Blitz++所提供的函数来构建。

2、POOMA

参考网站:http://www.codesourcery.com/pooma/pooma

  POOMA是一个免费的高性能的C++库,用于处理并行式科学计算。POOMA的面向对象设计方便了快速的程序开发,对并行机器进行了优化以达到最高的效率,方便在工业和研究环境中使用。

3、MTL

参考网站:http://www.osl.iu.edu/research/mtl

  Matrix Template Library(MTL)是一个高性能的泛型组件库,提供了各种格式矩阵的大量线性代数方面的功能。在某些应用使用高性能编译器的情况下,比如Intel的编译器,从产生的汇编代码可以看出其与手写几乎没有两样的效能。

4、CGAL

参考网站:www.cgal.org

  Computational Geometry Algorithms Library的目的是把在计算几何方面的大部分重要的解决方案和方法以C++库的形式提供给工业和学术界的用户。

================================================================

作者说:MFC是不大漂亮的。我至今没有这样的认识。好像很多人这样说,我不明白为什么,我觉得MFC是优美的,合适的。而且只要 你明白了MFC的模块状态、线程状态和模块线程状态,明白了OLE,那么MFC就是清晰的。有些说MFC的宏不好,我不认为,ATL也像MFC一样用宏, 而且这些宏虽不利于调试,却是利于阅读的。如果说MFC提供的界面元素不够新颖,不够丰富,我没有任何意见,这也是BCG库及类似的库存在的原因。



posted @ 2008-09-12 13:55 茶 阅读(763) | 评论 (1)编辑 收藏

STL vector 容器介绍

     摘要: http://blog.csdn.net/masterlee/archive/2004/11/09/174129.aspx STL vector 容器介绍 A Presentation of the STL Vector Container (By Nitron) 翻译 masterlee 介绍std::vector,并且讨论它在STL中的算法和条件函数remove_if()。 &nbs...  阅读全文

posted @ 2008-09-04 17:06 茶 阅读(1356) | 评论 (0)编辑 收藏

vc的stdafx文件和C1083、C1010错误(转)

http://blog.csdn.net/gofishing/archive/2006/04/12/660798.aspx

今天在改一个旧的vc6工程(为了节省空间和方便备份,以前收尾时把中间文件都删了),整理了一下文件,归了归类,结果不知怎么的,工程不能编译了,编译 什么文件都出现 fatal error C1083: Cannot open precompiled header file: 'Debug/xxx.pch': No such file or directory, 可是我也没删什么文件,改程序内容,就是把文件挪了挪,看来是vc的工程有点问题,只好查查怎么回事。

用vc新建的工程一般都有这两个文件(空工程除外),其实如果不用mfc,这两个根本没用
StdAfx.cpp 就一句#include "stdafx.h"
StdAfx.h 包含了一些头文件,如果没用mfc就一句有用的#include <stdio.h>
要 是你把哪个源文件的#include "stdafx.h"这行删除了,或者从其他工程考过来一个文件没有这行的,编译时一律是 fatal error C1010: unexpected end of file while looking for precompiled header directive, 这时你只要给该文件开头加个#include "stdafx.h"就了事。
这两个文件除了这点之外还有一个问题,就是这两个文件不能从工程里删 除,不然你编译任何一个.cpp/.c的文件都会报 fatal error C1083: Cannot open precompiled header file: 'Debug/xxx.pch': No such file or directory, 你build也不行,vc会给每一个源文件报这样一个错误。

你再把这两个文件加入工程,一样不行,不论你把他们加在哪,怎么编译就是fatal error C1083,找不到.pch文件。只有新建一个工程,然后把原来的源文件都加过去,要是工程里有很多源文件,进行了很多设置的话,可就麻烦了。

于 是,我新建了一个工程就叫test把,看看怎么会出现fatal error C1083的。在新建一个工程后,vc在工程目录里生成了几个文件,包括 test.dsp(工程文件)、StdAfx.h、StdAfx.cpp。和主程序源文件test.cpp等。如果你build工程,会在相应的编译目录 下(一般为debug或release)产生test.pch、vc60.idb、vc60.pdb、StdAfx.obj和源程序的obj、pdb文件 和一个test.exe程序,fatal error C1083就是说没有这个.pch文件,他也不能产生这个文件。那到底vc是怎么产生这个文件的, 又是作了什么改动使他不能再产生这个文件的呢?我们将debug目录删除,然后编译test.cpp文件,结果j:\test \test.cpp(4) : fatal error C1083: Cannot open precompiled header file: 'Debug/test.pch': No such file or directory; 不行,我build:
--------------------Configuration: test - Win32 Debug--------------------
Compiling...
StdAfx.cpp
Compiling...
test.cpp
Linking...
test.exe - 0 error(s), 0 warning(s)

看 来是编译StdAfx.cpp产生了test.pch,然后再编译test.cpp的把;再把debug目录删了,编译StdAfx.cpp就ok,看看 debug目录:test.pch、StdAfx.obj、vc60.idb、vc60.pdb。原来是编译StdAfx.cpp产生的pch文件,那从 工程里删除这个文件然后在添加这个文件为什么不行呢?肯定是在在删除/添加StdAfx.cpp文件过程中,工程文件不一样了。先关闭工程,把 test.dsp备份,然后打开工程,删除StdAfx.cpp文件,在添加,编译,错误C1083,然后关闭工程(保存工程)。fc比较一下刚才备份的 dsp和现在的工程文件,发现原来正常的那个工程文件里在SOURCE=.\StdAfx.cpp之后多这么一 行# ADD CPP /Yc"stdafx.h",而删了StdAfx.cpp再添加的工程就没有,其他的就完全一样。

正常的dsp文件包含StdAfx.cpp的这两行是这样的:
SOURCE=.\StdAfx.cpp
# ADD CPP /Yc"stdafx.h"
# End Source File

后记:
vc 真是奇怪呀,这行# ADD CPP /Yc"stdafx.h"在新建工程时有,从工程里删除了StdAfx.cpp就没有了,再在工程里加上这个 StdAfx.cpp就没有加上。看似删除再添加好像没有动工程,谁知道他来这么一手,艾,要是懂编译懂vc的还好,要是遇上我这样的菜鸟,艾,只有和他 奋斗半天才把他搞得稀里糊涂。把他写出来,免得和我一样的菜鸟再费半天劲。

其实这个pch文件是预编译头 (PreCompiled Header),下边是msdn里关于PreCompiled Header和/Yc选项的解释。一直都是用集成编译环境的, 先是tc,然后是vc,没用过make,没写过makefile,对编译、连接这些东西还不是很懂,高手见笑了。这个选项是可以在工程的设置里设的,具体 可以看下边的msdn帮助。

/Yc  (Create Precompiled Header File)
Home | Overview | How Do I | Compiler Options
This option instructs the compiler to create a precompiled header (.PCH) file that represents the state of compilation at a certain point. (To find this option in the development environment, click Settings on the Project menu. Then click the C/C++ tab, and click Precompiled Headers in the Category box.) 
Command Line Project Settings Description 
/Yc Create Precompiled Header File The compiler compiles all code up to the end of the base source file, or to the point in the base file where #pragma hdrstop occurs.
/Ycfilename Through Header The compiler compiles all code up to and including the .H file specified in the Through Header text box (filename).

The precompiled code is saved in a file with a name created from the base name of the file specified with the /Yc option and a .PCH extension. You can also use the /Fp option to specify a name for the precompiled header file.
If you use /Ycfilename (Through Header), the compiler compiles all code up to and including the specified file for subsequent use with the /Yu option. 
Note  If the options /Ycfilename and /Yufilename occur on the same command line and both reference, or imply, the same file name, /Ycfilename, takes precedence. This feature simplifies the writing of makefiles.
Example
Consider the following code:
#include <afxwin.h>  // Include header for class library
#include "resource.h" // Include resource definitions
#include "myapp.h"  // Include information specific to this app
...
When this code is compiled with the command
CL /YcMYAPP.H PROG.CPP
the compiler saves all the preprocessing for AFXWIN.H, RESOURCE.H, and MYAPP.H in a precompiled header file called MYAPP.PCH.
See Also  Creating Precompiled Header Files

posted @ 2008-09-04 14:17 茶 阅读(1317) | 评论 (0)编辑 收藏

同步通信方式与异步通信方式有什么区别

最近在看通信的接口规范,对同步通信和异步通信概念不了解。这里收集点相关资料。以后如果用到也会逐步填加。有什么不对的地方也请各位帮忙指点下。

同步通信方式与异步通信方式有什么区别

资料一:
在串行通信中,由于是一位一位地进行数据传送。为了把每个字节区别开来,需
要收发双方在传送数据的串行信息流中,加入一些标记信号位。根据所添加的标记信号
位的不同方式,分成同步通信和异步通信两种。

    异步通信在添加标记信号位时,把所传送的数据以字节为单位。每个字节前加上
一位起始位,每个字节的后面加上停止位,停止位可以是1位、1.5位或2位。有时,还
要加上一位奇偶检验位。

    1(起始位)+2(停止位)+1(奇偶校验位)Κ4位标记信号位。这样,异步通
信方式的效率就比较低。

    同步通信是把所传送的数据以多个字节(100字节以上)为单位,在其前后添加
标志。

资料二:
异步通信”是一种很常用的通信方式。异步通信在发送字符时,所发送的字符之间的时间间隔可以是任意的。当然,接收端必须时刻做好接收的准备(如果接收端主 机的电源都没有加上,那么发送端发送字符就没有意义,因为接收端根本无法接收)。发送端可以在任意时刻开始发送字符,因此必须在每一个字符的开始和结束的 地方加上标志,即加上开始位和停止位,以便使接收端能够正确地将每一个字符接收下来。异步通信的好处是通信设备简单、便宜,但传输效率较低(因为开始位和 停止位的开销所占比例较大)。
异步通信也可以是以帧作为发送的单位。接收端必须随时做好接收帧的准备。这是,帧的首部必须设有一些特殊的比特组合,使得接收端能够找出一帧 的开始。这也称为帧定界。帧定界还包含确定帧的结束位置。这有两种方法。一种是在帧的尾部设有某种特殊的比特组合来标志帧的结束。或者在帧首部中设有帧长 度的字段。需要注意的是,在异步发送帧时,并不是说发送端对帧中的每一个字符都必须加上开始位和停止位后再发送出去,而是说,发送端可以在任意时间发送一 个帧,而帧与帧之间的时间间隔也可以是任意的。在一帧中的所有比特是连续发送的。发送端不需要在发送一帧之前和接收端进行协调(不需要先进行比特同步)。 每个字符开始发送的时间可以是任意的t0 0 1 1 0 1 1 0起始位结束位t每个帧开始发送的时间可以是任意的以字符为单位发送以帧为单位发送帧开始帧结束
“同步通信”的通信双方必须先建立同步,即双方的时钟要调整到同一个频率。收发双方不停地发送和接收连续的同步比特流。但这时还有两种不同的 同步方式。一种是使用全网同步,用一个非常精确的主时钟对全网所有结点上的时钟进行同步。另一种是使用准同步,各结点的时钟之间允许有微小的误差,然后采 用其他措施实现同步传输。

posted @ 2008-08-21 10:26 茶 阅读(2051) | 评论 (0)编辑 收藏

学习linux/unix编程方法的建议(转)

首先先学学编辑器,vim, emacs什么的都行。
然后学make file文件,只要知道一点就行,这样就可以准备编程序了。

  然后看看《C程序设计语言》K&R,这样呢,基本上就可以进行一般的编程了,顺便找本数据结构的书来看。

  如果想学习UNIX/LINUX的编程,《APUE》绝对经典的教材,加深一下功底,学习《UNP》的第二卷。这样基本上系统方面的就可以掌握了。

  然后再看Douglus E. Comer的《用TCP/IP进行网际互连》第一卷,学习一下网络的知识,再看《UNP》的第一卷,不仅学习网络编程,而且对系统编程的一些常用的技巧就很熟悉了,如果继续网络编程,建议看《TCP/IP进行网际互连》的第三卷,里面有很多关于应用协议telnet、ftp等协议的编程。
如果想写设备驱动程序,首先您的系统编程的接口比如文件、IPC等必须要熟知了,再学习《LDD》2。

  对于几本经典教材的评价:

  《The C Programing Language》K&R 经典的C语言程序设计教材,作者是C语言的发明者,教材内容****。虽然有点老,但是必备的一本手册,现在有时候我还常翻翻。篇幅比较小,但是每看一遍,就有一遍的收获。另外也可用谭浩强的《C语言程序设计》代替。

  《Advanced Programing in Unix Envirement》 W.Richard Stevens:也是非常经典的书(废话,Stevens的书哪有不经典的!),虽然初学者就可以看,但是事实上它是《Unix Network Programing》的一本辅助资料。国内的翻译的《UNIX环境高级编程》的水平不怎么样,现在有影印版,直接读英文比读中文来得容易。

  《Unix Network Programing》W.Richard Stevens:第一卷讲BSD Socket网络编程接口和另外一种网络编程接口的,不过现在一般都用BSD Socket,所以这本书只要看大约一半多就可以了。第二卷没有设计到网络的东西,主要讲进程间通讯和Posix线程。所以看了《APUE》以后,就可以看它了,基本上系统的东西就由《APUE》和《UNP》vol2概括了。看过《UNP》以后,您就会知道系统编程的绝大部分编程技巧,即使卷一是讲网络编程的。国内是清华翻译得《Unix网络编程》,翻译者得功底也比较高,翻译地比较好。所以建议还是看中文版。

  《TCP/IP祥解》一共三卷,卷一讲协议,卷二讲实现,卷三讲编程应用。我没有怎么看过。,但是据说也很经典的,因为我没有时间看卷二,所以不便评价。

  《用TCP/IP进行网际互连》Douglus.E.Comer 一共三卷,卷一讲原理,卷二讲实现,卷三讲高级协议。感觉上这一套要比Stevens的那一套要好,就连Stevens也不得不承认它的第一卷非常经典。事实上,第一卷即使你没有一点网络的知识,看完以后也会对网络的来龙去脉了如指掌。第一卷中还有很多习题也设计得经典和实用,因为作者本身就是一位教师,并且卷一是国外研究生的教材。习题并没有答案,留给读者思考,因为问题得答案可以让你成为一个中级的Hacker,这些问题的答案可以象Douglus索取,不过只有他只给教师卷二我没有怎么看,卷三可以作为参考手册,其中地例子也很经典。如果您看过Qterm的源代码,就会知道Qterm的telnet 实现部分大多数就是从这本书的源代码过来的。对于网络原理的书,我推荐它,而不是Stevens的《TCP/IP祥解》。

  《Operating System - Design and Implement》这个是讲操作系统的书,用Minix做的例子。作者母语不是英文,所以英文看起来比较晦涩。国内翻译的是《操作系统 设计与实现》,我没看过中文版,因为翻译者是尤晋元,他翻译的《APUE》已经让我失望头顶了。读了这本书,对操作系统的底层怎么工作的就会
有一个清晰的认识。

  《Linux Device Driver》2e ,为数不多的关于Linux设备驱动程序的好书。不过内容有些杂乱,如果您没有一些写驱动的经验,初次看会有些摸不着南北。国内翻译的是《Linux设备驱动程序》第二版,第一版,第二版的译者我都有很深的接触,不过总体上来说,虽然第二版翻译的有些不尽人意,但是相比第一版来说已经超出了一大截。要读这一本书,至少应该先找一些《计算机原理》《计算机体系结构》的书来马马虎虎读读,至少应该对硬件和计算机的工作过程有一些了解。

posted @ 2008-08-05 00:04 茶 阅读(268) | 评论 (0)编辑 收藏

教你怎样做项目开发总结报告

I 引言
1.1编写目的
  说明编写这份项目开发总结报告的目的,指出预期的阅读范围。
1.2背景
  说明:
  a.本项目的名称和所开发出来的软件系统的名称;
  b.此软件的任务提出者、开发者、用户及安装此软件的计算中心。
I.3定义
  列出本文件中用到的专门术语的定义和外文首字母组词的原词组。
1.4参考资料
  列出要用到的参考资料,如:
  a.本项目的已核准的计划任务书或合同、上级机关的批文;
  b.属于本项目的其他已发表的文件;
  c.本文件中各处所引用的文件、资料,包括所要用到的软件开发标准。 列出这些文件的标题、文

件编号、发表日期和出版单位,说明能够得到这些文件资料的来源。
2 实际开发结果
2.1产品
  说明最终制成的产品,包括:
  a.程序系统中各个程序的名字,它们之间的层次关系,以千字节为单位的各个程序的程序量、存储

媒体的形式和数量;
  b.程序系统共有哪几个版本,各自的版本号及它们之间的区别;
  c.每个文件的名称;
  d.所建立的每个数据库。 如果开发中制订过配置管理计划,要同这个计划相比较。
2.2主要功能和性能
  逐项列出本软件产品所实际具有的主要功能和性能,对照可行性研究报告、项目开发计划、功能需

.求说明书的有关内容,说明原定的开发目标是达到了、未完全达到、或超过了。
2.3基本流程
  用图给出本程序系统的实际的基本的处理流程。
2.4进度
  列出原定计划进度与实际进度的对比,明确说明,实际进度是提前了、还是延迟了,分析主要原因


2.5费用
  列出原定计划费用与实际支出费用的对比,包括:
  a.工时,以人月为单位,并按不同级别统计;
  b.计算机的使用时间,区别CPU时间及其他设备时间;
  c.物料消耗、出差费等其他支出。
  明确说明,经费是超出了、还是节余了,分析其主要原因。
3 开发工作评价
3.1对生产效率的评价
  给出实际生产效率,包括:
  a.程序的平均生产效率,即每人月生产的行数;
  b.文件的平均生产效率,即每人月生产的千字数;
  并列出原订计划数作为对比。
3.2对产品质量的评价
  说明在测试中检查出来的程序编制中的错误发生率,即每干条指令(或语句)中的错误指令数(或

语句数)。如果开发中制订过质量保证计划或配置管理计划,要同这些计划相比较。
3.3对技术方法的评价
  给出对在开发中所使用的技术、方法、工具、手段的评价。
3.4出错原因的分析
  给出对于开发中出现的错误的原因分析。
4 经验与教训
  列出从这项开发工作中所得到的最主要的经验与教训及对今后的项目开发工作的建议。

posted @ 2008-07-02 00:26 茶 阅读(533) | 评论 (0)编辑 收藏

进程间通讯的方法

进程通常被定义为一个正在运行的程序的实例,它由两个部分组成:
       一个是操作系统用来管理进程的内核对象。内核对象也是系统用来存放关于进程的统计信息的地方
      另一个是地址空间,它包含所有的可执行模块或DLL模块的代码和数据。它还包含动态分配的空间。如线程堆栈和堆分配空间。每个进程被赋予它自己的虚拟地址空间,当进程中的一个线程正在运行时,该线程可以访问只属于它的进程的内存。属于其它进程的内存则是隐藏的,并不能被正在运行的线程访问。
   为了能在两个进程之间进行通讯,由以下几种方法可供参考:

0。剪贴板Clipboard: 在16位时代常使用的方式,CWnd中提供支持

1。窗口消息 标准的Windows消息以及专用的WM_COPYDATA消息 SENDMESSAGE()接收端必须有一个窗口

2。使用共享内存方式(Shared Memory)
   a.设定一块共享内存区域          
     HANDLE CreateFileMapping(HANDLE,LPSECURITY_ATTRIBUTES, DWORD, DWORD, DWORD,  LPCSTR)
     产生一个file-mapping核心对象
     LPVOID MapViewOfFile(
         HANDLE hFileMappingObject,
         DWORD  dwDesiredAcess,
         DWORD  dwFileOffsetHigh,
         DWORD  dwFileOffsetLow,
         DWORD  dwNumberOfBytesToMap
     );
    得到共享内存的指针
   b.找出共享内存
    决定这块内存要以点对点(peer to peer)的形式呈现
        每个进程都必须有相同的能力,产生共享内存并将它初始化。每个进程
        都应该调用CreateFileMapping(),然后调用GetLastError().如果传回的
        错误代码是ERROR_ALREADY_EXISTS,那么进程就可以假设这一共享内存区         域已经被别的进程打开并初始化了,否则该进程就可以合理的认为自己 排在第          一位,并接下来将共享内存初始化。
    还是要使用client/server架构中
       只有server进程才应该产生并初始化共享内存。所有的进程都应该使用

HANDLE OpenFileMapping(DWORD dwDesiredAccess,
                                   BOOL bInheritHandle,
                                   LPCTSTR lpName);
        再调用MapViewOfFile(),取得共享内存的指针
   c.同步处理(Mutex)
   d.清理(Cleaning up) BOOL UnmapViewOfFile(LPCVOID lpBaseAddress);
                        CloseHandle()

3。动态数据交换(DDE)通过维护全局分配内存使的应用程序间传递成为可能
   其方式是再一块全局内存中手工放置大量的数据,然后使用窗口消息传递内存    指针.这是16位WIN时代使用的方式,因为在WIN32下已经没有全局和局部内存    了,现在的内存只有一种就是虚存。  

4。消息管道(Message Pipe)
   用于设置应用程序间的一条永久通讯通道,通过该通道可以象自己的应用程序
   访问一个平面文件一样读写数据。
   匿名管道(Anonymous Pipes)
       单向流动,并且只能够在同一电脑上的各个进程之间流动。
   命名管道(Named Pipes)
       双向,跨网络,任何进程都可以轻易的抓住,放进管道的数据有固定的格        式,而使用ReadFile()只能读取该大小的倍数。
       可以被使用于I/O Completion Ports

5   邮件槽(Mailslots)
    广播式通信,在32系统中提供的新方法,可以在不同主机间交换数据,在        WIN9X下只支持邮件槽客户

6。Windows套接字(Windows Socket)
   它具备消息管道所有的功能,但遵守一套通信标准使的不同操作系统之上的应    用程序之间可以互相通信。

7。Internet通信 它让应用程序从Internet地址上载或下载文件

8。RPC:远程过程调用,很少使用,因其与UNIX的RPC不兼容。

9。串行/并行通信(Serial/Parallel Communication)
   它允许应用程序通过串行或并行端口与其他的应用程序通信

10。COM/DCOM
     通过COM系统的代理存根方式进行进程间数据交换,但只能够表现在对接口     函数的调用时传送数据,通过DCOM可以在不同主机间传送数据。

posted @ 2008-07-02 00:21 茶 阅读(345) | 评论 (0)编辑 收藏

C/C++预处理过程与语句总结

转载请保留: http://www.cnscn.org(CNS电脑与英语学习网)
Author: cnscn <http://www.cnscn.org>

1)预处理

  根据已放置在文件中的预处理指令来修改源文件的 内容
  预处理器会分析\执行所有的预处理器指令,然后删除他们,得到一个仅包含C++语句的转换单元
  预处理指令以#号开头


  常用的预处理指令:
  #include       包含头文件

  #if               条件
  #else          否则
  #elif            否则如果
  #endif         结束条件

  #ifdef  或 #if defined        如果定义了一个符号, 就执行操作
  #ifndef 或 #if !defined      如果没有定义一个符号, 就指执行操作

  #define        定义一个符号
  #undef         删除一个符号

  #line            重新定义当前行号和文件名

  #error            输出编译错误 消息, 停止编译

  #pragma        提供 机器专用的特性,同时保证与C++的完全兼容


2)#include  在 程序中包含头文件
 头文件通常以.h结尾,其 内容可使用#include预处理器指令包含到 程序
 头文件中一般包含: 函数原型与全局变量

  形式常有下面两种
  #include <iostream>
  #include "myheader.h"

  前者<>用来引用标准库头文件,后者""常用来引用自定义的头文件
  前者<>编译器只搜索包含标准库头文件的默认 目录,后者首先搜索正在编译的源文件所在的 目录,找不到时再搜索包含标准库头文件的默认 目录.
  如果把头文件放在其他 目录下,为了查找到它,必须在双引号中指定从源文件到头文件的完整路径


3)#define  定义符号、宏
1>符号
  #define PI 3.1415925  定义符号PI为3.1415925
  #define PI      取消PI的值

  这里PI看起来像一个变量,但它与变量没有任何关系,它只是一个符号或标志,在 程序代码编译前,此符号会用一组指定的字符来代替
  3.14159265 不是一个数值,只是一个字符串,不会进行检查

  在编译前,预处理器会遍历代码,在它认为置换有意义的地方,用字符串PI的定义值(3.14159265)来代替
 在注释或字符串中的PI不进行替换

  在C中常以#define来定义符号常量,但在C++中最好使用const 来定义常量
  #define PI 3.14159265
  const long double PI=3.14159265;
  两者比较下,前者没有类型的指定容易引起不必须的麻烦,而后者定义清楚,所以在C++中推荐使用const来定义常量

 #define的缺点:
   1)不支持类型检查
   2)不考虑作用域
   3)符号名不能限制在一个命名 空间



2>#undef 删除#define定义的符号
  #define PI 3.14159265
  ... //之间所有的PI都可以被替换为3.14159265

  #undef PI
  之后不再有PI这个标识符


3>定义宏
  #define Print(Var) count<<(Var)<<endl
  用宏名中的参数带入语句中的参数
  宏后面没有;号
  Print(Var)中的Print和(之间不能有空格,否则(就会被解释为置换字符串的一部分

  #define Print(Var, digits)  count << setw(digits) << (Var) << endl
  调用
  Print(ival, 15)
  预处理器就会把它换成
  cout << setw(15) << (ival) << endl;


  所有的情况下都可以使用内联函数来代替宏,这样可以增强类型的检查
  template<class T> inline void Print (const T& var, const int& digits)
  {
      count<<setw(digits)<<var<<endl;
  }

  调用
  Print(ival, 15);


  使用宏时应注意的易引起的错误:
  #define max(x,y) x>y?x:y;+


  调用 result = max(myval, 99);  则换成 result = myval>99?myval:99;  这个没有问题是正确的
  调用 result = max(myval++, 99);  则换成 result = myval++>99?myval++:99; 这样如果myval>99那么myval就会递增两次,这种情况下()是没什么用的如result=max((x),y)则 result = (myval++)>99?(myval++):99;

  再如
  #define product(m,n) m*n

  调用
  result = product(5+1,6);则替换为result = 5+1*6; 所以产生了错误的结果,此时应使用()把参数括起
  #define product(m,n) (m)*(n)
  则result = product(5+1,6);则替换为result = (5+1)*(6); 所以产生了错误的结果,此时应使用()把参数括起


结论: 一般用内联函数来代替预处理器宏


技巧:
    1)给替换变量加引号
    #define MYSTR "I love you"

    cout << MYSTR ; //I love you而不是"I love you"
    如果
    cout << "MYSTR" ; //则会输出"MYSTR"而不是"I love you"

    可以这样做
    cout << #MYSTR ;  //则会输出 "I love you"即cout << "\"I love you\"";

    2)在宏表达式中连接几个参数
    如
      #define join(a,b) ab 这样不会理解为参数a的值与参数b的值的连接,即如join(10,999)不会理解为10999而是把ab理解为字符串,即输出ab
    这时可以
    #define join(a,b) a##b
      则join(10,999)就会输出10999


3)逻辑预处理器指令
 #if defined CALCAVERAGE 或 #ifdef CALCAVERAGE
   int count=sizeof(data)/sizeof(data[0]);
   for(int i=0; i<count; i++)
     average += data;
   average /= count;
  #endif

  如果已经定义符号CALCAVERAGE则把#if与#endif间的语句放在要编译的源代码内


  防止重复引入某些头文件
  #ifndef COMPARE_H
  #define COMPARE_H     注意: 这里只是定义一个没有值的符号COMPARE_H, 下面的namespace compare不是COMPARE_H的 内容,这里的定义不像是定义一个常量或宏,仅仅定义一个符号,指出此符号已定义,则就会有下面的 内容namespace compare{...
   namespace compare{
     double max(const double* data, int size);
     double min(const double* data, int size);
   }
  #endif

  比较
  #define VERSION \
   3
  因为有换行符\ 所以上句等价于 #define VERSION 3
  由此可以看出#define COMPARE_H与namespace compare是独立没有关系的两个行


  也可以这样用
  #if defined block1 && defined block2
  ...
  #endif

  #if CPU==PENTIUM4
    ...
  #endif


  #if LANGUAGE == ENGLISH
  #define Greeting "Good Morning."
  #elif LANGUAGE == GERMAN
  #define Greeting "Guten Tag."
  #elif LANGUAGE == FRENCH
  #define Greeting "Bonjour."
  #else
  #define Greeting "Hi."
  #endif
  std::cout<<Greeting << std::endl;


  #if VERSION == 3
  ...
  #elif VERSION == 4
  ...
  #else
  ...
  #endif


5)标准的预处理器宏
  __LINE__     当前源文件中的代码行号,十进制整数
  __FILE__   源文件的名称,字符串字面量
  __DATE__  源文件的处理日期,字符串字面量,格式mmm dd yyyy其中mmm是月份如Jan、Feb等 dd是01-31 yyyy是四位的年份
  __TIME__    源文件的编译 时间,也是字符串字面量格式是hh:mm:ss
  __STDC__   这取决于实现方式,如果编译器选项设置为编译标准的C代码,通常就定义它,否则就不定义它
  __cplusplus  在编译C++ 程序时,它就定义为199711L

  使用#line可以修改__FILE__返回的字符串
  如
  #line 1000    把当前行号设置为1000
  #line 1000 "the program file"      修改__FILE__返回的字符串行号改为了1000,文件名改为了"the program file"
  #line __LINE__ "the program file"  修改__FILE__返回的字符串行号没变,文件名改为了"the program file"

  cout << "program last complied at "<<__TIME__
       << " on " << __DATE__
       << endl;


6)#error
  在预处理阶段,如果出现了错误,则#error指令可以生成一个诊断 消息,并显示为一个编译错误,同时中止编译
  #ifndef __cplusplus
  #error "Error -  Should be C++"
  #endif


7)#pragma
 专门用于实现预先定义好的选项,其结果在编译器说明文档中进行了详细的解释。编译器未识别出来的#pragma指令都会被忽略


8)assert()宏
  在标准库头文件<cassert>中声明
  用于在 程序 测试一个逻辑表达式,如果逻辑表达式为false, 则assert()会终止 程序,并显示诊断 消息
  用于在条件不满足就会出现重大错误,所以应确保后面的语句不应再继续执行,所以它的应用非常灵活
  注意: assert不是错误处理 机制,逻辑表达式的结果不应产生负面效果,也不应超出 程序员的控制(如找开一个文件是否成功), 程序应提供适当的代码来处理这种情况
 assert(expression);
  assert(expression) && assert(expression2);
  可以使用#define NDEBUG来关闭断言 机制

  #include <iostream>
  #include <cassert>
  using std::cout;
  using std::endl;

  int main()
  {
     int x=0;
     int y=0;

     cout<<endl;

     for(x=0; x<20; x++)
     {
        cout<<"x= "<<x <<" y= "<<y<<endl;
        assert(x<y); //当x>=y与x==5时,就报错,并终止 程序的执行
     }
     return 0;
  }

posted @ 2008-01-03 13:59 茶 阅读(3504) | 评论 (1)编辑 收藏

仅列出标题
共4页: 1 2 3 4