忠忠的新百宝袋

做人要厚道

Archive for the 'tech' Category


一个调试的小方法

Posted by Kai on 9th October 2008

我有一个程序,是非控台程序,我需要看到程序运行过程中的一些变量的值,但是我不想用断点停下程序。因为程序是有窗口的不断运行的,所以我需要在程序运行过程中看到某些变量的值,根据看到的结果我可以做出一些操作,之后再看到结果。

今天碰巧想到了一个小方法,用起来还挺方便。实践了一下,也不麻烦。

首先,在代码里面,把要监视的数据用文件流输出到一个文件,比如watch.txt

第二,写一个相应的bash脚本,不停的检测watch.txt的大小有没有改变,如果有改变,输出watch.txt的最后几行,行数看需要。

这个bash脚本很容易,寥寥几行。

PRE=”"
NOW=”"
FILE=”output.txt”
NO=0
echo “Watch $FILE”
while [[ 1 ]];
do
PRE=$NOW
NOW=`stat $FILE | grep -i size`
if [[ "$PRE" != "$NOW" ]];
then
clear
echo ——————- $NO ——————–
cat $FILE
let NO=$NO+1
echo
else
sleep 0.2#停顿一会,避免繁忙等待占用过多的cpu资源
fi
done
接下来,需要使用Cygwin,启动一个bash shell,调用那个bash脚本就可以了。

实验了一下,效果非常的好,就仿佛在运行中把visual studio的watch窗口拿出来一样,这样我可以同时在桌面上显示调试程序的窗口和cygwin shell窗口,用鼠标操作调试程序,同时看到某些变量的值的变化。

不一定用bash,用python,perl等等其他脚本语言也能做到,而且还可以做的更加强大。我用bash只是因为bash在linux上是比较通用的脚本语言。

Posted in tech | No Comments »

毕设过程10-完结

Posted by Kai on 25th June 2008

省优我的论文没有评上,金远平老师说我做的太工程了,摘要第一句就是“本文实现了”,这个我无话可说。本来就是工程的东西,我不认为工程就代表着简单。

不过,既然省优评的是论文,不是产品,我也认了。这是别人订的标准,参加比赛的人必须遵守。我们实验室的另一个评上了省优,高老师肯定很开心。高老师我我太老实了,没有掌握写论文的要领,做人也低调,不善于表现自己的亮点。哎,这个嘛,我一直比较厚道的说。

总结,毕业论文的论文写作是需要特殊技巧的,实验做的再好,要把自己的闪光点亮出来也是需要技巧的。写作是门技术,和编程一样有难度。

高老师把承诺我的经费都给我了,真是守信的老师。

Posted in tech | 1 Comment »

毕设过程9-答辩

Posted by Kai on 10th June 2008

今天上午答辩。论文从用户手册到PPT,一共做了13天。其中的辛苦和痛苦,相比写过论文的人都能体会。答辩过程相当的自如,因为除了我没有一个人懂图像的,所以我怎么忽悠都行,哇哈哈哈。路上高老师遇到我,问我怎么样,我说“完胜”。

今天下午跑来跑去,交齐了所有材料。毕业最后一道坎总算完整的跨越。

话说我们班还真是一如既往的强势,全系11个申请系优的论文,其中9篇是我们班的。其他3个班加起来2篇。

话说我们导师还真是幸福,全系4个校优,其中2个是他带的。

话说我们导师还真是相当的幸福,全系2个去参加校优答辩以争取省优资格的论文,2个都是他带的。

Posted in tech | No Comments »

The Pragmatic Programmer

Posted by Kai on 27th April 2008

We want to see pride of ownership.”I wrote this, and I stand behind my work.” Your signature should come to be recognized as an indicator of quality. People should see your name on a piece of code and expect it to be solid, well written, tested, and documented. A really professional job. Written by a real professinal.

A pragmatic Programmer.

It took me a month to finish this book. I gotta say, this one deserves your time.

