文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>短信操作(简陋版)

短信操作(简陋版)

时间:2009-07-26  来源:nothing3618

文件: 小学期课程设计之短信操作.rar
大小: 3160KB
下载: 下载
   这是个小学期作业。要求是实现对短信的处理,具体是读取短信的内容,获取电话号码(区分座机号和手机号),获取事件的时间、地点和动作,然后触发通讯录功能或者记事本功能。在文档readme中应该说明白了。这个程序是在pc上模拟的。当初刚接到任务,想做到手机上,但是,发现在短短的十八天内做出来几乎不可能,因为我们还没学过做手机软件等相关知识,单单学懂这些就不容易,况且要让其在手机上能运行起来,还得考虑数据的大小和运行的速度等,很麻烦。最后只好在pc上仿真实现交了任务算了。获取电话号码那块,主要是根据我的手机(诺基亚6120)上类似功能做的。当时很有趣,用飞信可以自己给自己发短信,于是我测试出来它的规则后,程序的这一块就基本成型了。我想,专门做手机的,对手机号的界定应该有比较深刻的理解的,我就不耗脑力去抠出错的情况了。然后是对事件的识别。这个……我觉得很难做好。提取事件的时间这块还好,因为常见的时间表达方式不会有太多,用有限状态机算法就可以实现。我觉得我的程序在这一块已经做得不错了,可以提取大多数在手机短信中出现的时间信息。然后是事件的地点和动作。对地点的识别,目前有个比较流行的名词是“命名实体识别”。但是,我没有语料没有地名库,根本没法做好。老师建议用句法剖析。当然,大家都清楚,目前这个技术本不成熟,所以并不期望我们能做到怎么样。用句法剖析提取,会有很多很多尚没法解决的问题。短信的用语习惯千差万别,不规范;没有语料库!
    老师说,这个作业目的不是作出有实用的东西,而是让大家初步接触大型程序设计。好吧,虽然本来很想做出个东西来,但真的很难,时间太紧,技术不成熟,材料不足。于是玩了好几天,在最后三四天赶出来这个程序。用了win32-gui模块做了个界面。所以,要运行需要给电脑安装这个模块先。  

#!/usr/bin/perl

use strict;
#use warnings;

use Encode;
use Win32::GUI();

 ##########################        第一个窗口“短信发送端”     ####################

my $DOS = Win32::GUI::GetPerlWindow();        #这里目的是运行程序时隐藏dos界面

Win32::GUI::Hide($DOS);

my $win1 = Win32::GUI::Window->new(        #创建短信发送端窗口

   -name => 'mainWindow1',
   -title => '短信发送端',
   -pos     => [150, 300],
   -size => [400, 200],    
);

$win1->AddLabel(
   -name => 'Label1',
   -title => '本机号码:',
   -pos => [20,20],
);

$win1->AddTextfield(
   -name => 'Edit1',
   -pos => [80,15],
   -size => [100,20],
);

$win1->AddLabel(
   -name => 'Label2',
   -title => '短信:',
   -pos => [20,40],
);

$win1->AddTextfield(
   -name => 'Edit2',
   -multiline => 1,
   -pos => [20,60],
   -size => [280,90],
);

$win1->AddButton(
   -name => 'ResetSms',
   -title => '重置',
   -pos => [310,70],
   -size => [60,20],
);

$win1->AddButton(
   -name => 'SentSms',
   -title => '发送',
   -pos => [310,100],
   -size => [60,40],
   -ok => 1,
);

$win1->AddTimer('T1', 1000);    #这里是为了在窗口中显示系统时间


sub T1_Timer {
    my $time = localtime();
    $win1->AddLabel(
    -title => $time,
    -pos => [210,20],
    );
}

#########################        第二个窗口“短信接收端”        #########################

my $win2 = Win32::GUI::Window->new(        #创建“短信接收端”窗口

   -name => 'mainWindow2',    
   -title => '短信接收端',
   -pos     => [700, 200],
   -size => [400, 500],
);

$win2->AddLabel(
   -name => 'Label3',
   -title => '原始短信:',
   -pos => [20,20],
);

$win2->AddLabel(
   -name => 'Label4',
   -title => '发信人:',
   -pos => [30,45],
);

$win2->AddTextfield(
   -name => 'Edit3',
   -pos => [90,40],
   -size => [100,20],
);

$win2->AddLabel(
   -name => 'Label5',
   -title => '发送时间:',
   -pos => [30,75],
);

$win2->AddTextfield(
   -name => 'Edit4',
   -pos => [90,70],
   -size => [180,20],
);

