九天雁翎的博客
如果你想在软件业获得成功,就使用你知道的最强大的语言,用它解决你知道的最难的问题,并且等待竞争对手的经理做出自甘平庸的选择。 -- Paul Graham

为学习APUE(Unix环境高级编程)偷懒,而写的脚本,基本上相当于一个简单的工程创建脚本了

 首先我单独建了一个目录用来保存学习时需要的目录,将此脚本拷贝到这个目录下面,以后每次以一个参数运行脚本,就会自动创建目录,cpp文件,makefile文件,需要做的就是进入此目录,然后修改cpp文件,然后make,enjoy it!呵呵,说实话,自从学习了bash以后,才越来越觉得linux并不是一个复杂难用的系统。

D:/ubuntu/apue/ctapue.sh.html 1 #!/usr/bin/env bash
 2 dir=apue$1
 3 file=${dir}/apue${1}.cpp
 4
makefile=${dir}/Makefile
 5
 6 if [ -d ${dir} ]
 7 then
 8     echo "the path ${dir} is exist."
 9     exit 1
10 else
11     mkdir ${dir}
12 fi
13
14 # Create the src
file

15 cat >${file} <<end-of-file
16
#include <stdio.h>
17 #include "../apue.h"
18
19
20 int main(int argc, char*
argv[])

21 {
22
23
24     exit(0);
25 }
26
27 end-of-file
28
29 #
Create the makefile

30 cat >${makefile} <<end-of-makefile
31
src=apue${1}.cpp
32 ob=test
33 /${ob} : /${src}
34     g++ -Wall -g -o /${ob} /${src}
35
36 end-of-makefile

阅读全文....

一天一个C Run-Time Library 函数 (11) bsearch

 

一天一个C Run-Time Library 函数  (11)  bsearch

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

msdn:

Performs a binary search of a sorted array. A
more secure version is available; see
bsearch_s.

void
*bsearch(

   const void *key,

   const void *base,

   size_t num,

   size_t width,

   int ( __cdecl *compare ) ( const void *, const
void *)

);

 

 

测试程序:(来自MSDN)

#include <search.h>

#include <string.h>

#include <stdio.h>

 

int compare( char **arg1, char **arg2 )

{

    /* Compare all of both strings: */

    return _strcmpi(
*arg1, *arg2
);

}

 

int main( void )

{

    char *arr[]
= {"dog", "pig",
"horse", "cat",
"human", "rat",
"cow", "goat"};

    char **result;

    char *key
= "cat";

    int i;

 

    /* Sort using Quicksort algorithm: */

    qsort( (void *)arr, sizeof(arr)/sizeof(arr[0]), sizeof( char * ), (int (*)(const

       void*, const void*))compare );

 

    for( i
= 0; i < sizeof(arr)/sizeof(arr[0]); ++i
)    /* Output
sorted list */

       printf( "%s ", arr[i] );

 

    /* Find the word "cat" using
a binary search algorithm: */

    result = (char **)bsearch( (char *) &key,
(char *)arr,
sizeof(arr)/sizeof(arr[0]),

       sizeof( char * ), (int (*)(const void*, const void*))compare );

    if( result
)

       printf( "/n%s found at %Fp/n", *result, result
);

    else

       printf( "/nCat not found!/n" );

}

说明:

bsearch又是一个看起来相当有用,但是其实我却一次都没有在实际工作中碰到需要用的函数。。。。二分查找是算法教学的经典内容,呵呵

实际中我还真没有碰到这样的需要,因为碰到需要快速查找的时候一般都用map搞定了。。。人哪。。。才发现用C++也是会越来越懒的。。。。。因为有STL吗,所以map用的不亦乐乎,早完了C语言中该怎么来实现类似效果了。其实就算是想要实现我也很可能是用C++算法库的binary_search吧。

 

 

实现:

MS:

gcc:

对于这样经典的算法好像gccMS终于没有办法不一致了,事实上也是如此,两者几乎没有任何区别,其实现可以在任何关于算法的书籍上找到。

 

效率测试:

见以前有人说过C++的二分查找会比C语言的快,这是很多用C++的人证明C++不比C语言慢的一个例证。但是实际上,我也一直认为,不用其他非C语言特性的东西,为啥C++会比C语言慢呢?除非硬是碰到喜欢用类来描述这样算法的人吧。

 

相关函数:

qsort,不先排序,二分查找可是没有办法进行的

 

个人想法:

非常标准的C语言函数,通用性非常好。最后,我越来越懒了,并且发现这样写下去已经比较脱离我当时的想法了。。。。。现在每天工作回来还真的是很辛苦,脑袋都一直比较痛的感觉。。。。呵呵,郁闷啊。另外,再一次证明了我的恒心和毅力都是很有问题的。于是我找到了又一个来拖延此专题的借口,那就是我发现我现在去学习关于数据结构和算法还有Unix环境高级编程等书的话,实际意义更大。。。。。。。另外,对于多弄弄lua,python也是很有益处,没有想到C语言函数库的函数这么多,这么杂,这么多我完全就没有用过。。。。。用C++的人(比如我),常常将自己使用的语言称为C/C++,似乎表示自己用C++,就一直象在用C一样,自己懂C++也就懂C,不过,其实两者的区别,比我想的要大的多.因为C++有了太多特性,所以很多C语言的相关特性难免都被丢在了被遗忘的角落了.

 

 

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....

一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现(2) IntCell类


一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现2
IntCell

write by 九天雁翎(JTianLing) --
blog.csdn.net/vagrxie

 

《数据结构与算法分析c++描述》 Mark Allen Weiss 人民邮电大学出版 中文版第8面,图1-5,一个最最简单的类

刚开始都是太简单没有技术含量的东西,这样也好,不至于把我吓到,毕竟lua学了已经4个月了,python学了已经2个月了都没有怎么用,而sh虽然最近才学,但是实践的也是这么少。。。。。唯一已经不用思考语法的就是C++了吧。。。呵呵C++和汉语一样都是我的“母语”,虽然全世界人都说他复杂,但是用了这么久也就习惯了。

python就像英语,本身语法比较简单,但是学的比较晚,(相对于汉语/C++),所以暂时不能完全体会它的好处,但是学的时间越久你就会越喜欢:)最最让人郁闷的是词汇(库)丰富的让你想哭,要掌握全太难了。呵呵平时虽然看的多,却说/写的少。

lua就像是日语吧,虽然学过,知道其基本的发音(语法),但是却从来不说(不写代码),最多丢几句(写几段)最最简单的东西。

bash就像是韩语,想去学,但是看着头晕,奇形怪状的字符(语法)让人不得其要领。


以下为实现部分:

CPP:
书上已有实现。



LUA:

 1
#!/usr/bin/env
lua

 2
 3 IntCell = { storedValue = 0 }
 4
 5 function IntCell:new(orig)
 6     if type(orig)
== "number"
 7     then
 8         o
= {}
 9         o.storedValue
= orig
10     else
11         o
= orig or {}
12     end
13     setmetatable(o, self)
14     self.__index =
self
15     return o
16 end
17
18 function IntCell:read()
19     return self.storedValue
20 end
21
22 function IntCell:write(x)
23     self.storedValue

= x
24 end
25
26 -- test code
27 -- new IntCel
and read and write

28 a = IntCell:new()
29 print ("a:" .. (a:read()))
30 a:write(10)
31 print ("a:" .. (a:read()))
32
33 -- create
IntCell from a

34 b = IntCell:new(a)
35 print ("b:" .. (b:read()))
36
37 -- create
IntCell from a number

38 c = IntCell:new(100)
39 print ("c:" .. (c:read()))

PYTHON:

 1
#!/usr/bin/env
python

 2
 3 class IntCell(object):
 4     def __init__(self,
orig = 0):
 5         self.storedValue
= orig
 6     def read(self):
 7         return self.storedValue
 8     def write(self,x):
 9         self.storedValue
= x
10
11 # Test Code
12 def Test():
13     a = IntCell()
14     print "a:" +
str(a.read())
15     a.write(10)
16     print "a:" +
str(a.read())
17
18     b = IntCell(100)
19     print "b:" +
str(b.read())
20
21 if __name__ == '__main__':
22     Test();
23
24         
25

BASH:

1 没有类的概念。。。也没有办法像lua一样模拟出来(就我所知)

 write by 九天雁翎(JTianLing)
-- www.jtianling.com

 

阅读全文....

一天一个C Run-Time Library 函数 (10) atol,atof,atoi, ltoa , itoa,

 

一天一个C Run-Time Library 函数 (10) atol,atof,atoi, ltoa , itoa,

 

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

msdn:

Convert strings to double (atof), integer (atoi,
_atoi64), or long (atol).

double
atof(

   
const char *
string

);

 

int
atoi(

   const
char *
string

);

 

_int64
_atoi64(

const
char *
string

);

 

long
atol(

const
char *
string

);

Converts a long
integer to a string. These functions are deprecated because more secure
versions are available; see
_ltoa_s, _ltow_s.

char *_ltoa(

   long value,

   char *str,

   int radix

);

wchar_t *_ltow(

   long value,

   wchar_t *str,

   int radix

);

template <size_t size>

char *_ltoa(

   long value,

   char (&str)[size],

   int radix

); // C++ only

template <size_t size>

