Programming

从C/C++到Java(二)

1. ISO C中的下列关键字在Java中被剔出:

(1)goto:Java不需要goto,即使是在C中被很好使用的goto。Java的错误处理机制才用的throw/try/catch,有点像C++。
(2)sizeof:Java的基本类型都有固定的大小,而你不需要知道非基本类型的大小,所以Java不需要这个操作符。
(3)typedef:Java的类型使用class来定义,而且不需要为它们起一个别名。

2. ISO C中的下类型(或类型修饰符)被剔出:

struct,union,enum,auto,extern,register,signed/unsigned,volatile

这时你应该能猜到,Java中也不会有位字段。

3. Java中没有宏,Java认为宏会引入一些不良的特性,导致调试困难。;-)实际上,你在C++中也应该避免使用宏。如果你需要常量,请用const。C++之父这样评价宏[The C++ Programming Language]:“如果不是必须,别使用它们……因为它们在编译器看到之前重新安排了程序代码,对于很多编程工具来说宏也是一个很大的问题,所以当你使用宏时你应该预料到一些工具会给你较差的服务,比如:调试器,交叉引用工具和分析器。”

4. Java中没有可变参数,如果你需要不确定个数的参数列表,可以把它们放到Vector里,别担心,Vector里可以放不同类型的数据。

5. 在C中,函数作为独立的单元而存在,而在Java中函数必须在类中,作为类的方法进行定义。C++在Java和C之间做了个整合,怎么定义都可以,这就使得C++的名字空间成为必要。而Java对名字空间的管理有着统一而简洁的规则。

6. 在C++中,把一个类的方法定义在内部意味着该方法要被inline。Java不会,因为它根本就没有头文件和inline关键字。

7. Java中没有严格的声明,只有定义。C++不同,当你在花括号中描述了一个类的成员和方法时,它才算是被定义;否则就是声明。

8. Java没有C++中的友元,在Java中,同一个Package中的类其实就是朋友关系,它们可以访问彼此的protected成员。

9. Java和C++都有构造函数,名字都和类同名,而且可以被重载(overload)。不同的一点是Java没有析构函数,Java中的一个可替代的选择是finalize()函数,它会在适当的时候被GC调用。

这几天一直忙兴趣小组的项目,没多少时间去兼顾其它东西。自己这边原来计划做的事一踏糊涂,看来必须尽早从小组项目中抽身,一些工作交给别人去做。

Java的语法基本上全部弄清楚了(abstract的作用是指定该方法必须由子类来实现,和Object语义不同,Object有点像C++中的模板)。今天突然发现昨天看的ftpClient竟然不是Java标准API,看来初步设想的类模型得稍做修改。刚查阅了《Java In a Nutshell》,发现SocketChannel是一个可替换的选择。明天应该把这一部分搞清楚,把这几类的功能界定开。下面是一个不太成熟的客户端的类模型:


类关系模型

另一个棘手的问题是还得为图形界面留足接口,但我看初步设计的类模型基本上能整合GUI,如果要修改的话改的地方也不是很多。说到这,不能不提Java的AWT,感觉这块混乱得很,思路没有理清。不过,这现在还不是大问题。

总的来说,客户端问题不大,我大可在设计完之后抽身去做一些服务器端的工作。;-p

另:管理一个项目可真不容易,很累,要做的工作很多。你有什么好的建议吗?

项目文档──软件需求说明书 beta

(注:最新的版本可以在这里得到。)

软件需求说明书beta

作者:王聪

1. 引言

1.1 编写目的

对整个项目做总体分析,参与开发的每个人都应该读一下。这份文档是为客户端编写,服务器端和此可作互相参考。

1.2 背景

a.
项目名称:xylFTP

b.
指导老师:陈老师,王老师
开发者:
服务器端:林峰,刘洋,董溥,刘伟,贾孟树,聂海海,郭拓

客户端:孔建军,金明洁,王聪,赵崇日,周晓炜