$win2->AddLabel(
   -name => 'Label6',
   -title => '内容:',
   -pos => [30,105],
);

$win2->AddTextfield(
   -name => 'Edit5',
   -multiline => 1,
   -pos => [90,100],
   -size => [280,90],
);

$win2->AddLabel(
   -name => 'Label7',
   -title => '通讯录:',
   -pos => [20,220],
);

$win2->AddLabel(
   -name => 'Label8',
   -title => '手机:',
   -pos => [30,250],
);

$win2->AddTextfield(
   -name => 'Edit6',
   -pos => [60,245],
   -size => [100,20],
);

$win2->AddLabel(
   -name => 'Label9',
   -title => '座机:',
   -pos => [30,275],
);

$win2->AddTextfield(
   -name => 'Edit7',
   -pos => [60,270],
   -size => [100,20],
);

$win2->AddLabel(
   -name => 'Label10',
   -title => '备注:',
   -pos => [30,300],
);

$win2->AddTextfield(
   -name => 'Edit8',
   -pos => [60,300],
   -size => [100,110],
   -multiline => 1,
);

$win2->AddLabel(
   -name => 'Label11',
   -title => '记事本:',
   -pos => [190,220],
);

$win2->AddLabel(
   -name => 'Label12',
   -title => '时间:',
   -pos => [200,250],
);

$win2->AddTextfield(
   -name => 'Edit9',
   -pos => [230,245],
   -size => [140,50],
   -multiline => 1,
);

$win2->AddLabel(
   -name => 'Label13',
   -title => '地点:',
   -pos => [200,305],
);

$win2->AddTextfield(
   -name => 'Edit10',
   -pos => [230,300],
   -size => [140,50],
   -multiline => 1,
);

$win2->AddLabel(
   -name => 'Label14',
   -title => '动作:',
   -pos => [200,365],
);

$win2->AddTextfield(
   -name => 'Edit11',
   -pos => [230,360],
   -size => [140,50],
   -multiline => 1,
);

$win1->AddTimer('T2', 1000);    #为了在窗口中动态显示系统时间


sub T2_Timer {
    my $time = localtime();
    $win2->AddLabel(
    -title => $time,
    -pos => [210,20],
    );
}

$win1->Edit1->SetFocus();        #为后面对文本框的处理作准备

$win1->Edit2->SetFocus();
$win2->Edit3->SetFocus();
$win2->Edit4->SetFocus();
$win2->Edit5->SetFocus();
$win2->Edit6->SetFocus();
$win2->Edit7->SetFocus();
$win2->Edit8->SetFocus();
$win2->Edit9->SetFocus();
$win2->Edit10->SetFocus();
$win2->Edit11->SetFocus();

$win1->Show();        #显示窗口

$win2->Show();

Win32::GUI::Dialog();
Win32::GUI::Show($DOS);        #程序运行结束后让dos界面重新显示

exit(0);

##########################        某些子函数        #############################

sub mainWindow1_Terminate {    
    return -1;
}

sub mainWindow2_Terminate {
    return -1;
}

sub ResetSms_Click {    #对“重置”按钮设置功能,也就是将发送端短信输入框中内容清零

    $win1->Edit2->Text("");
}

sub SentSms_Click {        #对“发送”按钮设置功能

    my $text1 = $win1->Edit1->Text;        #获取文本框中的内容

    my $text2 = $win1->Edit2->Text;
    my $filename = localtime();            #获取系统时间

    $filename =~ s/:/-/g;                #由于要用系统时间来作为文件名存储短信,所以需要改成合适的表示方式

    $filename = $filename.'.txt';

    open FILE, ">", "sms\\$filename" || die "Cannot open file: $!";
    print FILE $text1,"\n",$text2;        #存储原始短信

    close(FILE);
    
    $win1->Edit2->Text("发送中……");
    $win2->Edit3->Text("");            #每次发短信,都要将见面上原来的痕迹先擦除

    $win2->Edit4->Text("");
    $win2->Edit5->Text("");
    $win2->Edit6->Text("");
    $win2->Edit7->Text("");
    $win2->Edit8->Text("");
    $win2->Edit9->Text("");
    $win2->Edit10->Text("");
    $win2->Edit11->Text("");

    main($text2);    #调用主体函数main(),实现对短信的操作

    display_osms($text1, $text2, $filename);    #显示原始短信

    $win1->Edit2->Text("发送成功!");
}

sub display_osms {            #显示原始短信

    my $num = $_[0];
    my $sms = $_[1];
    my $filename = $_[2];
    $filename =~ s/-/:/g;
    $filename =~ s/.txt//;
    $win2->Edit3->Text($num);
    $win2->Edit4->Text($filename);
    $win2->Edit5->Text($sms);
}