wchar_t *_ltow(

   long value,

   wchar_t
(&
str)[size],

   int radix

); // C++ only

Converts a
long integer to a string. These functions are deprecated because more secure
versions are available; see
_ltoa_s, _ltow_s.

char *_ltoa(

   long value,

   char *str,

   int radix

);

wchar_t *_ltow(

   long value,

   wchar_t *str,

   int radix

);

template <size_t
size>

char *_ltoa(

   long value,

   char (&str)[size],

   int radix

); // C++ only

template <size_t
size>

wchar_t *_ltow(

   long value,

   wchar_t (&str)[size],

   int radix

); // C++ only

 

 

测试程序:

原谅我再偷懒一次

说明:

这一族函数的使用就看个人的习惯而异了,我个人使用的不是太多,除了一些不可避免的情况以外。

一般来说,sprintf可以完成大多数从整数到字符串的转换,转换很多的时候stringstream也是我常用并且更喜欢用的。从字符串到整数的方法好像就只能靠这些函数了。

记得就前两天看公司的代码,以前有个兄弟特别喜欢用这些函数,连对话框的中各类空间的获取一律都是先获取字符串,然后转换成整数。。。。。可能是不知道有类似GetDlgItemInt之类的接口吧。。。。

实现:

MS:

浮点数我没有找到源码。

整数的都通过一个更复杂的函数

static unsigned long __cdecl strtoxl (

        _locale_t
plocinfo,

        const char *nptr,

        const char **endptr,

        int ibase,

        int flags

        )

来实现。随便看了一眼,就像我个人想实现的话会用的方法一样,从字符串到整数,我应该会通过一个一个字符的计算与’0’字符的ascII值的差,然后相应其位置的乘以10^n,累加到一个整数吧。

整数到字符串可能就是上面方式的反过来。。。。假如不让用sprintf等函数时。(这个我没有看源码了,应该差不多)

 

gcc:

随便看了一下,也差不多

 

效率测试:

 

相关函数:

windows中有一些例如itow等,gcc由于支持C99C99中的long long类型也有支持,lltoa等。

个人想法:

想起一个大牛Lippman说过的话,假如C++抛弃了C那么多的整数类型的话,那么重载函数的负担会小得多。。。。。。。。事实就是这样。

这类函数就是典型的例子。不仅仅是重载麻烦了,并且哪怕一个简单的关于整数的函数,都需要实现很多种,并且在C中需要很多的名字。。。。还好有一定规律。

windows中甚至实现了关于double的此类函数,呵呵,浮点都有两种。

但是,反过来说,当在C++中还有那么多人需要精确的控制自己需要的整数大小,甚至有的时候根本就不是整数,需要的仅仅是一个确定大小的缓存(或空间)时,不同的整数就不可避免。。。。。其实,除非C++将所有的整数全部整合到integer然后将目前用于内存等精细操作的整形放在诸如BYTEWORD,DWORD中去实现也是不错的选择。。。。当然,很多时候,我们还是需要苛刻的对空间进行要求,对于一个表示类型的变量用unsigned char,对于一个不会大于65535的整数用unsigned short时,(我们公司写游戏和服务器的时候都是这样),这些想法可能永远不会实现。

记得,以前看到mysql的一份文档中,mysql的开发人员甚至以自己的整数类型比较多而感到自豪(也许不是自豪吧),进行了类似这样描述,mysql有丰富的整数类型,这样你可以使用更适合你的整数,在数据很大时,这可以为你省下很大的空间。。。。。。。。。。。the same in C/C++.......................

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....

人类是在偷懒中进步的,用一个windows批处理解决4个脚本到html的转换+更多

 

人类是在偷懒中进步的,用一个windows批处理解决一切

write by 九天雁翎(JTianLing) -- www.jtianling.com

相当的郁闷啊,本来写了很多东西了,一步一步分析我是怎么偷懒的。。。结果因为误点了firefox的一个按钮,什么东西都没有了,血的教训啊,我再也不在线写东西了。

首先,鉴于没有现成的很好的方法来为我的lua,python,bash脚本色彩鲜艳一点,并且缩进也很符合要求,我本来是想在ubuntu下面用一个脚本来通过vim2html实现所有我想要的功能,结果发现vim在控制台下生成的东西颜色都不太好。毕竟那里是颜色深的低为主的世界。(别说gvim,我没有装X11,更没有在编译vim的时候加上GUI选项)。

于是只好放到windows中来做了,就昨天的效果,虽然操作麻烦了点,其实效果还是很不错的:)

既然学了那么多脚本技术,批处理更是不再话下了吧,虽然没有系统学过,搞了几篇教程就上了。

解决一次转换4个文件的方法很简单,脚本如下:

set CPP=cpp/dsaa%1.cpp
set LUA=lua/dsaa%1.lua
set PY=py/dsaa%1.py
set SH=sh/dsaa%1.sh
rem 
没有用start是为了保证一个一个执行
gvim -c ":syntax on|:colo
default|:TOhtml"
 -c ":w|:qa" %CPP%
gvim -c ":syntax on|:colo
default|:TOhtml"
 -c ":w|:qa" %LUA%
gvim -c ":syntax on|:colo
default|:TOhtml"
 -c ":w|:qa" %PY%
gvim -c ":syntax on|:colo
default|:TOhtml"
 -c ":w|:qa" %SH%

 

目的是达到了,但是。。。。我还是需要一个一个粘贴复制到文章中。。。我还是懒的做啊。。。。生成一个文件多好啊,直接将所有生成的文件重定向输出到一个文件中就得了(还好bat也有重定向)

set OB=dsaa%1.html

echo CPP: >>
%OB%
echo LUA: >>
%OB% 
echo PYTHON: >>
%OB% 
echo BASH: >>
%OB% 

 

作为一个懒的出奇的人。。。。我还是不满意,每个代码中间没有说明文字啊。。。到时候这样肯定不行,还得手工添加?我才懒的做呢。。。。于是新的偷懒方式诞生了,每个代码段前加上标题说明啊。直接加上文字,可以实现,没有问题,效果不好。(我是有追求的懒人)

首先这竟然是分段的说明,起码也算个小标题,需要写大点吧。没错,既然是html文件,嵌入html格式的东西指定大小就得了啊,说起来简单实现起来难。因为echo没有办法支持带<的东西,用了””号是没有问题,但是又污染了生成的文件。最后通过很扭曲的方式完成了。看了完整的脚本后你就知道了:

 

1 set CPP=cpp/dsaa%1.cpp
 2 set LUA=lua/dsaa%1.lua
 3 set PY=py/dsaa%1.py
 4 set SH=sh/dsaa%1.sh
 5 set OB=dsaa%1.html
 6 rem 
以下的两个变量我本来想要减少输入的,但是竟然不好用,用了""界定就影响html,不用windows不准
 7 rem 
直接在echo后面输入也不行,于是用同名的相同内容的文件代替了
 8 set HEAD="<html>
<br><br><br><font size="
+3">"
 9 set TAIL="<font><br><br>
</html>"

10
11 rem 
没有用start是为了保证一个一个执行
12 gvim -c ":syntax
on|:colo default|:TOhtml"
 -c ":w|:qa" %CPP%
13 gvim -c ":syntax
on|:colo default|:TOhtml"
 -c ":w|:qa" %LUA%
14 gvim -c ":syntax
on|:colo default|:TOhtml"
 -c ":w|:qa" %PY%
15 gvim -c ":syntax
on|:colo default|:TOhtml"
 -c ":w|:qa" %SH%
16
17 rem 
所有部分的头
18 type head
>>%OB%
19 type allhead
>%OB%
20 type tail >> %OB% 
21
22 rem cpp
部分
23 type head
>>%OB%
24 echo CPP: >> %OB%
25 type tail >> %OB% 
26 type %CPP%.html >>
%OB%
27
28 rem lua
部分
29 type head >> %OB%
30 echo LUA: >> %OB% 
31 type tail >> %OB% 
32 type %LUA%.html >>
%OB%
33
34 rem python
部分
35 type head >> %OB%
36 echo PYTHON: >> %OB% 
37 type tail >> %OB% 
38 type %PY%.html >>
%OB%
39
40 rem bash
部分
41 type head >> %OB%
42 echo BASH: >> %OB% 
43 type tail >> %OB% 
44 type %SH%.html >>
%OB%

 

 

最后,以前可能需要多次用gvim打开文件,并且改变颜色(因为我默认的是desert,是黑色背景的,不改不行,我也不希望平时就用default),然后输入:TOhtml转换,然后保存退出,然后开始下一个。。。。。。全部转换完后再一个一个复制到文章中。。。。

 

现在仅仅需要在控制台输入dsaa xxx,然后一次复制到文章的末尾就全部搞定了:)呵呵,懒人的办法啊。。。。想起以前某人说过:人类是在偷懒中进步的。。。深有体会,但是偷懒不是懒得睡觉,而且去想偷懒的好办法。。。做一个新时代的有追求的懂得偷懒的好青年:)

 

效果也贴一下,除了cpp文件,就是昨天的文章各个代码,效果不错吧:)呵呵

 

 

write by 九天雁翎(JTianLing)
-- www.jtianling.com

以下为实现部分:

CPP:

 1
#ifndef
__JT_MATRIX_H__

 2 #define