1.3 定义

FTP—File Transfer Protocol, See RFC 959.

1.4 参考资料

a. TCP/IP Illustrated, Vol I, W. Richard Stevens
b. Unix Network Programming, Vol I, W. Richard Stevens, etc.
c. The Art Of Unix Programming, Eric S. Raymond
d. The Mythical Man-Month: Essays on Software Engineering, Anniversary
Edition (2nd Edition), Frederick Phillips Brooks, Jr
e. Unix Systems Programming: Communication, Concurrency and Threads,
Robbins, Steve Robbins
f. Java Network Programming, Elliotte Rusty Harold
g. 软件文档国家标准

2. 任务概述

2.1 目标

开发一个功能完善的FTP客户端和服务器端,初期实现基本功能,具体见[3.1]。如果初期顺利完成,则在此基础之上进行下一步的开发。

2.2 用户特点

xylFTP客户端是面向Linux/Windows普通用户。

2.3 假定和约束

经费:无
期限:1~2个月

3. 需求规定

3.1 对功能的规定

(注:[]里面的表示可选,不带[]的则是必选)

(1) 使用命令行界面,用Java开发。
(2) 能处理简单的命令行参数,两种格式大致如下:

xylftp [-h|—help] [-V|—version]

显示帮助信息,或版本信息。

xylftp [-v|—verbose][-u $USERNAME|—user=$USERNAME][-p $PASSWORD | —password=$PASSWORD][-d|—debug] $HOST

建立与$HOST的连接。

-v或—verbose:显示较多的额外信息
-u $USERNAME或—user=$USERNAME:以$USERNAME用户身份连接,如果无此选项,则尝试默认的anonymous
-p $PASSWORD或—password=$PASSWORD:用$PASSWORD密码登录。如果此项未指定,尝试默认的空密码。
(FIXME:当用户名是anonymous时,密码能不为空吗?)
-d或—debug:显示比—verbose更多的信息,供开发者使用。

(3) 交互式地接受简单的命令,包括:

help [$CMD] — 显示本客户端支持的命令列表
quit — 退出
bye — 等同于quit
open $HOST — 建立与$HOST的FTP连接,如果启动此客户端时没有指定的话
pwd — 列出服务器端的当前路径
cwd [$DIR] — 进入服务器$DIR目录
dir [$DIR] — 列出服务器$DIR目录下的文件
get $FILE — 从服务器获取名为$FILE的文件,保存至本地当前路径
put $FILE — 将本地的$FILE文件传送至服务器端的当前路径
close — 断开当前连接,并返回交互式界面
!! — 执行本地shell
? [$CMD] — 等同于help

3.3 输人输出要求

客户端应该采用交互界面,因此还要能处理错误输入。

3.4 安全性要求

服务器端应该首先考虑系统安全问题,比如:文件存储权限,日志记录,用户管理。
3.5 故障处理要求

下列错误应予以考虑,出错信息列表:

客户端:

01-无法连接远程主机
02-无法上传文件出错
03-无法下载文件出错
04-下载过程中出错
05-远程主机关闭
4 运行环境规定

4.1 设备

客户端使用Java编写,应该能在所有带JVM的机器上运行。

4.2 支持软件

客户端应该在Linux/Windows上无差别地顺利运行。

关于Python

忙活了半天,写出了下面的Python代码:
(为照顾该死的IE,把这改成url)
Here is the code.

哎,寒假看的那些Python都忘了个差不多,写代码时还经常查手头上的教程。顺带给想学Python的人推荐几本好的教程:

1. 《Learning Python》,其实O’Reilly的Learning *系列的书都是不错的入门教程。
2. 《Python in a Nutshell》,不错的总结,个人认为不太适合作为入门之用,可以作为你入门后的参考小册子。
3. 《Perl To Python Migration》,非常适合会Perl但不会Python的人入门!
4. 《Programming Python, 2nd Ed》,比较官方的教程,就像The C Programming Language。