This book is the reason why I started learning Perl, Learn a text manipulation language, so said the pragmatic programmer.

Compared with lot technology books i’ve read, this one is just like talking about philosophy. Well, it’s right. We programmers consider too much about detailed techonlogy, other than how to be a reliable engineer.

pragmatic programmer

Posted in books, tech | No Comments »

学习Perl感慨设计模式的代价

Posted by Kai on 25th April 2008

这几天学了Perl,然后看懂了The Pragmatic Programer上从元数据生成结构代码那个题目的答案。有一些感慨。

我的程序使用C++,一共380行。见一个生成代码的小练习

书上的Perl答案,一共52行。短到以至于我可以把代码贴在这里。

论通用性,well,我有的通用性他的代码也有。OO不是复用的唯一手段。它甚至不是最容易最方便的手段。

我的解法是设计模式的初学者常犯的错误,把一个不需要使用设计模式的问题做的太复杂。

Perl程序使用模块来实现换语言,产生一种新语言的工作量和我的答案差不多。

learning perl

PS:Learning Perl(中文名:Perl语言入门)是很好的适合Perl入门的一本书,又称小骆驼书(因为比大骆驼书薄)。如果你是Perl初学者,选这本没错。但是如果你想精通Perl,去看大骆驼书。

Perl语法里面我最喜欢的是倒装语法。

open INFILE,”< filename.txt” or die “can not open file.”;(live or die语句)

print “I do” if &you_would_like_to;(条件倒装语句)

print “I have to do” unless &you_have_to.

这些句子在Perl里是合法的语句。酷吧!

Perl是至今为止我见过的最酷的语言。

Posted in books, tech | No Comments »

Eclipse ECIP Debugger blocked by Firewall

Posted by Kai on 23rd April 2008

我使用的Eclipse,3.3版本,Perl,5.10版本,ECIP0.66版本,PadWalker1.7版本,但是就是不能调试。今天搞了几个小时。

刚刚把防火墙关掉,发现一下子就可以调试了。又经过半个小时的折磨,在防火墙里面找到一个“Enable Secure Port Technology”的复选框,选上就没事了。

郁闷了一下午。差点就转到Python阵营去了。

weblog

Posted in perl, tech | No Comments »

毕设过程8——更好的光照

Posted by Kai on 18th April 2008

光照使用了负责的Phong模型(其实我认为Phong模型和Gouraud模型的差别是计算方法不是光照模型)。另外使用更另一种新的比较自然的颜色,得到的效果也提升了很多。

 

cadaver-Data(4-18-2008)_Time(16-7-25)_968

光照模型里带有高光参数,很多地方只是随便的设个参数,看这还可以就过了。

我考虑我的光线合成或者模糊运算的方法可能有错,因为在原本黄色的颜色上添加了一些白色的条条。

我还顺便添加了根据计算机的配置自动选择最合适的分辨率的功能,其实很简单,就是二分搜索到我需要的FPS为止,也好快,如果设FPS目标是10的话,大概1秒不到就能搞找到合适的分辨率。

Posted in c++, tech | No Comments »

C++的有趣而罕见的特性:局部类

Posted by Kai on 14th April 2008

昨天看《C++设计新思维》,看到C++有个很有趣但是很少有人用的新特性,局部类。

就是可以在函数里面定义一个类,这个类在函数外面无法访问到。

这样,配合模板就可以在常用的循环里面很方便的做出for_each循环的效果。

因为如果使用自己定义的数据结构,要使用for_each循环就得自己定义迭代子,而且在迭代器模式中,尽管有迭代子的帮助,共有的循环控制代码还是重复了。

比如:

iterator it = vector::begin();
while(it != vector::end())
{
    //do something
   it = it->next;
}

在这种模式下,对容器的遍历被抽象为迭代子的步进,但是如果需要多个处理,while循环还是要写很多次。

现有的一个方法是使用std::for_each模板,通过

std::for_each(vector::begin(), vector::end(), DoSomethingClass());

这样需要建立一个DoSomethingClass的类。

