Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何解析表达式'^#[0-9A-F]{2}\$[0-9A-F]{4}/$';在perl中有效地_C_Perl_Parsing_Scanf - Fatal编程技术网

C 如何解析表达式'^#[0-9A-F]{2}\$[0-9A-F]{4}/$';在perl中有效地

C 如何解析表达式'^#[0-9A-F]{2}\$[0-9A-F]{4}/$';在perl中有效地,c,perl,parsing,scanf,C,Perl,Parsing,Scanf,我必须解析GIA10N模块返回的数据字符串。响应字符串由带模式的9字节ASCII码组成 ^[0-9A-F]{2}\$[0-9A-F]{4}/$ 说明: 数字123456789 代码#FF$DDDD/ #--响应令牌 FF——功能代码00-FF $--分隔符 DDDD——数据值0000-FFFF /--终端符号 例如: #0A$F831——表示函数0A中的值-1999 通常,sscanf函数将在C中完成解码该字符串的工作 #包括 int-parseData(字符*数据,int-prn){

我必须解析GIA10N模块返回的数据字符串。响应字符串由带模式的9字节ASCII码组成

^[0-9A-F]{2}\$[0-9A-F]{4}/$

说明:

数字123456789
代码#FF$DDDD/
#--响应令牌
FF——功能代码00-FF
$--分隔符
DDDD——数据值0000-FFFF
/--终端符号
例如:

#0A$F831——表示函数0A中的值-1999
通常,sscanf函数将在C中完成解码该字符串的工作

#包括
int-parseData(字符*数据,int-prn){
字符ff[3]=“0”;
无符号int-udddd=0;
int-sdddd=0;
如果(sscanf(数据“#%2s$%X/”、ff和udddd)!=2){
printf(“分析%s\n”数据时出错);
返回0;
}
sdddd=(int)udddd;
if(sdddd和0x8000)
sdddd-=0x10000;
如果(prn)
printf(“代码:%s已解析:%s%d\n”,数据,ff,sdddd);
返回1;
}
int main(int argc,字符**argv)
{
parseData(#0A$F831/”,1);
返回0;
}
使用运行时:

$gcc测试扫描.c-o测试扫描
$time./testsprintf
代码:#0A$F831/已解析:-1999
实0.003s
用户0.000s
系统0m0.000s
在perl中,与格式%X联合使用的函数sscanf是不可用的。我必须定制和拆分消息,并执行十六进制/16位转换魔术,这要慢得多

#/usr/bin/env perl
使用警告;
严格使用;
子解析数据($$){
我的($msg,$print)=@;
我的($ff,$dddd)=拆分/\$/,子字符串($msg,1,长度($msg)-2);
$dddd=十六进制($dddd);
如果$dddd&0x8000,则$dddd-=0x10000;
printf“代码:%s已分析:%s%d\n”、$msg、$ff、$ddddd
如果$print;
}
解析数据('#0A$F831/',1);
检查perl运行时:

$time./test-scan.pl
代码:#0A$F831/解析:0A-1999
实0.012s
用户0m0.008s
系统0m0.000s
我想知道有没有其他方法可以在不使用其他语言的情况下加快速度

附录

根据和的答案和概念以及我的方法:


#!/usr/bin/env perl
使用警告;
严格使用;
使用基准qw(CMP准则);
我的%tests=(
ike=>q{
我的($ff,$dddd)=$msg=~m{^#([0-9A-F]{2})\$([0-9A-F]{4})/\z}
或死亡(“错误解析\“$msg\”\n”);
$dddd=十六进制($dddd);
},
哈克=>q{
(我的($ff,$dddd)=拆分(/\$/,子字符串($msg,1,长度($msg)-2))==2
或死亡(“错误解析\“$msg\”\n”);
$dddd=十六进制($dddd);
},
pbear=>q{
my($ff,$dddd)=解包($xA2xA4',$msg);
$dddd=十六进制($dddd);
},
);
$\=“use strict;use warnings;我们的\$msg;for(1..1000){$\}”
对于%测试值;
本地我们的$msg='#0A$F831/';
cmpthese(-3,\%测试);
我得到了以下基准结果:

/usr/bin/perl-w“bench cvx data.pl”
艾克·哈克·佩尔
ike 1070/s--33%-41%
哈克1596/s 49%--12%
pbear 1816/s 70%14%--
^[0-9A-F]{2}\$[0-9A-F]{4}/$
匹配9或10个字符。我想你是说

^#[0-9A-F]{2}\$[0-9A-F]{4}/\z

您的代码简化为以下内容:

my($ff,$ddddd)=$msg=~m{^#([0-9A-F]{2})\$([0-9A-F]{4})/\z}
或死亡(“错误解析\“$msg\”\n”);
$dddd=十六进制($dddd);
也就是说,这比你的版本慢。不过,它的可读性要高得多

以下内容与我的一样可读,与你的一样快,但不可验证:

my($ff,$ddddd)=解包('x a2 x a4',$msg);
$dddd=十六进制($dddd);

也就是说,为我加载
perl
只需要12毫秒(尽管在不同的机器上只有5毫秒)

$time perl-e1
实0.012s
用户0m0.016s
系统0m0.000s
是否正在尝试优化耗时不到1毫秒的内容

所以我写了一个基准。对我来说

  • 您的版本使用了1/1232000 s=0.81μs
  • 我的版本使用了1/636000 s=1.3μs
基准:

使用警告;
严格使用;
使用基准qw(CMP准则);
我的%tests=(
ike=>q{
我的($ff,$dddd)=$msg=~m{^#([0-9A-F]{2})\$([0-9A-F]{4})/\z}
或死亡(“错误解析\“$msg\”\n”);
$dddd=十六进制($dddd);
},
哈克=>q{
(我的($ff,$dddd)=拆分/\$/,子字符串($msg,1,长度($msg)-2))==2
或死亡(“错误解析\“$msg\”\n”);
$dddd=十六进制($dddd);
},
);
$\=“use strict;use warnings;我们的\$msg;for(1..1000){$\}”
对于%测试值;
本地我们的$msg='#0A$F831/';
cmpthese(-3,\%测试);
代表性产出:

给艾克·哈克评分 ike 752/s--39% 哈克1232/s 64%--
在OP的code
sscanf
中,假设输入数据具有恒定的字段宽度

对于这种结构化输入数据,函数
unpack
是一个很好的选择

use strict;
use warnings;
use feature 'say';

my $in = '#0A$F831/';

my($hex_func,$hex_val) = unpack('xA2xA4',$in);
my $value = hex $hex_val;

$value = (($value^0xFFFF)+1)*-1 if $value & 0x8000;

say "
    Function: $hex_func
    Value:    $value
";
输出


    Function: 0A
    Value:    -1999


谢谢,这在相同的运行时间下运行良好且优雅,但我如何补偿sscanf%X问题。您指的是什么问题?谢谢您编写的时间计算实验非常鼓舞人心。我必须处理两个问题。1用于传感器现场的迁移(运行多条RS485总线)。由于验证特性和易于编写的网络通信特性,我想使用perl环境。旧的实现是在工业PC上编写的(运行XP/cygwin的2000er)。2.我想将这种技术/逻辑迁移到更小的嵌入式linux设备上,时钟频率更低,如果我能离开C prog,我就不是舒尔了