0

关于投票
学习Tcl(续六)——纠正自己一个错误的概念

    在《学习Tcl(续四)》中我给出了一个在String和Binary类型之间转换的程序。编写这一程序的目的是为了区分Tcl中使用这两种数据类型时的差异,并且通过编写程序的方式提供一个实际的应用方法。 riple

    但是这个程序是错误的,程序中提到的String和Binary类型刚好相反。这一点是我在昨晚练习创建二进制文件时发现的。我按照错误的方法创建的文件是预期文件大小的两倍。想一想为什么。 riple

    正确的程序如下: riple

set string_type [lindex $argv 0]
puts "string type : $string_type"
set numeric_type [binary format "H2" $string_type]
puts "numeric type : $numeric_type"
binary scan $numeric_type "H*" string_again
puts "string again : $string_again"
set numeric_again [binary format "H2" $string_again]
puts "numeric again : $numeric_again"

    当时导致我颠倒这两个概念的原因是:我认为能够显式地输出为数值的数据类型就是二进制类型,我认为puts会如实地把数据的原本形式输出到用户界面。 riple

    先说第一个错误认识:能够显式地输出为数值的数据类型其实是String,是显示为数值的String。 riple

    再说第二个错误认识:puts,顾名思义,是put string的意思。puts输出的内容,采用文本方式查看,都是String类型的。而我从用户界面和记事本里看到的,恰好都只能是字符,而不是二进制。查看二进制文件需要在类似UltraEdit的软件中,使用HEX方式打开文件。 riple

    综合上述认识,可以认为,通过用户界面和记事本看到的数据,如果和输入的原数据一模一样的话,那么原数据类型是String;反之,如果查看到的结果令人意外的话,那么原数据类型就多半是Binary的。 riple

    这本是一个很基本的概念,只是我在这些方面的知识不够扎实,造成了错误的,甚至是黑白颠倒的认识和理解。基本的概念并不等于清楚易懂的概念,甚至可能是被我误解的概念,而我还浑然不觉呢。 riple

    在此向可能被我误导的朋友道歉,并提醒被我误导的朋友,你在二进制数据类型上的认识可能也是不可靠的。 riple

    相关链接:Working with binary data riple

系统分类: CPLD/FPGA
用户分类: Tcl/Tk
标签: Tcl 二进制 字符串
来源: 原创
发表评论 阅读全文(1074) | 回复(0)

2

关于投票
学习Tcl(续五)

    这些天在编一个windows操作系统下接收和发送UDP包的程序,由于我C语言编程基础差,时间又紧,所以选择了Tcl作为编程语言。 riple

    在手头一本Tcl编程的书中查找了一下,只有TCP套接字编程的指导,没有UDP的相关内容。 riple

    眼前没有,只好到Tcl Developer Xchange上“大海捞针”一下。相关的内容还真不少,顺着前面几个链接,我终于找到了UDP相关的内容。到Xchange上搜索,真是一个学习、开发Tcl的好方法。 riple

    在Tcl的标准发布包内是没有直接对UDP操作的命令的,需要下载一个TclUDP包,在程序中包含这个包即可。 riple

    经过两天的分解、重组、拷贝、粘贴、尝试和失败,终于把示例程序中提供的程序修改成了我需要的能够连续接收、响应的简单UDP服务器程序。 riple

    Tcl编程中的高级功能(如加载包、事件驱动编程、套接字编程)和几个重要但是难懂的操作(如从用户输入中提取参数、列表操作),以前我是敬而远之的,这次也不得不硬着头皮一一“磨”了下来。学习一门编程语言还是要“躬行”才能学得快啊。 riple

    现在看来,当初觉得很难的UDP网络收发包也不是那么难。分析清楚了,和Tcl下对文件的操作差不多。 riple

   

    从本机特定端口向目标机特定端口发送特定包的程序:udp_send.tcl

package require udp 1.0.6

proc Event {sock} {
    global forever
    global pkt
    global peer
    set pkt [read $sock]
    set peer [fconfigure $sock -peer]
    puts "Received [string length $pkt] from $peer\n$pkt"
    set forever 1
    return
}

set forever 0
# parse input arguments
if {[lindex $argv 2]    == ""} {
    puts "\n"
    puts "usage: quartus_sh -t udp_send.tcl -srcport -host -desport -msg"
    puts "\n"
} else {
  # parse input arguments
    set srcport [lindex $argv 0]
    set host    [lindex $argv 1]
    set desport [lindex $argv 2]
    set msg     [lindex $argv 3]
  # open udp   
    set s [udp_open $srcport]
    fconfigure $s -blocking 0 -buffering none -translation binary \
        -remote [list $host $desport]
    fileevent $s readable [list Event $s]
  # send message
    if {$msg == {}} {
        for {set i 0} {$i < 512} {incr i 1} {
        append loop_hello "hello"
        }
        puts -nonewline $s $loop_hello
    } else {
        puts -nonewline $s $msg
   
    }
  # close udp
    close $s
}

    监听本机特定端口UDP包,接受后根据发送机IP和端口返回特定信息的程序:udp_reply.tcl

package require udp 1.0.6

proc Event {sock} {
    global forever
    global pkt
    global peer
    set pkt [read $sock]
    set peer [fconfigure $sock -peer]
    puts "Received [string length $pkt] from $peer\n$pkt"
    set forever 1
    return
}

set forever 0