__JT_MATRIX_H__

 3
 4
 5 class CJTMatrix
 6 {
 7 public:
 8     CJTMatrix();
 9     CJTMatric(CJTMatrix
*
10     ~CJTMatrix();
11
12     Transpose();
13
14 };
15
16
17
18
19
20
21
22
23
24
25
26 #endif

LUA:

 1
function f(x)
 2     if (x == 0)
 3     then
 4         return 0;
 5     else
 6         return 2 *
f(x -1) + x * x;
 7     end
 8 end
 9
10 -- Test code
11 print(f(1))
12 print(f(2))
13 print(f(3))
14 print(f(4))
15     

PYTHON:

 1
def
 f(x):
 2     'a easy recursive funtion'
 3     if x == 0:
 4         return 0
 5     else:
 6         return 2 * f(x -1) + x * x
 7
 8
 9 # test code
10 print f(1)
11 print f(2)
12 print f(3)
13 print f(4)
14

BASH:

 1
#!/bin/bash
 2
 3 function f
 4 {
 5     local number="$1"
 6     if [ $number = 0 ]
 7     then
 8         ret=0
 9     else
10         let "decrnum = number - 1"
11         f
$decrnum
12         let "ret = $? * 2 + $1 * $1"
13     fi
14
15     return $ret
16 }
17
18 for i in 1 2 3 4
19 do
20     f i
21     echo $?
22 done
23

阅读全文....

一天一个C Run-Time Library 函数 (9) atexit


一天一个C Run-Time Library 函数 9 atexit

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

msdn:

Processes the specified function at exit.

int
atexit(

   void (__cdecl *func )( void )

);

 

 

 

测试程序:

#include
<stdlib.h>

#include
<stdio.h>

 

void fn1(
void ), fn2( void ), fn3( void ), fn4( void );

 

int main(
void )

{

   atexit( fn1 );

   atexit( fn2 );

   atexit( fn3 );

   atexit( fn4 );

   printf( "This is executed
first./n" );

}

 

void fn1()

{

   printf( "next./n" );

}

 

void fn2()

{

   printf( "executed " );

}

 

void fn3()

{

   printf( "is " );

}

 

void fn4()

{

   printf( "This " );

}

 

说明:

这个函数有点像一个类的析构函数。就是在程序结束的时候调用你指定的函数,按照类似堆栈的先进后出原则调用。呵呵,貌似很有用,其实从来没有用过,就我的想法可以在这里清理一下一些全局的变量,但是实际上因为类用的多,全局变量都等进程退出的时候自动析构处理了,全局打开的文件句柄也从来没有用过,一般起码放在类中,类析构的时候也会自动关闭了,所以实际我还真不太清楚什么时候需要用到这样的函数,也许仅仅是可以多提供一条更好的路径罢了。。。。也许是因为这毕竟是C语言的库,C语言的全局变量,或者全局的文件句柄可能就只能通过这样的方式来保证销毁或关闭了。

 

实现:

MS:

还真没有看懂。。。。。。

其实最主要不懂的就是以前看文件操作底层也会用到的一对函数,_encode_pointer_decode_pointer

 

gcc:

用了全局的名叫__exit_funcs链表,来不断链接你输入的函数,甚至我看到了一个可以输入参数的实现,atexit就是通过给定void参数通过那个实现来完成的。实际调用函数的时候就是在exit函数中先调用。这里顺便说一句,_exit是不调用atexit指定函数的退出方式,exit是调用atexit的退出方式。实际上,exit函数中仅仅是先执行了atexit指定的函数,然后再调用了_exit

下面贴出那个有参数调用的实现

int __cxa_atexit (void (*func) (void *), void *arg, void *d)

{

    struct exit_function
*new = __new_exitfn
();

 

    if (new
== NULL)

       return -1;

 

#ifdef PTR_MANGLE

    PTR_MANGLE (func);

#endif

    new->func.cxa.fn = (void (*) (void *, int)) func;

    new->func.cxa.arg = arg;

    new->func.cxa.dso_handle
= d;

    atomic_write_barrier ();

    new->flavor
= ef_cxa;

    return 0;

}

 

 

 

效率测试:

 

相关函数:

exit,_exit

 

个人想法:

虽然不知道这3个函数是否标准,但是就实现情况来看,放心用应该是没有问题的。另外,在APUE(Unix环境高级编程)中推荐的进程终止方式不是通过我们习惯的常用的return方式,而是用exit函数结束的方式。这点倒是和《windows核心编程》的作者对于在windows下进程退出的方式有出入,在这本书中作者说进程最佳的退出方式就是return.

具体的原因我也不太清楚,APUE中倒是有一些描述,但是看了很久了,现在忘了,《windows核心编程》作者对于推荐使用return的描述主要是和windows中的TerminateProcessExitProcessAPI作为对比的,没有提及exit.

 

 

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....

关于strcpy的问题,解释一下为什么VS中标准的方法不用memcpy实现

原文:http://blog.csdn.net/youyouzhishen/archive/2008/11/02/3207836.aspx

 


#include <cstring>

using namespace std;

 

inline char* myStrcpy(char* apszDest, char* apszSrc)

{

    memcpy(apszDest, apszSrc, strlen(apszSrc) + 1);

    return apszDest;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

    char lszSrc[] = "GOD, I'm a test string./n";

    char lszDest[256];

 

    printf("%s",myStrcpy(lszDest, lszSrc));

    printf("%s",strcpy(lszDest, lszSrc));

 

    return 0;

 

}


 

 

 


 

 

其实strcpy实现成我上面写的那样一样也可以实现strcpy,并且平均效率似乎要更高。这种错觉来自于debug时看到的strcpy的源代码(K&R中,一般的笔试题也广为通用此源代码)

其实到最近才知道,debug时可以看到strcpy的实现,memcpy一般情况下比strcpy那样的实现效率要高,这是很明显的,哪怕字符数量比较小,memcpy起码也不输给strcpy,但是,事实上,在优化后的release汇编代码就能发现,其实strcpy这样常用的函数(虽然是C Runtime Library的函数),但是编译器实际是做了优化的,这些叫做内部函数(中文版VS2005标准译法),直接就通过strcpy生成了汇编代码,所以实现上就没有必要使用memcpy了,见下面的汇编代码。

 

 

    printf("%s",myStrcpy(lszDest, lszSrc));

00401026 8D 44 24 08      lea         eax,[esp+8]

0040102A A4               movs        byte ptr es:[edi],byte ptr [esi]

0040102B 8D 50 01         lea         edx,[eax+1]

0040102E 8B FF            mov         edi,edi

00401030 8A 08            mov         cl,byte ptr [eax]

00401032 83 C0 01         add         eax,1

00401035 84 C9            test        cl,cl

00401037 75 F7            jne         wmain+30h (401030h)

00401039 2B C2            sub         eax,edx

0040103B 83 C0 01         add         eax,1

0040103E 50               push        eax 

0040103F 8D 44 24 0C      lea         eax,[esp+0Ch]

00401043 50               push        eax 

00401044 8D 4C 24 2C      lea         ecx,[esp+2Ch]

00401048 51               push        ecx 

00401049 E8 26 08 00 00   call        memcpy (401874h)

0040104E 8B 35 A0 20 40 00 mov         esi,dword ptr [__imp__printf (4020A0h)]

00401054 8D 54 24 30      lea         edx,[esp+30h]

00401058 52               push        edx 

00401059 68 10 21 40 00   push        offset string "%s" (402110h)

0040105E FF D6            call        esi 

00401060 83 C4 14         add         esp,14h

    printf("%s",strcpy(lszDest, lszSrc));

00401063 33 C0            xor         eax,eax

00401065 8A 4C 04 08      mov         cl,byte ptr [esp+eax+8]

00401069 88 4C 04 24      mov         byte ptr [esp+eax+24h],cl

0040106D 83 C0 01         add         eax,1

00401070 84 C9            test        cl,cl

00401072 75 F1            jne         wmain+65h (401065h)

00401074 8D 44 24 24      lea         eax,[esp+24h]

00401078 50               push        eax 

00401079 68 10 21 40 00   push        offset string "%s" (402110h)

0040107E FF D6            call        esi 

 

没有见过strcpy的汇编代码前。。。。哪想的到原来这么简单

阅读全文....

一个无聊男人的疯狂《数据结构与算法分析-C++描述》学习笔记 用C++/lua/python/bash的四重实现(1) f(x) = 2f(x-1) + x^2

 

一个无聊男人的疯狂数据结构学习(1 f(x) = 2f(x-1) + x^2

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

《数据结构与算法分析c++描述》 Mark Allen Weiss 人民邮电大学出版 中文版第6面,图1-2,一个递归函数

C++:

书上已有实现。这里就不贴了,对于没有书的人来说,f(x) = 2f(x-1) + x * x的说明好像也足够了。

 

lua:

1 function f(x)
 2     if (x == 0)
 3     then
 4         return 0;
 5     else
 6         return 2 * f(x -1) + x * x;
 7     end
 8 end
 9
10 -- Test code
11 print(f(1))
12 print(f(2))
13 print(f(3))
14 print(f(4))
15    

python:

1 def f(x):
 2     'a easy recursive funtion'
 3     if x == 0:
 4         return 0
 5     else:
 6         return 2 * f(x -1) + x * x
 7
 8
 9 # test code
10 print f(1)
11 print f(2)
12 print f(3)
13 print f(4)
14

bash:

bash写一个简单的递归竟然也这么难。。。。。。郁闷,这是过了两天自己后来补上的,最后因为vim的上色没有办法直接复制到word和这边,所以通过vim2html的转换后再贴过来:)效果很好啊。

1 #!/bin/bash
 2
 3 function f
 4 {
 5     local number="$1"
 6     if [ $number = 0 ]
 7     then
 8         ret=0
 9     else
10         let "decrnum = number - 1"
11         f $decrnum
12         let "ret = $? * 2 + $1 * $1"
13     fi
14
15     return $ret
16 }
17
18 for i in 1 2 3 4
19 do
20     f i
21     echo $?
22 done
23

补充说明一下,这次完全lua,python都是在windows中gvim完成,以后全部放到linux中完成。呵呵,其实作为脚本语言这样移植性非常好的语言来说,主要的区别仅仅是开始第一句linux会多句magic指示,以方便直接在shell中执行而已。主要的目的是以后的vim2html可以通过bash的脚本来一次完成,不需要在windows中通过这么多操作了。:)

write by 九天雁翎(JTianLing) -- www.jtianling.com

阅读全文....

一天一个C Run-Time Library 函数(8) assert

 

 

一天一个C Run-Time Library 函数8  assert

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

msdn:

Evaluates an expression and, when the result is false,
prints a diagnostic message and aborts the program.

 

void
assert(

   int expression

);

测试程序:

说明:

assert实在是所有C语言运行库中用的最多的函数之一,这么说可能有些让人惊讶,事实上却很容易让人接受,除了用于日志记录和控制台输出的函数printf+文件一族函数,还有哪个函数会被频繁的调用啊。

这里说明一下,其实虽然assertdebug的时候肯定不会调用,但是其实你可以定义一个宏,比如我们公司JTASSERT来替代assert,然后用另外一个宏作为开启开关,比如__JTASSERT__,这样,就算在debug版本下你也获得了是否使用断言的功能。另外,其实更进一步的用法是使用一个数字作为JTASSERT的参数,然后将__JTASSERT__的宏定为一个数值,然后只在参数的整数大于此宏定义数值的时候才真正调用assert,那么就实现了一个可控级别的断言函数。

再另外,一般的assertrelease下就没有作用了,这时候还是想要断言的话,可以用abort函数自己来实现。

最后,用assert(false);的形式可以断言你认为不会进入的分支,这在if-else if的多重语句中,最后一个语句,还有switchdefault分支中使用,价值很大。

 

实现:

MS:

基本上没有什么太多技术含量,就不贴了,说下流程,无非就是先判断是否是控制台的程序,然后用两条线来实现,控制台的从命令行输出错误信息,不是控制台的直接弹出对话框。(其实我自己都感觉这样的分析和事实有出入,因为以前写的服务器在控制台下也是弹出对话框的)到最后都是调用abort函数实现,其实最想不到的是微软竟然也会用abort函数。。。。。。。。呵呵

gcc:

MS的简单的更多,因为没有需要判断是否用GUI来提示,最后也是用abort来实现,代码也不贴了。

 

 

 

效率测试:

 

相关函数:

abort

个人想法:

真正健壮的代码就是一直在干你想干的事情,出现异常或错误也能恢复。但是事实上,出现异常和错误能够让你知道,这也是很重要的,特别是与很多人一起调试的时候。这个时侯,assert就是很重要的了,比如参数的检验,自赋值的预防,等等都是可以给你省下很多调试的时间。其实,很多时候,设计的时间要远远大于编码的时间。而调试的时间又会大于设计的时间,这是我在刚学习编程的时候所不能想想的。。。。。但是工作中感受到了。

 2009.1.24后补:其实assert的实现还是有点意思的,当时只是随便看了下assert.c文件,所以那样说,今天再看《C陷阱与缺陷》的时候发现了这一点,我在这里补上:

#define assert(_Expression) (void)( (!!(_Expression)) || (_wassert(_CRT_WIDE(#_Expression), _CRT_WIDE(__FILE__), __LINE__), 0) )

assert是个宏,大部分人可能都不会惊讶,不然也达不到debug时有效,release时无效的效果,但是最有意思的是判断是否需要弹出异常的方式,并没有使用if-的判断方式,仅仅是为了避免宏的副作用。假如是用if方式实现的话,当在外部通过

    if(someEx)
        assert(someEx);
    else
        assert(someEx);
    的形式使用时,会使得else与assert中的if配对,而发生问题。。。。所以通过&&,||的计算顺序特性来完成:)又是一个C语言的小技巧啊。。。。太多这样的奇技淫巧了-_-!


 