###############################    主函数    ########################

sub main {
    my $sms = $_[0];        #接收短信内容

    
    $sms = tel($sms);            #先查看短信中是否有电话号码并操作

    $sms = event_time($sms);    #查看短信中事件的时间信息并操作

    $sms = participle($sms);    #对消去电话号码和事件时间后的短信分词

    event_main($sms);            #查找事件的地点和动作

        
    sub tel {            #短信中电话号码操作

        my $tel;
        my $i;
        my $line = $_[0];
        chomp($line);
        while ($line =~ /([0-9|+][0-9]*-?[0-9]+)/g) {    #正则匹配

            $tel = $1;
            if (length($tel) >= 5 && length($tel) <= 20) {    #设定长度的范围在5和20之间

                $line =~ s/$tel//;                        #将原始短信消去电话号码的部分

                if ($tel =~ /^(13|18|15|\+8613|\+8618|\+8615)/) {    #如果符合这些规则,则判为手机号码

                    $win2->Edit6->Text($tel);
                }
                else {                #否则,都判为座机号码

                    $win2->Edit7->Text($tel);
                }
            }
        }
        return $line;
    }

    sub event_time {        #对短信中事件发生时间操作

        my $_2 = "3-9-10";        #创建状态转移表

        my $_8 = "9-10";
        my $_9 = "11-12-9-10";
        my @tran = (["4", "2", "7", "7", "7", "7", "8", "8", "8", "5", "6", "6", $_8, "3", "7"],["wait", "wait", "wait", "wait", "wait", "wait", "wait", "wait", "wait"],[$_2, $_2, $_2, $_2, $_2, $_2, $_2, $_2, $_2, $_2, $_2, $_9, "wait"],["2"],["wait"],["wait"],["wait", "wait", "wait", "wait"],["wait", "wait"],["10", "wait", "wait", "wait"],["10", "10", "wait", "10", "wait", "10", "wait", "wait"],[$_9],["13","13"],["14"],["end"],["end","end","15", "wait"]);
        my %hash;
        my @line;
        my $line;
        my $j = 0;
        my $k;
        my $m;
        my $sms = $_[0];
        my $time = "";

        open FILE, "<", "time.txt" || die "Cannot open file: $!";
        while (<FILE>) {
            chomp;
            $line = decode("gbk", $_);
            @line = split (/ /, $line);
            for ($k = 0; $k < @line; ++ $k) {
                $hash{$j + 1}{$line[$k]} = $tran[$j][$k];
            }
            ++ $j;
        }
        close(FILE);

        chomp($sms);
        $line = decode("gbk", $sms);
        @line = split(//, $line);        #将短信按字分开存入数组,然后使用状态机,逐字查看

        $m = 0;
        hello(-1, 0);    #调用函数


        sub hello {        #有限状态机核心算法

            my $index = $_[0];    #字符串上的下标

            my $state = $_[1];    #状态号

            my @next;
            my $i;
            while ($index + 1 < @line) {    #遍历直到找到被接受的字符串或者到达原字符串的最后

                if ($state == 0) {        #如果$state

                    @next = (1, 3);        #时间的第一个字必然在状态1或者状态3

                    for ($i = 0; $i < @next; ++ $i) {    
                        if ($line[$index + 1] =~ /[0-9]/ || exists $hash{$next[$i]}{$line[$index + 1]}) {
                            $time = $time.encode("gbk", $line[$index + 1]);
                            $state = $next[$i];
                            hello($index + 1, $state);
                            last;
                        }
                    }    
                }
                else {
                    if ($line[$index] =~ /[0-9]/) {
                        @next = split (/-/, $hash{$state}{"[0-9]"});
                    }
                    else {
                        @next = split (/-/, $hash{$state}{$line[$index]});
                    }
                    for ($i = 0; $i < @next; ++ $i) {
                        if ((exists $hash{$next[$i]}{"[0-9]"} && $line[$index + 1] =~ /[0-9]/ ) || exists $hash{$next[$i]}{$line[$index + 1]}) {
                            $time = $time.encode("gbk", $line[$index + 1]);
                            $state = $next[$i];
                            hello($index + 1, $state);
                        }
                        else{
                            if ($next[$i] eq "end") {
                                $m = 1;
                                last;
                            }
                            elsif ($next[$i] eq "wait") {
                                if ($line[$index + 1] =~ /[0-9]/ || exists $hash{3}{$line[$index + 1]}) {
                                    $time = $time.encode("gbk", $line[$index + 1]);
                                    $state = 3;
                                    hello($index + 1, $state);
                                }
                                elsif (exists $hash{1}{$line[$index +1]}) {
                                    $time = $time.encode("gbk", $line[$index + 1]);
                                    $state = 1;
                                    hello($index + 1, $state);
                                }
                                elsif (exists $hash{15}{$line[$index + 1]}) {
                                    $time = $time.encode("gbk", $line[$index + 1]);
                                    $state = 15;
                                    hello($index + 1, $state);
                                }
                                else {
                                    $m = 1;
                                    last;
                                }
                            }
                        }
                        if ($m == 1) {
                        last;
                        }
                    }
                }
                if ($m == 1) {
                    last;
                }
            ++ $index;
            $state = 0;
            $time = "";
            }
        }
        if ($time ne "") {    #如果找出时间了,则在界面中显示出来

            $win2->Edit9->Text($time);
        }
        $sms =~ s/$time//;
        return $sms;
    }

    sub participle {        #用前向最大匹配算法分词

        my %hash;        #用于存放词表的哈希表

        my $line;        
        my $f1;    
        my $fs;
        my $fw;
        my $sms = $_[0];

        open FILE,"vocabulary.txt" || die "Cannot open file: $!";
        while (<FILE>) {    
            chomp;
            $line=decode("gbk",$_);    #用gbk编码

            $hash{$line}='1';
        }
        close(FILE);
        
        $f1=decode("gbk",$sms);        #用gbk编码

        $fs="";            #用来存放每段切分好了的文本

        while ($f1) {
            $fw=substr $f1,0,4;     #将前四个字(包括标点)作为候选字符串$fw

            while (!(exists $hash{$fw})&&(length $fw)!=1) { #当$fw在词表中没匹配成功且长度大于单字时

                $fw=substr $fw,0,((length $fw)-1);        #将$fw最右边一个字去掉

            }
            $fs=$fs.$fw." ";
            $f1=substr $f1,(length $fw),(length $f1);    #将待切分字符串去掉已经匹配成功的候选字符串

        }            
        return encode("gbk", $fs);
    }

    sub event_main {
        my @line;
        my %hash;
        my $i;
        my $j;
        my $k;
        my @v;
        my @a;
        my $line;
        my $ad;
        my $veb;
        my $maxlen = 2;
        my @sign = qw(学校 大学 中学 小学 街 路 门 楼 国 省 市 区 镇 村);    #以这些字词作尾的就判为地点

        my $sms = $_[0];
        my $filename = $_[1];

        open FILE, "<", "parse.txt" || die "Cannot open file: $!";    #读入训练好了的规则库

        while (<FILE>) {
            chomp;
            @line = split (/\//, $_);
            $hash{$line[0]} = $line[1];
        }
        close(FILE);

        @line = split (/\s+/, $sms);

        for ($i = 0; $i < @line; ++ $i) {        #找出词性为动词的词

            if ((exists $hash{$line[$i]}) && ($hash{$line[$i]} eq "v")) {
                push(@v, $i);
            }
            for ($j = 0; $j < @sign; ++ $j) {
                if ($line[$i] =~ /$sign[$j]$/) {
                    push(@a, $i);
                }
            }
        }

        if (@a > 0) {    #如果找出了地点

            my $ad = "";
            $j = 0;
            for ($i = 0; $i < @a; ++ $i) {
                if ($a[$i] - $j > $maxlen) {
                    $ad = $ad.' ';
                    for ($k = $a[$i] - $maxlen; $k <= $a[$i]; ++ $k) {
                        $ad = $ad.$line[$k];
                    }            
                }
                else {
                    for ($k = $j; $k <= $a[$i]; ++ $k) {
                        $ad = $ad.$line[$k];
                    }
                }
                $j = $a[$i] + 1;
            }
            $win2->Edit10->Text($ad);    #在界面中显示出来

        }

        if (@v > 0) {        #如果找到了动词

            $veb = "";
            for ($i = 0; $i < @v; ++ $i) {
                $veb = $veb.$line[$v[$i]].' ';
            }
            $win2->Edit11->Text($veb);    #在界面中显示出来

        }
    }
}

相关阅读 更多 +
排行榜 更多 +
mirrox模组(玩家自制)手机版下载

mirrox模组(玩家自制)手机版下载

休闲益智 下载
集装箱模拟器手机版下载安装

集装箱模拟器手机版下载安装

模拟经营 下载
哔咔漫画app下载免费2025

哔咔漫画app下载免费2025

浏览阅读 下载