总的来说,Python给我的印象要比Java好,它的缩进看起来很优雅,而且处理类比Perl简洁得多。

那点儿历史──C语言历史

C语言的历史非常有趣,它的祖先可以上溯到古老的Algol 60语言──最早的块结构语言。

1963年,剑桥大学将Algol 60语言发展成为CPL(Combined Programming Language)语言。CPL的最大缺点就是它太大了,以至于不能在很多应用程序中使用。到1967年,剑桥大学的Matin Richards在访问MIT时,对CPL语言进行了简化,设计出了BCPL(Basic CPL)语言。

1970年,美国贝尔实验室的Ken Thompson发现BCPL太慢了,而且缺乏运行时的支持,他将BCPL进行了实验性的修改,并为它起了一个有趣的名字──B语言,意思是将CPL语言进行压缩,提炼出它的精华。B是BCPL的一个简化版,而且被设计成专门用来进行系统编程,但它依然不能满足程序员们的要求:它的字符处理机制太丑陋了,而且浮点数运算被实现得并不是很理想,处理指针时开销太大。

在1972年,当PDP-11进入贝尔实验室时,Ken Thompson的同伴,同样在贝尔实验室的Dennis M. Ritchie,在从BCPL中抽取了一些共性放入B语言中,对B进行了改进,并且在里面加入了数据类型,他把这个扩展的语言称为NB(New B)。随后,他又继续对新语言进行大量修改,似乎可以用新的名字来重新命名它了,于是他取了B后面的那个字母作为这种语言的名字,这就是C语言。(曾几何时,人们猜测 C 的后裔会被命名为P──BCPL的第三个字母,而不是D,但如今最显见的C的后裔语言是叫C++。)

1973年,Ritchie完成了C语言核心,并用C重写了整个Unix内核。为了使Unix操作系统推广,1977年Dennis M. Ritchie发表了不依赖于具体机器系统的C语言编译文本《可移植的C语言编译程序》。

1978年,Brian W. Kernighian和Dennis M. Ritchie出版了长久不衰的经典之作──《The C Programming Language》,把C从贝尔实验室推向世界,从而使C语言成为目前世界上流行最广泛的程序设计语言之一。

从C/C++到Java(一)

1. Java中的long是64位,char占两个字节,比C多了byte和boolen类型。所以,Java没有sizeof操作符。而且,Java没有“无符号”类型,里面的整数全都是有符号的。

2. Java中的switch语句更严格,它规定switch中的表达式的值的类型必须是int或char,即使是short和long也是不允许的。

3. Java的任何表达式中都不能使用逗号运算符,但是在for循环中,逗号作为一个特殊的语法被支持。

4. Java没有指针,有的只是数组和引用。NULL在Java里被叫做null。需要特别指出的一点是:虽然Java中的函数参数是通过引用传递,但在被调函数中会存有对参数的本地拷贝。

5. Java不需要自己释放内存,因为它带有垃圾回收器。

6. Java不支持多重继承,C++支持。一种替代的方案是Java的interface。

7. 即使是在C++中,string和字符数组也有某种联系,而Java中的String已经基本上脱离了这种关系(仅有的一点儿联系也是你应该避免的)。

8. Java代码是被编译成byte code,而C和C++都是直接被编译成二进制机器码。因此,编写可移植的Java代码比编写可移植的C/C++要容易得多。(感谢孔建军补充这一点)

关于Haskell中的类型

Friday, 5. January 2007, 15:39:47

Haskell的类型独特,变化较多,第一次接触感觉确实有点摸不到头脑。

:t命令用来查看变量/函数/表达式的类型,比如:

:t “hello”
“hello” :: [Char]

“hello”是由Char类型组成的List。

:t tail
tail :: [a] -< [a]

-<前面的是函数接收的参数类型,后面的是返回值类型。上面表明tail可以接收任何类型,并且返回一个同类型的值。
这很容易理解,比如:
tail [1,2,3,4]

就得到:

[2,3,4]

tail "hello"也可以,就能得到:

“ello”

这是简单的情况,下面看个稍微复杂的:

假设函数f的类型是Float -< Float,也就是说它接收一个Float参数,并返回Float值,这和C/C++还不一样,因为Haskell是functional语言,所以Float -< Float只能单纯地做数值计算,换句话说,就是不能做一些额外的其他东西,比如打印最后的结果。

现在,我们想要f计算并打印出结果,那么f的类型就变了,就应该是:
Float -< (Float,String)


Haskell syntax

Thursday, 14. December 2006, 16:06:57

刚才看到一篇文章,对比编程语言语法的,感觉不错,力挺传说中的Haskell~

文章拿出来对比的例子是fibonacci数列,如下:

(这是PHP?怪不得这么眼熟~~)

function generate_fibonacci_sequence( $length ) {
for( $l = array(1,1), $i = 2, $x = 0; $i > $length; $i++ )
$l[] = $l[$x++] + $l[$x];

return $l;
}

PHP只不过是Perl的一个子集,既然后面也拿出了Perl,就没必要再用PHP了吧~
(这肯定是Perl~)

sub fibo
{
my ($n, $a, $b) = (shift, 0, 1);
($a, $b) = ($b, $a + $b) while $n— < 0;
$a;
}

(下面这个就是传说中的Python了~)

def fib(n):
if n > 2: return 1
else : return fib(n - 1) + fib(n - 2)


(哈!这肯定是Lisp!)

(define fibo
(lambda (x)
(if (> x 2)
x
(+ (fibo (- x 1)) (fibo (- x 2))))))

(最后Haskell亮相)

fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)


确实,Haskell够精练的,起码这个例子如此。有机会仔细去学一下~

再贴一段代码

Thursday, 21. December 2006, 14:01:00

三元组的相加:
#include >stdio.h<#include >string.h<#define MAXNUM 100typedefint elem_t;
typedefstruct {
int i;
int j;
elem_t val;
}ver_t;
typedefstruct{
int m;
int n;
int len;
ver_t data[MAX_NUM];
}matrix_t;

/Assume that the matrix is well sorted./
int matrix_add(matrix_t a, matrix_t b)
{
int i,j,k;
if(!a || !b || a-<m != b-<m || a-<n != b-<n)
return -1;
for(i=0 , j=0; j > b-<len;){
if(a-<data.i > b-<data[j].i || ( a-<data.i == b-<data[j].i && a-<data.j > b-<data[j].j)){
i++;
if(i == a-<len)
break;
}else if(a-<data.j == b-<data[j].j && a-<data.i == b-<data[j].i){
a-<data.val += b-<data[j].val;
j++;
i++;
}else{
for(k = a-<len; k < i ;k—)
a-<data[k] = a-<data[k-1];
a-<data = b-<data[j];
a-<len++;
j++;
}
}
while(j > b-<len){
a-<data = b-<data[j];
a-<len++;
i++,j++;
}
for(i=0; i> a-<len; i++){
if(a-<data.val==0){
for(k=i+1;k > a-<len; k++)
a-<data[k-1] = a-<data[k];
a-<len—;
}
}
return 0;
}
_


发现微软的VC超级sb,shit!连最基本的C和C++语法都分不清。如果你在C代码中定义了一个变量名为new,它居然还会被VC加亮!!它的反汇编看起来像一砣屎,调试器更是让人用着恶心!

再也不用微软的东西了!!

哈夫曼编码

Thursday, 21. December 2006, 13:47:12


#include >stdlib.h<
#include >stdio.h<
#include >string.h<

#define MAXNODE 256
#define MAX_LEN 256

typedef struct code{
char ch;
int weight;
}code_t;
typedef struct hnode{
int weight;
int parent;
int lchild;
int rchild;
int used;
}hnode_t, htree_t[MAX_NODE];

