博文
C/C++中利用空指针简化代码,提高效率(2008-04-14 22:16:00)
摘要:这里的写法,可以避免使用 for 循环,减少栈空间内存的使用和减少运行时的计算开销!
#include <iostream>
#include <string>
using namespace std;
void print_char(char* array[]);//函数原形声明
void main(void)
{
char* test[]={"abc","cde","fgh",NULL};//这里添加一个NULL,表示不指向任何地址,值为0
print_char(test);
cin.get();
}
void print_char(char* array[])
{
while(*array!=NULL)
{
cout<<*array++<<endl;
......
VC6.0下配置boost库使用正则表达式(2008-04-14 22:06:00)
摘要:最近做开发碰到了长字符串匹配、搜索的问题,最先想到的是使用正则表达式,简单、高效。
但是我用的开发工具是VC6.0,不支持正则表达式。
上网baidu一下,发现支持正则的库还真不少,大概有以下几种:boost,GNU,VC7带的ATL中的和微软发布的greta。
网上的朋友对boost评价不错,决定就使用是它了!
1、接下来的就是下载boost库,网上很好找。我下载的是压缩包,20多M,解压后将近100多M。
我解压的目录是D:\boost
2、然后是编译,我只要支持正则表达式就可以,因此只需要编译D:\boost\libs\regex\build目录下的文件。据说全部编译要花将近2个小时,没有验证过,在我家里的机器上编译正则表达式部分只用了不到5分钟。
网上介绍的如何编译最多的一篇文章是“VC利用boost库解析正则表达式”,如果有人能根据这篇文章编译成功不妨告诉小弟一声……
以下是我的操作:
在“运行”里输入“cmd”,打开命令提示符;
输入命令“cd D:\boost\libs\regex\build”//设置当前目录
输入命令“D:”//转到当前目录
接下来是很关键的一步:
很多文章是这样说的“输入 nmake -fvc6.mak”
但是出现了“'nmake' 不是内部或外部命令,也不是可运行的程序或批处理文件。”的错误提示。
然后你就会拼命查找原因,结果又有文章上说是环境变量没配置好,然后给出一堆“set”。
也有的文章说是运行一下visual studio安装目录下的VC98\Bin\VCVARS32.BAT文件就OK了。
你按照文章作者的方法做的,结果发现问题依旧!
以上说法都是正确的,但是说得都不是很完整,出现错误提示的根本原因就是环境变量没配置好,不识别nmake命令,配置过jdk的朋友就很容易明白。如果按照作者的要求搞一堆“set”,未免大题小作了吧,因为我们只需要用一次'nmake' 就可以解决问题了。
VCVARS3......
在同一网卡绑定二IP(2008-04-13 18:54:00)
摘要:网络结构:
有二台路由分别带有二条ADSL,组成了二个不同IP段的局域网,原本二个局域网是相互独立互不干涉的(这也是单位领导的目的)后来因为有一数据需要共享,二个IP段分别为192.168.0.0 mask 255.255.255.0 gateway是192.168.0.1;192.168.1.0 mask 255.255.255.0 gateway是192.168.1.1。
现在领导的要求是,相互还是独立,只是需要共享的二台之间进行数据共享。为此不能把IP段改成统一的,又要能使其中指定二台进行数据共享,首先,我在二台路由下的交换机之间加了一条网线,将二个局域网进行了物理联接。然后是进行IP协议的联接.
方法为:在该连接的tcp/ip协议属性里的高级中的IP设置页中的IP地址里添加一个另一个网段的IP。如下图
比如:在192.168.1.11的机子上添加上一个192.168.0.22的IP,这样二台之间立码可以共享了。
唯一的不足是:这一台机子(也只是这一台)在二个局域网内可以被大家看到。
......
关于窗口、进程和线程的初步探讨(2008-04-13 18:48:00)
摘要:A.无窗口的线程
#i nclude "stdafx.h"
INT PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpszCmdParam,INT nCmdShow)
{
MSG message;
while(GetMessage(&message,NULL,0,0)) //建立消息循环
{
TranslateMessage(&message); //翻译键盘消息
DispatchMessage(&message); //向消息处理模块发送消息
}
return 0;
}
B.默认回调函数的窗口程序
#i nclude "stdafx.h"
LRESULT CALLBACK WndProc(HWND hMainwnd, UINT message, WPARAM wParam, LPARAM lParam);
HINSTANCE myhInst;//自己定义实例句柄名称!!
char szAppName[]="WinAPIDemo";//应用程序名
char szAppTitle[]="利用应用程序接口的Windows应用程序";//程序标题
INT PASCAL WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance, LPSTR lpszCmdParam,INT nCmdShow)
{
//主窗口句柄(句柄为窗口windows中的标识)
HWND hMainwnd;
WNDCLASS myWC;
//定义窗口类
{
myWC.style =CS_HREDRAW|CS_......
浅析mfc的Cstring类的copy-on-write(写时复制)功能 (2008-04-11 08:16:00)
摘要:CString类是vc中一个有关字符串处理的类,其中用到了很多好的技法,如写时复制
技法,内存管理技法等,处理字符串的效率是很高的。
这里仅谈谈copy-on-write技法的实现。
我以vc6中的mfc为例。
或许你曾写过如下的代码:
CString str_a = "abcd";
CString str_b = str_a;
当你调试程序时,你可能发现str_a 和 str_b 这两个对象中的唯一的一个data member m_pchDATA是指向同样的一个内存地址,即字符串abcd在堆中的首地址,也即字符串abcd在内存中只有一份copy,并不是两份数据。
当你再次写下如下代码时
str_a = “efg”;
会发现str_a的m_pchDATA指向了堆中的另一块内存efg,并没有将str_b中包含的数据覆盖掉。
可是CString的内存布局只有一个data member(因为它没有继承关系,所以没有虚函数,也就没有虚函数表指针)m_pchData,指向字符串数据,我们也没看见什么引用计数的变量呀。
那么CString是如何做到这一点(copy-on-write)的呢?
原来奥秘就在于有一个叫做CStringData的结构体,定义如下(见afx.h)
struct CStringData
{
long nRefs; // reference count
int nDataLength; // length of data (including terminator)
int nAllocLength; // length of allocation
&nbs......
调试技巧之调用堆栈(2008-04-09 22:45:00)
摘要:简单介绍调试是程序开发者必备技巧。如果不会调试,自己写的程序一旦出问题,往往无从下手。本人总结10年使用VC经验,对调试技巧做一个粗浅的介绍。希望对大家有所帮助。今天简单的介绍介绍调用堆栈。调用堆栈在我的专栏的文章VC调试入门http://www.vckbase.com/document/viewdoc/?id=924提了一下,但是没有详细介绍。首先介绍一下什么叫调用堆栈:假设我们有几个函数,分别是function1,function2,function3,funtion4,且function1调用function2,function2调用function3,function3调用function4。在function4运行过程中,我们可以从线程当前堆栈中了解到调用他的那几个函数分别是谁。把函数的顺序关系看,function4、function3、function2、function1呈现出一种“堆栈”的特征,最后被调用的函数出现在最上方。因此称呼这种关系为调用堆栈(call stack)。当故障发生时,如果程序被中断,我们基本上只可以看到最后出错的函数。利用call stack,我们可以知道当出错函数被谁调用的时候出错。这样一层层的看上去,有时可以猜测出错误的原因。常见的这种中断时ASSERT宏导致的中断。在程序被中断时,debug工具条的右侧倒数第二个按钮一般是call stack按钮,这个按钮被按下后,你就可以看到当前的调用堆栈。
实例一:介绍我们首先演示一下调用堆栈。首先我们创建一个名为Debug的对话框工程。工程创建好以后,双击OK按钮创建消息映射函数,并添加如下代码: void CDebugDlg::OnOK() { // TODO: Add extra validation here ASSERT(FALSE); } 我们按F5开始调试程序。程序运行后,点击OK按钮,程序就会被中断。这时查看call stack窗口,就会发现内容如下: CDebugDlg::OnOK() line 176 + 34 bytes_AfxDispatchCmdMsg(CCmdTarget * 0x0012fe74 {CDebugDlg}, unsigned int 1, int 0, void (void)* 0x5f402a00 `vcall'(void), void ......
More Effective C++:指针与引用的区别(2008-04-08 06:50:00)
摘要:指针与引用看上去完全不同(指针用操作符’*’和’->’,引用使用操作符’.’),但是它们似乎有相同的功能。指针与引用都是让你间接引用其他对象。你如何决定在什么时候使用指针,在什么时候使用引用呢?
首先,要认识到在任何情况下都不能用指向空值的引用。一个引用必须总是指向某些对象。因此如果你使用一个变量并让它指向一个对象,但是该变量在某些时候也可能不指向任何对象,这时你应该把变量声明为指针,因为这样你可以赋空值给该变量。相反,如果变量肯定指向一个对象,例如你的设计不允许变量为空,这时你就可以把变量声明为引用。
“但是,请等一下”,你怀疑地问,“这样的代码会产生什么样的后果?”
char *pc = 0; // 设置指针为空值
char& rc = *pc; // 让引用指向空值
这是非常有害的,毫无疑问。结果将是不确定的(编译器能产生一些输出,导致任何事情都有可能发生),应该躲开写出这样代码的人除非他们同意改正错误。如果你担心这样的代码会出现在你的软件里,那么你最好完全避免使用引用,要不然就去让更优秀的程序员去做。我们以后将忽略一个引用指向空值的可能性。
因为引用肯定会指向一个对象,在C里,引用应被初始化。
string& rs; // 错误,引用必须被初始化
string s("xyzzy");
string& rs = s; // 正确,rs指向s
指针没有这样的限制。
string *ps; // 未初始化的指针
// 合法但危险
不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。
void printDouble(const double& rd)
{
cout << rd; // 不需要测试rd,它
} // 肯定指向一个double值
相反,指针则应该总是被测试,防止其为空:
void printDouble(const double *pd)
{
if (p......
快速傅里叶变换(FFT)算法C++实现代码(2008-04-08 06:46:00)
摘要:#include <math.h>
#define DOUBLE_PI 6.283185307179586476925286766559
// 快速傅里叶变换
// data 长度为 (2 * 2^n), data 的偶位为实数部分, data 的奇位为虚数部分
// isInverse表示是否为逆变换
void FFT(double * data, int n, bool isInverse = false)
{
int mmax, m, j, step, i;
double temp;
double theta, sin_htheta, sin_theta, pwr, wr, wi, tempr, tempi;
n = 2 * (1 << n);
int nn = n >> 1;
// 长度为1的傅里叶变换, 位置交换过程
j = 1;
for(i = 1; i < n; i += 2)
{
if(j > i)
{
temp = data[j - 1];
data[j - 1] = data[i - 1];
&nbs......
堆和栈的区别(2008-03-24 00:25:00)
摘要:堆和栈的区别
(http://zhidao.baidu.com/question/6415859.html)
一般认为在c中分为这几个存储区
1栈 - 有编译器自动分配释放
2堆 - 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收
3全局区(静态区),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静
态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。
- 程序结束释放
4另外还有一个专门放常量的地方。 - 程序结束释放
在函数体中定义的变量通常是在栈上,用malloc, calloc, realloc等分配内存的函数分
配得到的就是在堆上。在所有函数体外定义的是全局量,加了static修饰符后不管在哪
里都存放在全局区(静态区),在所有函数体外定义的static变量表示在该文件中有效,
不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。另外,
函数中的"adgfdf"这样的字符串存放在常量区。
比如:
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc";栈
char *p2; 栈
char *p3 = "123456"; 123456\0在常量区,p3在栈上。
static int c =0; 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); 123456\0放在常量区,编译器可能会将它与p3所指向的"12345
6"优化成一块。
}
还有就是函数调用时会在栈上有一系列的保留现场及传递参数的操作。
栈的空间大小有限定,vc的缺省是2M。栈不够用的情况一般是程序中分配了大量数组和
递归函数层次太深。有一点必须知道,当一个函数调用完返回后它会释放该函数中所有
的栈空间。栈是由编译器自动管理的,不用你操心。
堆是动态分配内存的,并且你可以分配使用很大的内存。但是用不好会产生内存泄漏。
并且频繁地malloc和free会产生内存碎片(有点类似磁盘碎片),因为c分配动态内存时
......
关于malloc和free函数的用法(2008-03-22 19:45:00)
摘要:个人总结
在C语言的学习中,对内存管理这部分的知识掌握尤其重要!之前对C中的malloc()和free()两个函数的了解甚少,只知道大概该怎么用——就是malloc然后free就一切OK了。当然现在对这两个函数的体会也不见得多,不过对于本文章第三部分的内容倒是有了转折性的认识,所以
写下这篇文章作为一个对知识的总结。这篇文章之所以命名中有个“浅谈”的字眼,也就是这个意思了!希望对大家有一点帮助!
如果不扯得太远的话(比如说操作系统中虚拟内存和物理内存如何运做如何管理之类的知识等),我感觉这篇文章应该是比较全面地谈了一下malloc()和free().这篇文章由浅入深(不见得有多深)分三个部分介绍主要内容。
废话了那么多,下面立刻进入主题================》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
一、malloc()和free()的基本概念以及基本用法:
1、函数原型及说明:
void *malloc(long NumBytes):该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针(NULL)。
关于分配失败的原因,应该有多种,比如说空间不足就是一种。
void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。
2、函数的用法:
其实这两个函数用起来倒不是很难,也就是malloc()之后觉得用够了就甩了它把它给free()了,举个简单例子:
// Code...
char *Ptr = NULL;
Ptr = (char *)malloc(100 * sizeof(char));
if (NULL == ......