在Rust语言中,变量的生命周期与其作用域绑定,退出作用域时自动销毁。我们用一个简化模型来模拟这一过程:
“{” 和 “}” 表示新开和结束一个作用域;
每行要么是
let name
:在当前作用域声明变量 name
,drop name
:在当前作用域手动销毁变量 name
。离开一个作用域时,若有未被 $drop$
的变量,则自动按“后声明先销毁”顺序销毁。
在 Rust 语言中,一个变量的生命周期是与其变量的作用域绑定的,变量离开作用域时被自动销毁。
这里给出一个简单的模型;一对大括号为一个生命周期,除了括号之外,每一行包含以下两个操作之一:
let {var_ name} drop {var _ name}
其中:let 表示声明一个变量,{var_ name} 为变量名;drop 表示手动销毁一个变量,销毁的对象为变量名 {var_name} 。
其它规则:离开一个作用域时,如果有变量没有被drop显式销毁,则自动销毁,顺序规则是后声明的先销毁。
出错情况:
1.销毁了一个没有声明的变量。
2.一个已经声明的变量被手动 drop 超过一次。
第一行为一个数字 N ,表示后面待输入代码的行数。
其中:5<=N<=15000 。
{ 独占一行
} 独占一行
let 和变量名之间只有一个空格
drop 和变量名之间只有一个空格
变量名只包含大小写字母,长度为 [1,32]
输入约束:
1.全局每一行 let 声明变量的变量名都不相同。
2.用例中不会出现 drop 非同一作用域变量(包括父作用域)的情况。
3.除输入的第一行为行数,输入的第二行一定会是 '{' ,最后一行一定是'}' :即一定会显式声明一个最外层作用域。
4.每一行输入的行头可能有 0 个或者多个前导空格,let/drop 与变量名之间只有一个空格。
5.不会出现括号不成对匹配、变量名不符号要求等输入异常的场景,编码时不需要考虑括输入不正确的场景。
输出各变量的销毁顺序,以一个空格分隔
如果发生出错的情况,则将出错前成功释放的变量全部按要求打印出来之后,再接一个空格和一个固定字符串 “Error”,然后中止输出。
输入
6
{
let a
let b
let c
drop b
}
输出
b c a
说明
按行说明:
待输入的总代码行数为 6
新增第一个作用域
第一个作用域声明变量 a
第一个作用域声明变量 b
第一个作用域声明变量 c
显式销毁 b
离开第一个作用域,按声明反序,销毁 ca (因为 b 已经显式销毁)
输入
9
{
let a
let b
{
let c
}
drop b
drop d
}
输出
c b Error
说明
按行说明:
待输入的总代码行数为 9
新增第一个作用域
第一个作用域声明变量 a
第一个作用域声明变量 b
新增第二个作用域
第二个作用域声明变量 c
离开第二个作用域,按声明反序,自动销毁 c
显式销毁 b
显式销毁 d ,但是 d 在其所属的第一个作用域中还没有声明,报错退出
输入
12
{
let a
let b
{
let c
{
let d
let f
}
}
drop b
}
输出
f d c b a
说明
按行说明:
待输入的总代码行数为 12
新增第一个作用域
第一个作用域声明变量 a
第一个作用域声明变量 b
新增第二个作用域
第二个作用域 声明变量 c
新增第三个作用域
第三个作用域 声明变量 d
第三个作用域 声明变量 f
离开第三个作用域,按声明反序,销毁 f d
离开第二个作用域,按声明反序,销毁 c
显式销毁变量 b
离开第一个作用,按声明反序,销毁 a (因为b已经显式销毁)
输入
7
{
let a
{
drop a
}
}
输出
Error
说明
按行说明:
待输入的总代码行数为 7
新增第一个作用域
第一个作用域声明变量 a
新增第二个作用域
drop 变量 a ,但是 a 非本作用域变量(为其父作用域变量),出错。