可惜C++不像Java和C#一样有匿名类的机制,那么一般的解决方法就是在外部建立一个DoSomethingClass的类。然而这样处理就向外界暴露了这个类,使得程序接口更加复杂。

在我的程序中,有这样一个功能:

for(int x = 0 ; x < x_Max; ++x)
{
    for(int y = 0 ; y < y_Max; ++y)
    {
        for(int z = 0 ; z < z_Max; ++z)
        {
            DoSomeThing();
        }
    }
    ShowProceedBar();
}
Refrush();

在好几个函数中我都有这种循环,唯一的区别就是DoSomeThingA(), DoSomeThingB(),…,这样三重循环的代码就被重复了好几次。重复是代码罪恶的源头。

而对于一个三重循环,要实现stl的iterator接口可能有点复杂。

现在可以用一个漂亮的解决方法。

首先建立一个模板函数:

template<typename Functor>
void DoEach(Functor func)
{
    for(int x = 0 ; x < x_Max; ++x)
    {
        for(int y = 0 ; y < y_Max; ++y)
        {
            for(int z = 0 ; z < z_Max; ++z)
            {
                func();
            }
        }
        ShowProceedBar();
    }
    Refrush();
}

然后根据我的需要,在原来的诸多函数的基础上,比如说:

void DoA( for…for…for (…DoSomeThingA())… );
void DoB( for…for…for (…DoSomeThingB())… );
void DoC( for…for…for (…DoSomeThingC())… );
void DoD( for…for…for (…DoSomeThingD())… );

在DoX()函数里面建立局部类,把原来的操作代码封装到局部类的operator()的定义里面去。因为局部类只在函数内部有效,所以不用担心名字冲突的问题。像这样:

void DoA()
{
    class Func
    {
    public:
        void operator()()
            {
                DoSomeThingA();
            }
    };
    DoEach(Func());
}

void DoB()
{
    class Func
    {
    public:
        void operator()()
            {
                DoSomeThingB();
            }
    };
    DoEach(Func());
}

因为class定义是在编译时处理,所以DoX在运行时实际的代码只有

void DoA()
{
    DoEach(Func());
}
void DoB()
{
    DoEach(Func());
}

 

相当于在外部定义了DoX_Functor。但是,得益于局部类的名称局部性控制,使得对与调用DoX函数的外部代码,DoX_Functor完全透明。

新的代码比原来的代码优雅,因为邪恶的重复循环代码只有一处。另外,对于DoX系列函数的调用者,什么都没有改变。可以认为我只是在函数内部做了调整,以达到减少重复的目的。实际上,在我的程序里,DoEach模板是私有成员模板函数,类的接口没有变化。

———————————————————————————–

刚刚在修改我的程序的时候发现了更酷更漂亮的做法,那就是搭配使用宏,来简化一些琐碎的工作。

#define For__Each(code); class Func \
        { \
        public: \
                void operator()() \
                { \
                        code \
                } \
        }; \
        DoEach(Func());

然后在DoA里面,只要写
void DoA()
{
        For__Each(
                DoSomeThingA();
        );
}
就可以了。

Posted in c++, tech | 1 Comment »

一个生成代码的小练习

Posted by Kai on 11th April 2008

在《程序员修炼之道》里面看到了这个题目:

Exercises 13:

Generating code from a language-neutral representation. In the input file, lines starting with ‘M’ flag the start of a message definition, ‘F’ lines define fields, and ‘E’ is the end of the message.

# Add a Product
# to the ‘no-order’ list
M AddProduct
F id    int
F name    char[30]
F order_code int
E

Generate C:

typedef struct {
    int    id;
    char    name[30];
    int    order_code;
} AddProductMsg;

Generate Pascal:

{ Add a Product }
{ to the ‘no-order’ list }
AddProductMsg = packed record
    id:        LongInt;
    name:        array [0..29] of char;
    order_code:        LongInt;
end;

今天我花了接近3个小时做这个程序,顺便练习一下最近学的设计模式。