write by 九天雁翎(JTianLing) -- www.jtianling.com

 

阅读全文....

一个无聊男人的疯狂数据结构学习(序)

write by 九天雁翎(JTianLing) -- www.jtianling.com

学习以《数据结构与算法分析—C++描述》第三版为基础。

目标是,以C++, python,lua,(甚至,只要感觉可能,加上bash)来实现书中所描述的所有例子(例子用C++实现了我就用其他语言),和所有习题。

这是个疯狂的学习计划,以前我学习数据结构老是学着学着从开始的慢慢的,耐心的学习变成了后期的光看书看概念,damn it.以至于无论工作了多么久,老是感觉一块是空的。现在不像当时纯粹在学习的时候了,老是感觉需要学点能赶快找到工作的东西(比如MFC),现在我开始做工具这一块了,感觉可能会稍微轻松点,(谁知道当时做服务器的时候进度怎么赶得)。

虽然每天可能仅仅实现那么一个例子,看那么一两面书,做那么一个题目,用一个月完成书的第一章,who care it。我有的是时间。又不担心没有工作,又不担心饿死,不用这点机会好好的学习一下数据结构那还干什么?lua,python,bash就是真的是书看的多,实践的少,不正好靠这个机会来实践一下吗?每天看一两面,看完这本书也仅仅需要一年。仅仅一年。数据结构和算法对我的帮助可是一辈子。想我光用工作的空隙,中午一个小时吃饭剩下的时间,晚上9点以后到家的时间都已经看了从《Effective C++》,《windows核心编程》,《lua程序设计》,《python核心编程》,《advanced bash shell》,和《win32多线程程序设计》的一半了,我还当心什么?担心什么啊。就一周一天的休息,我还能看完上述书籍,再熟悉了makefile的写法,vim的用法,(很好用哦:),我现在在公司都是用VS+VA+vimemu,gdb的调试方法,学完了上面的所有,才用了我半年。半年以来几乎天天加班,一周才休息一天,我怕什么?怎么还怕没有时间来学点数据结构,并且实践一下我喜欢的luapython?呵呵,不会没有时间,我有的是时间,时间不就像海绵里的水吗?(谁说的来着?)

