沐枫小筑(C++)

爱老婆,要比编程多一点...

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  18 Posts :: 0 Stories :: 84 Comments :: 0 Trackbacks

公告

沐枫的个人主页

eoool.com生成

eoool.com生成

常用链接

留言簿(8)

我参与的团队

搜索

  •  

积分与排名

  • 积分 - 55995
  • 排名 - 396

最新评论

阅读排行榜

评论排行榜

2007年12月15日 #

今天安装svn服务器。上官网下载,发现windows下有一个稍微好用些的svn服务器。
下载地址: http://www.visualsvn.com/server/

这个东西有几个特色:
1. 安装和配置过程很方便(最大优点之一)
2. 自带apache/ssl/mod_dav_svn/...等模块,既小巧,又简单,也安全一些。
3. 自带MSC管理工具,可以创建用户、用户组,还可以管理多个源码库,以及配置各个路径的访问权限(最大优点之二)

通过上面下载地址,可以看到截图。不过,截图的版本稍低点。目前的版本是1.01。核心是Svn1.45,与官方同步。其实它也是为官方提供windows移植版的网站之一。

需要注意的是,这个网站提供的VisualSVN Server是免费的,而客户端VisualSVN是收费的。我们可以不用该客户端,客户端还是用TortoiseSVN/AnkhSVN之类的。 VisualSVN客户端从介绍上看,与AkuhSVN是差不多的,只不过功能上略有优点。定价是$49。
posted @ 2007-12-15 18:34 沐枫 阅读(1550) | 评论 (1)编辑 收藏

2007年11月30日 #

    从VC2003到VC2005,一直有一个很奇怪的问题。
    如下的代码:
    short s1 = 0;
    
short s2 = 2;

    s1 
+= s2;
    在这两个编译器的 /w4 四级警告打开的时候,就冒出以下的警告来:
warning C4244: “+=”: 从“int”转换到“short”,可能丢失数据
    为了消除这个警,只能将 += 拆成 = 和 +,如 s1 = s1 + s2。

    终于,这个问题在VC2008消失了。
posted @ 2007-11-30 12:50 沐枫 阅读(2175) | 评论 (7)编辑 收藏

2007年10月17日 #

    没想到汉语编程又有人开始网上对骂了。一方指另一方骗人,一方吹自已伟大。
    今天群里头有人又把它翻出来了,刚好无聊,也就发明了一个汉语编程语言,集成到visual studio 2005的IDE中,名字就叫汉语编程++,欢迎同样无聊的朋友试用。
#include "常用头文件"


整数 主函数(整数 参数数量, 字符指针 参数 是数组)
{
    整数 变量1 赋值为 
3;
    如果(变量1 大于 
0)
    {
        打印(
"可以中文编程\n");
    }

    系统命令(
"Pause");
    返回 
0;
}


    运行结果就是:“可以中文编程”
    语法呢,就是C++一样的,那个“常用头文件”的内容如下:
#define 整数 int
#define 如果 if
#define 大于 >
#define 打印 printf
#define 系统命令 system
#define 赋值为 =
#define 主函数 _tmain
#define 字符指针 _TCHAR*
#define 是数组 []
#define 返回

#include 
<tchar.h>
#include 
<iostream>

    唯一美中不足的是,#include暂时无法汉化。于是劝群里的人用这个写写情书,结果,没人响应...
    不过,#include 可以在项目属性中去掉它(C++高级选项:强制包含),或是指定编译命令参数 /FI "常用头文件" ,这样就可以去掉上面的“#include "常用头文件"”了。  
-----
以上程序在VC++2005上编译并运行通过。

附群朋友的程序:
高興不<>  19:54:59
还真有这么玩的啊
沐枫(Liny)()  19:55:02
各位朋友,咱们提供一个头文件,于是全中国人都可以用vc++2005来进行中文编程了。
风在奔跑()  19:55:05
我从来没这么玩过.
沐枫(Liny)()  19:55:19
玩玩吧,挺好玩的。
风在奔跑()  19:55:28
干脆把所有函数用中文define成一个中文编程库.
沐枫(Liny)()  19:55:30
不就是一堆#defing
沐枫(Liny)()  20:13:43
用这个写情书吧各位。
西瓜()  20:13:57
女朋友不懂程序怎么办
TLAH()  20:13:58
这样的情书...球球不会喜欢的
高興不<>  20:14:04
。。。情书里就一个弹出的对话框"欲知详情,请看代码"
西瓜()  20:14:17
球球又没出现

TLAH()  
20:19:00

