我正在TCL中创建一个登录程序。我有以下代码:
package require Tk
set usr [open "$env(HOME)\\AppData\\Roaming\\basicfile\\USR.txt" r]
set pwd [open "$env(HOME)\\AppData\\Roaming\\basicfile\\PWD.txt" r]
set numtries [expr 3.0]
proc log {} {
if {$::numtries > 0.0} {
if {[.e get] == [read $::usr]} {
if {[.e1 get] == [read $::pwd]} {
close $::usr
close $::pwd
pack forget .l
pack forget .e
pack forget .l1
pack forget .e1
pack forget .b
.l configure -text "Login Successful!"
pack .l
} else {
set ::numtries [expr $::numtries - 1.0]
if {$::numtries <= 0.0} {
.b configure -state disabled
}
}
} else {
set ::numtries [expr $::numtries - 1.0]
if {$::numtries <= 0.0} {
.b configure -state disabled
}
}
} else {
.b configure -state disabled
}
if {$::numtries <= 0.0} {
.b configure -state disabled
}
}
ttk::label .l -text "Enter your name:"
ttk::entry .e
ttk::label .l1 -text "Enter your password:"
ttk::entry .e1 -show "*"
ttk::button .b -text "Login" -command log
pack .l
pack .e
pack .l1
pack .e1
pack .b
此程序打开一个文件夹basicfile
,位于Windows的AppData文件夹中。当它运行时,应用程序工作正常,除了一件事。看似错误的一行是set numtries [expr 3.0]
。程序是这样的,如果用户名和密码不正确,则从该变量中减去,如果变量达到0,则禁用该按钮。但是,当我运行程序并在输入框中使用错误的用户名和密码按三次按钮时,它会转到行.l configure -text "Login Successful!"
并绕过登录部分。我的问题是,为什么它忽略了登录代码并仍然进入?我还应该提一下,如果我将行set numtries [expr 3.0]
更改为set numtries [expr 2.0]
,程序运行正常。谢谢!
答案 0 :(得分:2)
问题可能是这个。 read
命令一次读取整个文件,因此下次从文件中读取时会得到空字符串。如果您的名称和密码字段为空,则它们将等于从您的文件中读取的空字符串,并且登录将成功。
这样的事情应该有效:
set dir $env(HOME)/AppData/Roaming/basicfile
set uf [open [file join $dir USR.txt]]
set pf [open [file join $dir PWD.txt]]
set usr [read -nonewline $uf]
set pwd [read -nonewline $pf]
close $uf
close $pf
set numtries 3
ttk::label .nl -text "Enter your name:"
ttk::entry .ne
ttk::label .pl -text "Enter your password:"
ttk::entry .pe -show "*"
ttk::button .b -text "Login" -command log
pack {*}[winfo children .]
proc log {} {
global numtries usr pwd
if {[incr numtries -1] > 0} {
if {([.ne get] eq $usr) && ([.pe get] eq $pwd)} {
destroy {*}[winfo children .]
ttk::label .l -text "Login successful"
pack .l
} else {
.ne delete 0 end
.pe delete 0 end
}
} else {
destroy {*}[winfo children .]
ttk::label .l -text "Too many tries"
pack .l
}
}
如果你有一个旧的,过时的Tcl版本,pack {*}[winfo children .]
和eq
运营商不会工作:尝试eval pack [winfo children .]
(同样使用destroy
)和而是==
。或者更好的是,升级。
文档:close,destroy,file,global,if,incr,open,{{3 }},pack,proc,read,set,ttk::button,ttk::entry,ttk::label
答案 1 :(得分:0)
package require Tk
set usr [open "usr.txt" r]
set pwd [open "pwd.txt" r]
set numtries 3
proc log {} {
puts "Attempt # $::numtries"
if {$::numtries <= 0} {
close $::usr
close $::pwd
.l configure -text "Max retries exceeded..."
.b configure -state disabled
pack forget .e
pack forget .e1
return
}
if {([.e get] != [gets $::usr]) || \
([.e1 get] != [gets $::pwd])} {
incr ::numtries -1
return
}
.l configure -text "Login Successful!"
pack forget .e
pack forget .e1
pack forget .b
close $::usr
close $::pwd
}
ttk::label .l -text "Enter your name:"
pack .l
ttk::entry .e
ttk::entry .e1
pack .e
pack .e1
button .b -text submit -command log
.b configure -state active
pack .b