谁都不可以抱怨没有时间来干自己感兴趣的事情。谁一天像我一样工作10多个小时一周工作6天?我都不抱怨没有时间,我有时间来干我自己想干的事情。比如实行这个疯狂的计划。另外,以前计划用多种语言实现makefile的自动生成在后来实际的使用中感觉没有那么太大用处了,也许某天我会用bash实现一下。实际上我现在在公司学习APUE(<<UNIX环境高级编程>>)做习题的时候,为了方便,写了一个bash的脚本,直接以一个参数运行,然后生成目录,及以参数确定的cpp,h文件和makefile文件了,也就是说,用一个bash脚本来生成了一个小型的测试工程以方便我实现书上的例子:),感觉仅仅实现自动生成makefile文件似乎都委屈了bash语言了:)

呵呵,大概计划就是这些了,首先第一个任务就是完成我给小强的一个习题了,用python,lua实现10进制转2进制的输出。(其实blog上有我用c++的实现,但是说实话,用来太多c++特性,比如bitset来实现实在没有体现出真正的思想,当我刚开始学C实现的时候,那时候成就感可是很大的,那是我为自己兴趣实现的第一个程序。自己想想,自己实现的一个程序,跟老师无关。虽然那时候老师也给题目做,不过好像我一个也没有做,都是抄的,因为不习惯在纸上写代码。

 

呵呵,晕了,真是疯狂了。。。。。。。。。。忘了说,我每天晚上都喝二锅头。红星二锅头。为什么特别提出红星?因为牛栏山的度数太低了(一般我看到的都只有45度,红星我一般喝56的。。。。呵呵。)

 

其实对上次对lua stdlibbug report很有成就感,其实有想法把lua stdlib全部用C++实现一次以提高效率,或者把现有的lua stdlib源代码全部研究一遍,甚至参与lua stdlib的开发,但是。。。。呵呵,可能要延后了。先这么着吧。反正还有时间,我有的就只有时间。耗费的就是时间。

过了这么久再回头看看。。。那时候就是喝高了-_-!一下子从自己挺感兴趣的服务器组调到工具组,心理的失落感还是挺大的,我这个人习惯不太好,平时没有事就喝酒,有点小事喝的更多。唉。。。。可惜唯一能够改变我这个习惯的人还不在身边。

不过当时的计划现在却还一直坚持着(虽然只目前只把书看到了45面,才只实现了5个很简单的算法),呵呵,也算个收获。希望能够一直坚持到将这本书看完。

 

 

write
by
九天雁翎(JTianLing)
-- www.jtianling.com

 

 

阅读全文....