#define 趁还 while
#define 那个啥 int
#define 总的来说 main
#define 买 cin
#define 卖 cout
#define 进 >>
#define 出 <<
#define 拜拜了 return
#define 去掉 -=
#define 等于 =
#define 屁 100e4
#define 我说 (
#define 是吧 )
#define 啊 a
#define 那么就 {
#define 得了 }
#define 呀 ;
#include 
<iostream>
using namespace std;

那个啥 总的来说 我说 那个啥 啊 是吧
那么就 那个啥 有钱 等于 屁 呀
趁还 我说 有钱 是吧    那么就
那个啥 多少 呀 买 进 多少 呀 卖 出 多少 呀 有钱 去掉 多少 呀
卖 出 多少 呀 得了
拜拜了 啊 呀 得了 

高興不
<>  20:19:30
最有语义的中文编程诞生了 



posted @ 2007-10-17 20:22 沐枫 阅读(4008) | 评论 (38)编辑 收藏

2007年9月27日 #

   C语言确实很优雅,整个语言的设计简洁一致。而在C++中,有一个让人诟病的问题就是变量初始化的不一致性。
   C语言中的初始化,都是用花括号进行,简单美观:

int array[] = {1,2,3,4,5};
struct Point point = {23};
struct Point arrPoint[] = 
{
  {
2,3},
  {
4,5},
  {
6,7}
};

   C++自然也兼容了C语言的初始化机制。然而,C++的Class乃至STL都不支持。它们要用不同的方式来初始化, 甚至根本不能够直接初始化, 只能使用运行时的赋值。
   比如Class:
class Param
{
public:
  
int Age;
  
int Value;
private:
  
int Level;
};

Param param 
= {2,3}; // ERROR
Param param = {2,3,4}; //ERROR
   无法初始化。而如果不初始化的话,所有的成员而处于无政府状态,这显然很不让人放心。于是,C++提供了专门用于Class的初始化方式--构造函数:
class Param
{
public:
  Param(
int x, int y)
    : x_(x), y_(y)
  {}
  Param()
    : x_(
0), y_(0)
  {}
private:
  
int x_, y_;
};

Param param(
1,2);
//
Param param;
   有了构造函数,可以在构造函数的初始化列表中对成员进行初始化。可是很明显,这里头还是有一个陷阱,默认构造初始化和非默认构造初始化的调用方式是不一致的。默认构造函数不能用括号来调用,否则编译器将会发疯:
Param param();
   它会把上面的语句看成是函数声明,而后面调用的时候就会出错,而错误信息可能会让你抓狂一下。但是这样也就算了,偏偏 new 可以接受有括号和没括号两种写法:
Param* p1 = new Param;
Param
* p2 = new Param();
   再来说说初始化列表。初始化列表,事实上,也只能支持简单的标量类型,诸如int,bool,指针之类的;复杂点的,如数组、结构,不好意思,不支持--只能在构造函数体中进行赋值。还有一个很迷糊初学者的问题是,成员初始化的顺序仅依赖于成员定义的顺序,而不是初始化列表中的顺序。

   再比如STL容器,这下好象更惨,连构造函数都帮不上忙了,除了初始化一个空的容器,或是复制一下别的容器,我们只能做用默认构造函数进行初始化。我们拿数组和vecotr做个比较:
// 数组
int arr[]={1,2,3,4};
// vector
vector<int> iarr;
// 必须在某个函数中赋初值
void init()
{
  
for(int i = 1; i <= 4++i) 
    iarr.push_back(i);
}

   再复杂一点的数据结构,那单单赋值程序就要写上老长,而且还不好看。还要记得调用。这对于仅仅是简单的设置一些初值的用途来说,太过于烦琐。

   横向比较,这次好象C++还不会太落伍,只有C和动态语言提供了初始化特性,其它支持OO高级语言好象都是学C++的。如Java, C#(注C#3.0开始提供初始化功能)...
   
   C++能不能做到简洁一致的实始化呢?
   Boost的assign库做了许多有益的工作。使用assign库,至少现在可以初始化了:
vector<int> arr = list_of(1)(2)(3)(4);   

typedef boost::tuple
<int,std::string,int> tuple;
vector
<tuple> v = tuple_list_of( 1"foo"2 )( 3"bar"4 );

map
<int,int> next = map_list_of(1,2)(2,3)(3,4)(4,5)(5,6);

stack
<string> names = list_of( "Mr. Foo" )( "Mr. Bar")( "Mrs. FooBar" ).to_adapter();
   如果是赋值,也可以简略很多:
vector<int> v;
+= 1,2,3,repeat(10,4),5,6,7,8,9;
// v = [1,2,3,4,4,4,4,4,4,4,4,4,4,5,6,7,8,9]
  不过,也仅能如此了。assign经过许多努力,也仅能支持容器的初始化,而且还不够漂亮。

   C++0x已确定提供与C一致的初始化功能。 Initialer lists Initializer Lists for Standard Containers Initializer lists WP wording 等草案就是为了这个目的服务的。
   如果使用C++0x,那么程序的初始化将变得清晰和一致:
complex<double> z = {1,2}; 
//
complex<double> z {1,2}; 
// 初始化中,有等号和无等号都是允许的,下同。
+= {2,3};

int a = {1}; 

new vector<string>{"once""upon""a""time"}; 

f( {
"Nicholas""Annemarie"} ); // 参数是两个元素的列表

return { "Norah" }; // 返回只有一个元素的列表
 
int* e {};  // 初始化为0或NULL指针

map
<string,int> anim = 

  {
"bear",4}, 
  {
"cassovary",2}, 
  {
"tiger",7
}; 

   这好象是C++欠了十多年的债吧。
   
posted @ 2007-09-27 17:39 沐枫 阅读(2656) | 评论 (6)编辑 收藏

2007年9月26日 #

    一直在使用C/C++,对于循环语句while、do while、for,对于for情有独钟,因为其简洁、清晰、灵活。访问数组类型的变量,只有for写出来的语句是最易于阅读的,如:
int arr[N] = {/**/};
for(int i = 0; i < N; ++i)
  printf(
"arr[%d] = %d\n", i, arr[i]);

    然而,这种情况,到了STL时,就有些变味了:
for(vector<MyClass>::const_iterator iter = m_vecData.begin(); iter != m_vecData.end(); ++iter)
{
    
if(!iter->IsBusy())
        iter
->DoSomeThing(param);
}
    这么长的一个for,不再给人一种清晰的感觉了。或许因为这个程序比较短,还没有太大的感觉,当回头去看自已的程序中,有不少这样的写法时,我就觉得一阵心烦。改改?
for(size_t i = 0; i < m_vecData.size(); ++i)
{
    
if(!m_vecData[i].IsBusy())
        m_vecData[i].DoSomeThing(param);
}
    不错,还是简单点好啊。但是因为这里举的是vector的例子。如果是list或是别的什么容器,就行不通了。
    其它的高级语言,都提供了foreach或是for in语句,写出来就很清晰:
foreach(item in m_vecData)
{
    
if(!item.IsBusy())
        item.DoSomeThing(param);
}
    C++是不是也可以这么简单?好象STL中也有一个for_each,试着改写一下:
struct IfNotBusyThenDoSomeThing
{
   
IfNotBusyThenDoSomeThing(const Param& param)
        : param_(param)
    {}
    
void operator() (const MyClass& item)
    {
        
if(!item.IsBusy())
            item.DoSomeThing(param_);
    }
private:
    
const Param& param_;
};

for_each(m_vecData.begin(), m_vecData.end(),
IfNotBusyThenDoSomeThing(param));
    不错,for语句简单了,但是却多了IfNotBusyThenDoSomeThing的定义,这代码可是多了好几倍。要是每个循环都要来这么一下,我还不如直接写for,要来得爽快一些。或许还有别的办法:
vector<MyClass> notBusyClass;
remove_copy_if(m_vecData.begin(), m_vecData.end(), inserter(notBusyClass, notBusyClass.begin()), mem_fun_ref(
&MyClass::IsBusy));
for_each(notBusyClass.begin(), notBusyClass.end(), bind2nd(mem_fun_ref(
&MyClass::DoSomeThing), param));
    天哪,这种写法好象更恐怖。而且,还不是每种情况都能用的:
    1. notBusyClass不能是vector<const MyClass&>,因为不能建立指向引用的指针。这就要求MyClass是可拷贝的。但就算是可拷贝的,有时候拷贝成本也是很高的。
    2. MyClass::DoSomeThing的参数不能是引用(我们常定义参数为:const Param&),因为不能定义引用的引用这种类型。
    3. 一旦出现错误,这错误信息会让人极其昏倒。

    看来单靠标准C++是不成的。Boost的lambda的库似乎很不错,用用:
    for_each(m_vecData.begin(), m_vecData.end(),
        if_then( !bind(
&MyClass::IsBusy, _1),
            bind(
&MyClass::DoSomeThing, _1, param)));
    不错,好了一些,但是还是很不好看。有没有更好的?有,boost1.34新加入的BOOST_FOREACH:
BOOST_FOREACH(cosnt MyClass& item, m_vecData)
{
    
if(!item.IsBusy())
        item.DoSomeThing(param);
}
    Oh Yeah!

    好了,问题来了,为什么C++不直接在语言中提供foreach这个功能呢?
    个人认为,原因有几点:
    1. C/C++除了数组外,没有内置的容器,因此for语句足矣。
    2. 当C++进化到STL的时候,C++标准委员会根本没空去考虑其它的。
    而其它高级语言之所以内置了foreach,就是因为它们一开始就提供了标准的容器库和迭代/枚举接口,因此提供foreach就顺理成章了。

    现在,总算C++开始考虑,由模板引入而造成的代码复杂性的问题,这的确是Cpper的福音。因此,一系列相关的提案被提交。牵涉到上面代码中的提案就有: DecltypeLambda expressions and closures for C++proposal for new for-loop。  
    其中,最符合foreach要求的就是新的for循环。采用这个语句,上面的程序就可以这么写:
for(const MyClass& item : m_vecData)
{
    
if(!item.IsBusy())
        item.DoSomeThing(param);
}

    不过,考虑到Decltype&auto提案已经被采纳,新的for-loop就不知道能不能再被采纳。因为使用Decltype&auto后,程序可以这么写:
for(auto iter = m_vecData.begin(), end = m_vecData.end(); iter != end; ++iter)
{
    if(!iter->IsBusy())
        iter->DoSomeThing(param);
}
    似乎还是复杂点是吧?但是有了decltype&auto后,foreach功能可以用程序库或宏的形式被模拟,BOOST_FOREACH就是这么做的。具体模拟的方式<<proposal for new for-loop>>提案写的很清楚了。
    同时,假如lambda提案要是能再被通过的话,那就真的要开心了:
for_each(
  m_vecData, 
  
<>(item) extern(param)
  {
    
if(!item.IsBusy())
        item.DoSomeThing(param);
  }
);
    Cool!

    不过,VC++2008倒是增加了foreach功能,不过关键字不是foreach,而是for each,这个让人有点郁闷.要用的时候最好用宏定义替换一下,免得可移植性上出现问题.

posted @ 2007-09-26 19:51 沐枫 阅读(16855) | 评论 (11)编辑 收藏

2007年8月14日 #

关于.net方面,已经有许多人在关注了,我就关注一下,VC2008方面的新东西吧。
1. 晕倒,实证后,没有增加tr1库(仅增加了tr1::hexfloat).
2. 对于模板的>>符号,中间不再需要空格了。
3. 增加了for each(T& in A){}语法--这个不算是改进吧,估计是为了与.NET一起工作的产物。

这是今天下午初步扫一眼VC2008中Native C++后的感觉。
同时,标准库已不再支持Win95/98/me和NT4了。

至于C++/CLR,一个重要的部份就是STL/CLR。
posted @ 2007-08-14 00:40 沐枫 阅读(2913) | 评论 (6)编辑 收藏

2007年7月21日 #

这是入门级的随笔,说的是函数对象的定义,使用,以及与函数指针,成员函数指针的关系。  阅读全文
posted @ 2007-07-21 21:36 沐枫 阅读(1229) | 评论 (4)编辑 收藏

2007年5月23日 #

boost 1.34 终于简化了内嵌python的支持。
还支持了python2.5。
在中文windows下用vc8编译boost的过程中,虽然仍有代码页字符警告,但是可以正常编译成功,不再象1.33.1那样造成正则表达式库不修改源码不能够编译通过的问题了。

下面的例子是从boost文档中来的:
#include <iostream>
#include 
<string>
#include 
<boost/python.hpp>
#include 
<boost/ref.hpp>
#include 
<vector>
using namespace boost::python;

void greet()
{
    
object main = import("__main__");
    
object global(main.attr("__dict__"));

    
// Define greet function in Python.
    object result = exec(
        
"def greet(a):               \n"
        
"   return 'Hello %s from Python!' % a \n",
        global, global);

    
object greet = global["greet"];

    list lst;
    lst.append(
1);
    lst.append(
2);

    
object r = greet(lst);

    std::
string message = extract<std::string>(r);
    std::cout 
<< message << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
    Py_Initialize();
    greet();
    system(
"Pause");
    
return 0;
}

BTW:
  我用vc8编译了全部的boost,然后,include加上lib目录(内仅有lib和dll文件),合计2.68GB。

posted @ 2007-05-23 12:58 沐枫 阅读(1061) | 评论 (0)编辑 收藏