# parse input arguments
  if {[lindex $argv 0] == ""} {
    puts "\n"
    puts "usage: quartus_sh -t udp_reply.tcl -port"
    puts "\n"
  } else {
    # open udp
      set s [udp_open [lindex $argv 0]]
      fconfigure $s -blocking 0 -buffering none -translation binary
   
    # listen to required port
      puts "\n"
      puts "listenning to local port [lindex $argv 0]"
      fileevent $s readable [list Event $s]
      vwait ::forever
     
    # reply to sender host and port
      fconfigure $s -remote [list [lindex $peer 0]  [lindex $peer 1]]
      puts  -nonewline $s hello
      puts "replied remote peer $peer"
      puts "\n"
   
    # close udp
      close $s
  }

系统分类: CPLD/FPGA
用户分类: Tcl/Tk
标签: Tcl UDP
来源: 原创
发表评论 阅读全文(629) | 回复(4)

2

关于投票
学习Tcl(续四)

    进行string和对应数值之间转换的小程序 riple

set numeric_type [lindex $argv 0]
puts "\noriginal numbr in hex : $numeric_type"

set string_type [binary format "H2" $numeric_type]
puts "transformed to string : $string_type"

binary scan $string_type "H*" numeric_again
puts "transformed to number : $numeric_again"

set string_again [binary format "H2" $numeric_again]
puts "transformed to string : $string_again\n"

 

    进行长串数值和string之间转换的小程序 riple

    puts "\n"
set hex_num [lrange $argv 0 end]
    puts "number inputed : $hex_num"
set hex_len [expr [string length $hex_num]/2]
    puts "number length : $hex_len"
for {set i 0} {$i < $hex_len} {incr i 1} {
    set hex_byte [string range $hex_num [expr $i*2] [expr $i*2+1]]
    puts "number [expr $i+1]: $hex_byte"
    append str_ing [binary format "H2" $hex_byte]
    puts "string appended : $str_ing"
}
 puts "\n"

系统分类: CPLD/FPGA
用户分类: Tcl/Tk
标签: 字符串 数值
来源: 原创
发表评论 阅读全文(601) | 回复(1)

3

关于投票
学习Tcl(续三)

    一个把十六进制数转换为十进制数的小程序: riple

proc h2d {{hex_num 0}} {
  set tmp1 0x
  append tmp1 $hex_num
  set tmp2 [format "%d" $tmp1]
  return $tmp2
}

 

    一个读取二进制文件的小程序: riple

# Show current directory
set tmp [pwd]
puts "\n Current dir : $tmp"
# Open file
puts "\n Type in the file name"
gets stdin disk_file_name
set disk_file_fileid [open "$disk_file_name" "r"]
fconfigure $disk_file_fileid -translation binary
# Main loop
while {1} {
    # Set read original address                           
    puts "\n Type in the addrByte"
    gets stdin addrByte
    seek $disk_file_fileid $addrByte start                           
    # read binary                           
    puts "\n Type in the numByte"
    gets stdin numByte
    set disk_read [read $disk_file_fileid $numByte]
    binary scan $disk_read "H*" tmp0
    puts "\nReturned [expr [string bytelength $tmp0] / 2] Byte(s) : "
    puts "$tmp0"
    puts "\n"

}
# Close file
close $disk_file_fileid

 

    一个顺序执行初始化、写入、读出的交互式创建文件的小程序 riple

proc wr_file {{file_id} {Byte_content 5A} {Byte_num 512}} {
  set loop_end $Byte_num
  set loop_num 0
  while {$loop_num < $loop_end} {
    puts -nonewline $file_id $Byte_content
    set loop_num [expr $loop_num + 1]
  }
  flush $file_id
}

proc rd_file {{file_id} {Byte_num 512}} {
  return [read $file_id [expr $Byte_num * 2]]
}

# show current directory
  set tmp [pwd]
  puts "\n Current dir : $tmp"
# open file
  file mkdir disk_sector
  puts "\n Type in the file name"
  gets stdin disk_file_name 
  set disk_fileid [open "disk_sector/$disk_file_name" "w+"]
  fconfigure $disk_fileid -translation binary
# init file
  puts "\n INIT FILE"
  puts "\n Type in the Byte content"
  gets stdin Byte_content
  puts "\n Type in the Byte number"
  gets stdin Byte_num
  wr_file $disk_fileid $Byte_content $Byte_num
# write file
  puts "\n WRITE FILE"
  puts "\n Type in the Byte content"
  gets stdin Byte_content
  puts "\n Type in the Byte address"
  gets stdin Byte_addr
  puts "\n Type in the Byte number"
  gets stdin Byte_num
 
  seek $disk_fileid [expr $Byte_addr * 2] start
  wr_file $disk_fileid $Byte_content $Byte_num
# read file
  puts "\n READ FILE"
  puts "\n Type in the Byte address"
  gets stdin Byte_addr
  puts "\n Type in the Byte number"
  gets stdin Byte_num
 
  seek $disk_fileid [expr $Byte_addr * 2] start
  puts [rd_file $disk_fileid $Byte_num]

# close file
  close $disk_fileid

 

    文件访问权限: riple

    r+ :可取可存;文件必须已经存在。 riple

    w+ :先存后取;文件存在会被清空,文件不存在会被创建。 riple

系统分类: CPLD/FPGA
用户分类: Tcl/Tk
标签: Tcl 进制转换 文件读取
来源: 原创
发表评论 阅读全文(799) | 回复(0)