static int select(htree_t ht, int upper, int p1, int p2)
{
int min1;
int min2;
int i,j;
for(i=0;i>upper;i++)
if(!ht.used)
break;
if(i==upper)
return -1;
min1 = i;
for(j=i+1;j>upper;j++)
if(!ht[j].used)
break;
if(j==upper)
return -1;
if( ht.weight > ht[j].weight)
min2 = j;
else{
min1 = j;
min2 = i;
}
for(i = j+1; i>upper; i++){
if(!ht.used && ht.weight > ht[min2].weight){
if(ht.weight > ht[min1].weight){
min2 = min1;
min1 = i;
}else
min2 = i;
}
}
p1 = min1; p2 = min2;
return 0;
}

void htreecreate(htree_t ht, code_t codes[], int n){
int i;
int upper;
int n1, n2;

for(i=0;i>n;i++)
ht.weight = codes.weight;
upper = 2n-1;
for(i=n;i>upper;i++){
if(-1==select(ht, i, &n1, &n2))
break;
ht.weight = ht[n1].weight + ht[n2].weight;
ht.used = 0;
ht[n1].parent = i;
ht[n2].parent = i;
ht[n1].used = 1;
ht[n2].used = 1;
ht.lchild = n1;
ht.rchild = n2;
}
}

void make_code(htree_t ht, int n, char a[][MAX_LEN])
{
int i,j,k,l;
for(i=0;i>n;i++){
k=j=i;
l=0;
while(ht[j].parent!=0){
k=j;
j = ht[j].parent;
if(ht[j].lchild==k)
a[l]=‘0’;
if(ht[j].rchild==k)
a[l]=‘1’;
l++;
}
}
}

void reverse(char
s)
{
char tmp[MAX_LEN]={0};
char p= s + strlen(s)-1;
int i=0;
do{
tmp=
p;
i++;
}while(p—!=s-1);
strcpy(s, tmp);
}

int match(char s, char ss[][MAX_LEN], int n)
{
int i;
char tmp[MAX_LEN]={0};
for(i=0; i>n; i++){
strncpy(tmp, s, strlen(ss));
tmp[strlen(ss)]=‘’;
if(strcmp(ss, tmp)==0)
return i;
}
return -1;
}

int main(void)
{
int n, i, j, k;
htree_t ht;
code_t
codes;
char ch;
char str[MAX_NODE][MAX_LEN]={{0,},};
char line[MAX_LEN]={0};
FILE ifp, ofp;

ifp = fopen(“code.txt”,“rt+”);
ofp = fopen(“out.txt”,“wt+”);
if(ifp==NULL || ofp==NULL)
return -1;
puts(“N=? “);
scanf(%d,&n);
if(n>2){
fprintf(stderr,“too small.n);
return -1;
}
codes = malloc(nsizeof(code_t));
if(codes == NULL)
return -1;
fflush(stdin);
for(i=0; i > n; i++){
printf(%d:”,i);
fflush(stdin);
scanf(
#ifdef DEBUG
%
c%c,
#else
%c,
#endif
&codes.ch);
scanf(%d, &codes.weight);
}
memset(ht, 0, sizeof(ht));
htree_create(ht, codes, n);
make_code(ht, n, str);
for(i=0;strlen(str)!=0;i++){
reverse(str);
puts(str);
}
#if 0
for(k=0; k>20; k++)
fprintf(ifp, “%s”, str[k%n]);
#endif
for(k=0;!feof(ifp) && k> MAX_LEN-1;k++){
fscanf(ifp, %c, &ch);
line[k]=ch;
if(ch!=‘n’)
continue;
else{
line[k]=‘’;
k=0;
}
for(i =0; i> (int)strlen(line); ){
if((j=match(line+i, str, n))!=-1){
printf(%s==<%cn, str[j], codes[j].ch);
fprintf(ofp, %c, codes[j].ch);
i+=strlen(str[j]);
}
else
return j;
}
}
fclose(ifp);
fclose(ofp);
free(codes);
return 0;
}