2007年5月13日 #

昨天,boost终于发布了1.34版本。该版本新增加了几个内容:
1. BOOST_FOREACH 宏
  一直对于C++的iterator枚举元素造成的bad smell感到无奈,同时,许多语言都增加了foreach机制。终于,boost增加了这个枚举工具。从此,C++的枚举不再难看。如:

#define foreach BOOST_FOREACH
short array_short[] = { 123 };
foreachshort & i, array_short )
{
    
++i;
}

  BOOST_FOREACH宏大大改良了代码可读性。

  上述程序执行后,array_short的内容为:{2,3,4}。 

2. 状态图
  随着工作流(WorkFlow)的流行,Boost也加入了状态机。这对于程序结构的优化,将是一个好的补充。
3. Tr1
  随着C++0x的进展,Tr1已经被通过。下一次Boost可能将增加Tr2了。
4. Typeof 库
  C++0x中的auto的替代品。时常关心C++0x进展的人就会知道auto的作用,现在终于可以提前使用了。只是没有auto漂亮,目前也仅能如此了,毕竟它现在能工作。
5. Xpressive库
  属于C++的正则表达式库。以前都是用字串来保存正则表达式,现在终于可以用C++的表达式来写正则了。

http://www.boost.org

posted @ 2007-05-13 22:24 沐枫 阅读(1338) | 评论 (0)编辑 收藏

2006年8月8日 #

摘要:  在这里,我想向大家介绍如何进行Lua程序设计。

全文:Lua脚本入门
posted @ 2006-08-08 13:09 沐枫 阅读(1825) | 评论 (0)编辑 收藏

2006年6月29日 #

用bitset进行2进制输入输出
posted @ 2006-06-29 10:14 沐枫 阅读(2188) | 评论 (1)编辑 收藏

2006年4月6日 #

汇编语言没有我想象的那么低级,它已经具备了不少高级语言的特性,代码也变得清晰,层次清楚,易于维护了。
全文见:汇编语言的Hello World
posted @ 2006-04-06 12:05 沐枫 阅读(1046) | 评论 (1)编辑 收藏

2006年3月13日 #

  C语言的指针相当的灵活方便,但也相当容易出错。许多C语言初学者,甚至C语言老鸟都很容易栽倒在C语言的指针下。但不可否认的是,指针在C语言中的位置极其重要,也许可以偏激一点的来说:没有指针的C程序不是真正的C程序。
  然而C++的指针却常常给我一种束手束脚的感觉。C++比C语言更加强调强类型,强调类型安全,强调编译时检查。因此,对于C语言中最容易错用的指针,更是不能放过:C++的指针被分成数据指针,数据成员指针,函数指针,成员函数指针,而且不能随便相互转换。而且这些指针的声明格式都不一样:

数据指针 T *
成员数据指针 T::*
函数指针 R (*)(...)
成员函数指针 R (T::*)(...)

  尽管C++中仍然有万能指针void*,但它却属于被批斗的对象,而且再也不能“万能”了。它不能转换成成员指针。

  这样一来,C++的指针就变得很尴尬:我们需要一种指针能够指向同一类型的数据,不管这个数据是普通数据,还是成员数据;我们更需要一种指针能够指向同一类型的函数,不管这个函数是静态函数,还是成员函数。但是没有,至少从现在的C++标准中,还没有看到。

全文见 《C++指针探讨 (三) 成员函数指针

posted @ 2006-03-13 16:44 沐枫 阅读(922) | 评论 (0)编辑 收藏

2005年12月17日 #

在C/C++中,数据指针是最直接,也最常用的,因此,理解起来也比较容易。而函数指针,作为运行时动态调用(比如回调函数 CallBack Function)是一种常见的,而且是很好用的手段。

注:这一部份没什么价值,纯是为了引出下一节的内容。

请点此处阅读全文:C++指针探讨 (二) 函数指针
posted @ 2005-12-17 11:53 沐枫 阅读(1147) | 评论 (0)编辑 收藏

2005年11月30日 #

指针,在C/C++语言中一直是很受宠的;几乎找不到一个不使用指针的C/C++应用。用于存储数据和程序的地址,这是指针的基本功能。用于指向整型数,用整数指针(int*);指向浮点数用浮点数指针(float*);指向结构,用对应的结构指针(struct xxx *);指向任意地址,用无类型指针(void*)。
本文先探讨C++中用于存储各种类型数据的指针。

——全文请见:C++指针探讨 (一)数据指针
posted @ 2005-11-30 11:12 沐枫 阅读(863) | 评论 (0)编辑 收藏