要求是只用一条语句(函数体就一个分号)完成功能。要求:
不能有逗号,不能有新变量声明,不能用?:,不能用循环,不能用char int 什么什么的保留字符
cpp代码
- #include "stdafx.h"
- #include <iostream>
- #include <cstring>
-
- using namespace std;
-
-
-
-
-
-
-
-
- int func(int i,int N)
- {
- return ((i==N&&printf("%d\n",i))||(printf("%d\n",i)&&func(i+1,N)&&printf("%d\n",i+1)));
- }
-
- void main()
- {
- cout<<func(1,5)<<endl;
- getchar();
- }
本贴地址:http://bbs.yingjiesheng.com/thread-231378-1-1.htm
Tags:
yhustc On
C/C++ @ 2009-10-08 22:52:59 |
1条评论
Unicode说得简单点,看看C#和JAVA,所有的字符不管汉字还是英文,计算length的时候都是1。
这有个好处,就是跟人处理起来是一样的思路,而不是非得用机器的思维来考虑怎么处理字符串的问题。而使用ANSI字符串,英文字符是一个char,中文字符两个char,最头痛的是你还得自己根据char的取值范围来判断一下这是一个英文还是中文中的一部分,再来做决定如果取一单位的substring的话,应该怎么搞。
另外一个好处就是C/C++写出来的东西可以与COM和.NET程序可以很好的互通,因为他们都使用Unicode,如果自己也用,大家在交互字符串的时候会非常方便。
那UTF-8的时候,中文是三字节,这个是怎么回事呢。这个其实不属于Unicode与ANSI的区别了,这个是不同字符集的问题。Unicode默认是UTF-16,也就是绝大部分字符全使用固定的2字节表示。UTF-8是可变的,有的1字节,有的3字节。这个具体是怎么搞,我也还是不太清楚,也许以后用到的时候需要再进一步找些资料学习。
Windows程序中很多函数都有A和W两种结尾,A表示他需要的参数是ANSI字符串的指针,而W是宽字符也就是Unicode字符串的形式。Windows核心编程上还有例子,自己lib中的函数如何实现两种字符串的版本,思路就是只实现一个Unicode的版本,然后ANSI的调用其实是先把参数中的ANSI字符串转换成Unicode的形式,然后用Unicode版本的函数处理,返回结果后再又转换回ANSI再return。
Tags:
yhustc On
C/C++ @ 2009-09-16 18:54:06 |
没有评论
InfoTV的节目单是用XML方式从YP服务器下载的。先走HTTP协议,保存到本地的program.xml,然后解析出来,填入节目列表中。
之前测试的时候,有个问题一直没发现。现在频道变多了,问题出来了。早上新开了一个频道后,发现节目单保存的XML文件有的字节错位了,导致加载进来的频道ID的hash值是错误的。
看了看程序,发现我的下载缓冲区是1024个字节,估计是这里有问题。一次下载1024,然后下一次下载的时候,可能有一个字符被截断了,导致保存下来的是错位的乱码。utf-8一个字符是不定长的,可能是2可能是3,那么下载缓冲区大小不合适就会造成单个字符给截断,缓冲区用1024字节,使用GBK编码搞定,呵呵。
之前没有查到这个问题,是因为频道少,输出内容本身就是1024字节以内,那么一次下载就够了,这个问题无法暴露。现在频道多了,输出内容大于1024字节,需要循环多次才能下载完成。刚好遇到内容被截断了。
这件事情告诉我们,一些细节性的东西不容忽视啊。字符集害死人。
Tags:
yhustc On
C/C++ @ 2008-06-04 10:39:00 |
没有评论
昨天调程序,recvfrom接收UDP数据,修改了一下缓冲区,将数据填进来,然后程序结束时始终报这个异常。
不管用Release还是Debug,然后参照以前的程序把项目设置修改了一下,仍然不能解决。
网上搜索,都说是数组越界造成堆栈出错,问题是我没有对接收数据的缓冲区进行太多的处理啊,只有recvfrom和一个printf设计到这个buffer,百思不得其解。从MSDN上面COPY一个UDP的例子出来,运行仍然报这个错误。
早上来了到VC6里面跑一样的程序,没问题。Debug调试,没有问题。
然后将项目从VC6转换到VC2005,问题出现了。O,F*CK!
绝望之下直接运行Release目录下的EXE,不从VS启动了,测试了一下,没有问题,没有抛出任何异常。再一次的F*CK。到底是什么问题?
我猜应该是从VS启动的时候加载了一下调试用的DLL,然后如错误信息所说“它所加载的任何DLL中有bug”。所以直接启动程序不会报这个错误。
Tags:
yhustc On
C/C++ @ 2008-03-11 10:05:00 |
4条评论
7. API之位图、图标和光栅运算函数
BitBlt 将一幅位图从一个设备场景复制到另一个
CopyIcon 制作指定图标或鼠标指针的一个副本。这个副本从属于发出调用的应用程序
CopyImage 复制位图、图标或指针,同时在复制过程中进行一些转换工作
CreateBitmap 按照规定的格式创建一幅与设备有关位图
CreateBitmapIndirect 创建一幅与设备有关位图
CreateCompatibleBitmap 创建一幅与设备有关位图,它与指定的设备场景兼容
CreateCursor 创建一个鼠标指针
CreateDIBitmap 根据一幅与设备无关的位图创建一幅与设备有关的位图
CreateDIBSection 创建一个DIBSection
CreateIcon 创建一个图标
CreateIconIndirect 创建一个图标
DestroyCursor 清除指定的鼠标指针,并释放它占用的所有系统资源
DestroyIcon 清除图标
DrawIcon 在指定的位置画一个图标
DrawIconEx 描绘一个图标或鼠标指针。与DrawIcon相比,这个函数提供了更多的功能
ExtractAssociatedIcon 判断一个可执行程序或DLL中是否存在图标,或是否有图标与系统注册表中指定的文件存在关联并提取之
ExtractIcon 判断一个可执行文件或DLL中是否有图标存在,并将其提取出来
GetBitmapBits 将来自位图的二进制位复制到一个缓冲区
GetBitmapDimensionEx 取得一幅位图的宽度和高度
GetDIBColorTable 从选入设备场景的DIBSection中取得颜色表信息
GetDIBits 将来自一幅位图的二进制位复制到一幅与设备无关的位图里
GetIconInfo 取得与图标有关的信息
GetStretchBltMode 判断StretchBlt 和 StretchDIBits函数采用的伸缩模式
LoadBitmap 从指定的模块或应用程序实例中载入一幅位图
LoadCursor 从指定的模块或应用程序实例中载入一个鼠标指针
LoadCursorFromFile 在一个指针文件或一个动画指针文件的基础上创建一个指针
LoadIcon 从指定的模块或应用程序实例中载入一个图标
LoadImage 载入一个位图、图标或指针
MaskBlt 执行复杂的图象传输,同时进行掩模(MASK)处理
PatBlt 在当前选定的刷子的基础上,用一个图案填充指定的设备场景
PlgBlt 复制一幅位图,同时将其转换成一个平行四边形。利用它可对位图进行旋转处理
SetBitmapBits 将来自缓冲区的二进制位复制到一幅位图
SetBitmapDimensionEx 设置一幅位图的宽度。以一毫米的十分之一为单位
SetDIBColorTable 设置选入设备场景的一个DIBSection的颜色表信息
SetDIBits 将来自与设备无关位图的二进制位复制到一幅与设备有关的位图里
SetDIBitsToDevice 将一幅与设备无关位图的全部或部分数据直接复制到一个设备
SetStretchBltMode 指定StretchBlt 和 StretchDIBits函数的伸缩模式
StretchBlt 将一幅位图从一个设备场景复制到另一个
StretchDIBits 将一幅与设备无关位图的全部或部分数据直接复制到指定的设备场景
阅读全部内容…
Tags:
yhustc On
C/C++ @ 2007-12-23 16:00:00 |
没有评论
1. API之网络函数
WNetAddConnection 创建同一个网络资源的永久性连接
WNetAddConnection2 创建同一个网络资源的连接
WNetAddConnection3 创建同一个网络资源的连接
WNetCancelConnection 结束一个网络连接
WNetCancelConnection2 结束一个网络连接
WNetCloseEnum 结束一次枚举操作
WNetConnectionDialog 启动一个标准对话框,以便建立同网络资源的连接
WNetDisconnectDialog 启动一个标准对话框,以便断开同网络资源的连接
WNetEnumResource 枚举网络资源
WNetGetConnection 获取本地或已连接的一个资源的网络名称
WNetGetLastError 获取网络错误的扩展错误信息
WNetGetUniversalName 获取网络中一个文件的远程名称以及/或者UNC(统一命名规范)名称
WNetGetUser 获取一个网络资源用以连接的名字
WNetOpenEnum 启动对网络资源进行枚举的过程
阅读全部内容…
Tags:
yhustc On
C/C++ @ 2007-12-23 16:00:00 |
没有评论
很久以前写的东西了,既然开新的技术博客,就全转过来吧
PHP、PERL、JAVA写的分词程序到处都是,它们使用宽字符集,字母“I”和汉字“我”在计算字长时结果是一样的,C++一般的输入都不是作为宽字符集处理的,使用C++分词,如果能完成窄字符输入,但按宽字符取子串,基本上分词的问题就解决了。(别说你取子串都按2个char算一个字啊,那样的话中英文夹杂的情况下就挂了)
下面是我本科时候写C++中文分词时写的文档,可能写得不太清楚,欢迎大家评论。
1 汉字的编码,这个主要是注意一下字典和待分词的字符串使用相同的编码就行了
2 宽字符集的转换及宽字符集字符串长度的计算
有一条关键命令是 setlocale(LC_CTYPE, "");
命令讲解:后一个参数是地区编码。如果要能正常显示宽字符集,应该正确的设置地区编码。但是我们这里要完成的工作仅仅是取子句,因此可以忽略地区编码。取子句的思路是先转换成任意编码格式的宽字符集,然后从中取子句,再转换回ASCII编码的字符串。
参考命令:
setlocale(LC_CTYPE, ""); //设置宽字符集的编码
mbstowcs(wchar_t *,const char *, size_t); //ASCII编码转宽字符集
wcstombs(char *,const wchar_t *,size_t); //宽字符集转ASCII编码
wcsncpy(wchar_t *,const wchar_t *,size_t); //宽字符集的COPY
wcslen(wchar_t *); //计算宽字符集的长度 e.g. 我是yh 宽字符集长度为4
我们写一个用于宽字符集的取子串的函数
cpp代码
- char* subwstr(const char* myword,char* result,int from,int len)
- {
-
- wchar_t* pwstr=new wchar_t[100];
- wchar_t* wcs=new wchar_t[100];
-
- setlocale(LC_CTYPE, "");
- mbstowcs(wcs, myword, 99);
- wcsncpy(pwstr,wcs+from,len);
- pwstr[len]='\0';
- wcstombs(result, pwstr, 99);
-
- delete[] pwstr;
- delete[] wcs;
- return 0;
- }
到这里可以说完成了一半的工作
3 逆向最大字长匹配分词
基于字典分词。字典加载进内存还是用数据库,随便。要的仅是搜索结果,即该词在字典中有没有。
思路:对一个字符串S,从前到后扫描,对扫描的每个字,从词库中寻找最长匹配.比如假设S="我是中华人民共和国公民",词库中有"中华人民共和国","中华","公民","人民","共和国"......等词.当扫描到"中"字,那么从中字开始,向后分别取1,2,3,......个字("中","中华","中华人","中华人民","中华人民共","中华人民共和","中华人民共和国",,"中华人民共和国公"),词库中的最长匹配字符串是"中华人民共和国",那么就此切分开,扫描器推进到"公"字.
4 其它词组的识别
如果前面和后面都是词组,当中间字符串长度大于1时,默认该词是一个词组。使用两个队列保存分词结果,正确匹配的词直接加入到结果队列中;另一个队列保存待分词的字符串。比如yhustc是湖南人,使用最大匹配分词,逐级减小字长,但因为字典中都无法匹配,所以前面6个字都会单独拆开,加入到待分词队列中。扫描器推进到“湖南人”,如果字典中有这个词,那么按照这里指定的规则,“湖南人”添加进结果队列,然后检查待分词队列,字长大于1,“yhustc是”也会被加入结果队列。为了提高精度,可以加入高频词筛选的功能把诸如“我”,“是”之类的词去掉。
5 输出
分词的结果保存在一个deque中,只有一个字的词去掉,各种半角的标点符号全去掉,仅保留用于表示版本号的与数字结合的.,其它结果全保留,包括全角的标点符号。
6 关于字典。字典当然是越大分词精度越高,网上有一些字典下载,但词库太小,分词精度不高。我当时从拼音加加中导出了90多万个词条的一个词库,可惜不知道丢到哪去了,需要字典的朋友,自己找个词库大点的输入法导出字典吧。
测试结果
输入:腾讯QQ2006SP1.exe 字典中仅有QQ一个词,要求去掉文件名并能正确分词
输出:腾讯 QQ 2006 SP1
程序下载:http://d95.d.iask.com/fs/800/1/2014601bd8e513f5e1f64f153d06c27e8888499/rar/wordsplit.rar
Tags:
yhustc On
C/C++ @ 2007-12-02 15:46:00 |
4条评论
gcc最基本的用法是:gcc [options] [filenames] 其中options就是编译器所需要的参数,filenames给出相关的文件名称。
-c,只编译,不连接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
-g,产生符号调试工具(GNU的gdb)所必要的符号信息,要想对源代码进行调试,我们就必须加入这个选项。
-O,对程序进行优化编译、连接,采用这个选项,整个源代码会在编译、连接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、连接的速度就相应地要慢一些。 -O2,比-O更好的优化编译、连接,当然整个编译、连接过程会更慢。
-Idirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。C程序中的头文件包含两种情况: A)#include B)#include “myinc.h” 其中,A类使用尖括号(< >),B类使用双引号(“ ”)。对于A类,预处理程序cpp在系统预设包含文件目录(如/usr/include)中搜寻相应的文件,而对于B类,cpp在当前目录中搜寻头文件,这个选项的作用是告诉cpp,如果在当前目录中没有找到需要的文件,就到指定的dirname目录中去寻找。在程序设计中,如果我们需要的这种包含文件分别分布在不同的目录中,就需要逐个使用-I选项给出搜索路径。
-Ldirname,将dirname所指出的目录加入到程序函数档案库文件的目录列表中,是在连接过程中使用的参数。在预设状态下,连接程序ld在系统的预设路径中(如/usr/lib)寻找所需要的档案库文件,这个选项告诉连接程序,首先到-L指定的目录中去寻找,然后到系统预设路径中寻找,如果函数库存放在多个目录下,就需要依次使用这个选项,给出相应的存放目录。
-lname,在连接时,装载名字为“libname.a”的函数库,该函数库位于系统预设的目录或者由-L选项确定的目录下。例如,-lm表示连接名为“libm.a”的数学函数库。 上面我们简要介绍了gcc编译器最常用的功能和主要参数选项,更为详尽的资料可以参看Linux系统的联机帮助。
假定我们有一个程序名为test.c的C语言源代码文件,要生成一个可执行文件,最简单的办法就是: gcc test.c 这时,预编译、编译连接一次完成,生成一个系统预设的名为a.out的可执行文件,对于稍为复杂的情况,比如有多个源代码文件、需要连接档案库或者有其它比较特别的要求,就要给定适当的调用选项参数。再看一个简单的例子。 整个源代码程序由两个文件testmain.c 和testsub.c组成,程序中使用了系统提供的数学库,同时希望给出的可执行文件为test,这时的编译命令可以是: gcc testmain.c testsub.c ?Clm ?Co test 其中,-lm表示连接系统的数学库libm.a,这个过程可以用图12-1框图描述。
gcc的错误类型及对策
gcc编译器如果发现源程序中有错误,就无法继续进行,也无法生成最终的可执行文件。为了便于修改,gcc给出错误信息,我们必须对这些错误信息逐个进行分析、处理,并修改相应的语言,才能保证源代码的正确编译连接。
gcc给出的错误信息一般可以分为四大类,下面我们分别讨论其产生的原因和对策。
第一类:C语法错误 错误信息:文件source.c中第n行有语法错误(syntex errror)。这种类型的错误,一般都是C语言的语法错误,应该仔细检查源代码文件中第n行及该行之前的程序,有时也需要对该文件所包含的头文件进行检查。有些情况下,一个很简单的语法错误,gcc会给出一大堆错误,我们最主要的是要保持清醒的头脑,不要被其吓倒,必要的时候再参考一下C语言的基本教材。
第二类:头文件错误 错误信息:找不到头文件head.h(Can not find include file head.h)。这类错误是源代码文件中的包含头文件有问题,可能的原因有头文件名错误、指定的头文件所在目录名错误等,也可能是错误地使用了双引号和尖括号。
第三类:档案库错误 错误信息:连接程序找不到所需的函数库,例如: ld: -lm: No such file or directory 这类错误是与目标文件相连接的函数库有错误,可能的原因是函数库名错误、指定的函数库所在目录名称错误等,检查的方法是使用find命令在可能的目录中寻找相应的函数库名,确定档案库及目录的名称并修改程序中及编译选项中的名称。
第四类:未定义符号 错误信息:有未定义的符号(Undefined symbol)。这类错误是在连接过程中出现的,可能有两种原因:一是使用者自己定义的函数或者全局变量所在源代码文件,没有被编译、连接,或者干脆还没有定义,这需要使用者根据实际情况修改源程序,给出全局变量或者函数的定义体;二是未定义的符号是一个标准的库函数,在源程序中使用了该库函数,而连接过程中还没有给定相应的函数库的名称,或者是该档案库的目录名称有问题,这时需要使用档案库维护命令ar检查我们需要的库函数到底位于哪一个函数库中,确定之后,修改gcc连接选项中的-l和-L项。 排除编译、连接过程中的错误,应该说这只是程序设计中最简单、最基本的一个步骤,可以说只是开了个头。这个过程中的错误,只是我们在使用C语言描述一个算法中所产生的错误,是比较容易排除的。我们写一个程序,到编译、连接通过为止,应该说刚刚开始,程序在运行过程中所出现的问题,是算法设计有问题,说得更玄点是对问题的认识和理解不够,还需要更加深入地测试、调试和修改。一个程序,稍为复杂的程序,往往要经过多次的编译、连接和测试、修改。下面我们学习的程序维护、调试工具和版本维护就是在程序调试、测试过程中使用的,用来解决调测阶段所出现的问题。
Tags:
yhustc On
C/C++ @ 2005-12-09 15:00:00 |
没有评论
最新评论