首先我单独建了一个目录用来保存学习时需要的目录,将此脚本拷贝到这个目录下面,以后每次以一个参数运行脚本,就会自动创建目录,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
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:
对于这样经典的算法好像 gcc 和 MS 终于没有办法不一致了,事实上也是如此,两者几乎没有任何区别,其实现可以在任何关于算法的书籍上找到。
效率测试:
见以前有人说过 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 类
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,
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 由于支持C99 ,C99 中的long long 类型也有支持,lltoa 等。
个人想法:
想起一个大牛 Lippman 说过的话,假如 C++ 抛弃了 C 那么多的整数类型的话,那么重载函数的负担会小得多。。。。。。。。事实就是这样。
这类函数就是典型的例子。不仅仅是重载麻烦了,并且哪怕一个简单的关于整数的函数,都需要实现很多种,并且在 C 中需要很多的名字。。。。还好有一定规律。
windows 中甚至实现了关于 double 的此类函数,呵呵,浮点都有两种。
但是,反过来说,当在 C++ 中还有那么多人需要精确的控制自己需要的整数大小,甚至有的时候根本就不是整数,需要的仅仅是一个确定大小的缓存(或空间)时,不同的整数就不可避免。。。。。其实,除非 C++ 将所有的整数全部整合到 integer 然后将目前用于内存等精细操作的整形放在诸如 BYTE , WORD,DWORD 中去实现也是不错的选择。。。。当然,很多时候,我们还是需要苛刻的对空间进行要求,对于一个表示类型的变量用 unsigned char ,对于一个不会大于 65535 的整数用 unsigned short 时,(我们公司写游戏和服务器的时候都是这样),这些想法可能永远不会实现。
记得,以前看到 mysql 的一份文档中, mysql 的开发人员甚至以自己的整数类型比较多而感到自豪(也许不是自豪吧),进行了类似这样描述, mysql 有丰富的整数类型,这样你可以使用更适合你的整数,在数据很大时,这可以为你省下很大的空间。。。。。。。。。。。 the same in C/C++.......................
write by 九天雁翎 (JTianLing) -- www.jtianling.com
阅读全文....
人类是在偷懒中进步的 , 用一个 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
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 中的 TerminateProcess , ExitProcess 等 API 作为对比的,没有提及 exit.
write by 九天雁翎 (JTianLing) -- www.jtianling.com
阅读全文....
原文: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的汇编代码前。。。。哪想的到原来这么简单
阅读全文....
一个无聊男人的疯狂数据结构学习( 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
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+ 文件一族函数,还有哪个函数会被频繁的调用啊。
这里说明一下,其实虽然assert 在debug 的时候肯定不会调用,但是其实你可以定义一个宏,比如我们公司JTASSERT 来替代assert, 然后用另外一个宏作为开启开关,比如__JTASSERT__, 这样,就算在debug 版本下你也获得了是否使用断言的功能。另外,其实更进一步的用法是使用一个数字作为JTASSERT 的参数,然后将__JTASSERT__ 的宏定为一个数值 ,然后只在参数的整数大于此宏定义数值的时候才真正调用assert ,那么就实现了一个可控级别的断言函数。
再另外,一般的assert 在release 下就没有作用了,这时候还是想要断言的话,可以用abort 函数自己来实现。
最后,用assert(false) ;的形式可以断言你认为不会进入的分支,这在if-else if 的多重语句中,最后一个语句,还有switch 的default 分支中使用,价值很大。
实现:
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 的调试方法,学完了上面的所有,才用了我半年。半年以来几乎天天加班,一周才休息一天,我怕什么?怎么还怕没有时间来学点数据结构,并且实践一下我喜欢的 lua 和 python? 呵呵,不会没有时间,我有的是时间,时间不就像海绵里的水吗?(谁说的来着?)
谁都不可以抱怨没有时间来干自己感兴趣的事情。谁一天像我一样工作 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 stdlib 的 bug report 很有成就感,其实有想法把 lua stdlib 全部用 C++ 实现一次以提高效率,或者把现有的 lua stdlib 源代码全部研究一遍,甚至参与 lua stdlib 的开发,但是。。。。呵呵,可能要延后了。先这么着吧。反正还有时间,我有的就只有时间。耗费的就是时间。
过了这么久再回头看看。。。那时候就是喝高了-_-!一下子从自己挺感兴趣的服务器组调到工具组,心理的失落感还是挺大的,我这个人习惯不太好,平时没有事就喝酒,有点小事喝的更多。唉。。。。可惜唯一能够改变我这个习惯的人还不在身边。
不过当时的计划现在却还一直坚持着(虽然只目前只把书看到了45面,才只实现了5个很简单的算法),呵呵,也算个收获。希望能够一直坚持到将这本书看完。
write
by 九天雁翎 (JTianLing)
-- www.jtianling.com
阅读全文....