下面是我的类图:

TargetFamily

这是输出用的类,其中使用了模板方法,工厂方法模式。

TypeFamily

这是字段的类型类,因为数组类型和原子类型输出不同,所以分开,这里也许应该用访问者模式。

CallSequence

这是调用顺序图,Type和Meta都必须通过工厂TypeResolver和MetaResolver产生实例,Type的虚礼析构函数向堆中释放自身。

其中我不满意的地方有:

1. 使用了protected访问控制,在Type的构造函数里面。protected是丑陋的。

2. 使用了friend class机制,以让工厂类能够访问MetaStrut和AtomType,ArrayType。friend机制是丑陋的。如果我做另外一个什么DerivedType,我必须在这个DerivedType里面再声明friend class,这就使得不能完全解耦。

第一个,如果Type不允许实例化的话,我也可以把Type的函数做成纯虚函数,这样就不需要使用protected保护Type了。

第二个,我没想到好的解决办法。我不能让MetaStrut、AtomType和ArrayType可以在栈上被实例化。为了使用多态,简单工厂返回的是基类的指针,所以不可以使用栈对象。使用堆对象的话,又必须在析构函数里面调用delete this。从而就不能有栈对象的存在,为了防止其他函数使用建立栈对象,我就想到把构造函数设成Private。这样建立对象的唯一机会就是在简单工厂里面,可以保证都是堆对象。

一下是我的程序的输出:

/* Add a Product */
/* to the ‘no-order’ list */
typedef struct {
    int    id;
    char    name[30];
    int    order_code;
} AddProductMsg;

{ Add a Product }
{ to the ‘no-order’ list }
AddProductMsg = packed record
    id:        LongInt;
    name:        array [0..29] of char;
    order_code:        LongInt;
end;

// Add a Product
// to the ‘no-order’ list
class AddProductMsg
{
public:
    int    id;
    char    name[30];
    int    order_code;
};

PS:这次做程序的过程中,我使用了Refactor!Pro来重构代码,使用了Extract Method,感觉很不错,这次的代码我看着也觉得有点漂亮。可惜我的Refactor!Pro是体验版,还有10天就到期了。另外,我决定以后一定要学会用flex,自己处理字符串既费时又没有意义。

Posted in c++, tech | No Comments »

重构:改善及有代码的设计

Posted by Kai on 3rd April 2008

昨天看完了《重构》,来发点读后感。

我觉得《重构》一书写的最好的是第一章,所以如果有谁感兴趣又没有那么多时间,花上1个小时琢磨一下第一章也能有很大收获的。

后面的章节我觉得作者更多的是从理论上讲重构过程中的步骤,过于细节,没有必要。须知,现在如果工程里面做重构,大都会借助自动重构工具。而大部分读者是不会去做一个自动重构工具的,所以中间章节实用价值不大。最后几章对于看过《设计模式》的人来说,也无多大作用。如果没看过《设计模式》,我想可能会有点帮助。

正如作者说所,GoF的《设计模式》指出了编码的方向,而重构告诉程序员具体的实现方法。所以,如果不看《设计模式》相关的书,光看《重构》效用也很局限。

今天在网上找到了《重构》作者的网站,还有一个叫做重构的网站。Refacting

本想找个免费好用的C++自动重构工具,但是木有发现。有个叫做Refactor!Pro的Visual Studio插件挺不错,但是不免费,而且很贵,要99美刀。Refactor!Pro有体验版,可以免费用大概1个月左右。最新的版本是3.0,已经支持VS2008了,所以我今天试用了一下,感觉很不错,界面漂亮的像Visual Studio一样。

相比较C++程序员的苦恼,Java程序员就舒服的多了。免费IDE Eclipse里面就有现成的Refacting工具,而且功能很多很强大。据说是因为C++的语法太复杂了,不能想Java那么容易的解释,所以没有重构方面没有Java发展的快。

Posted in books, tech | No Comments »

 
FireStats icon Powered by FireStats