Matlab 防止;输入“;函数调用函数或访问变量
考虑到以下代码Matlab 防止;输入“;函数调用函数或访问变量,matlab,input,user-input,Matlab,Input,User Input,考虑到以下代码 x = input('Input an array: '); 如果用户键入[1 2 3],变量x将被分配该数值向量。类似地,如果它们键入{1[23],'abc'},变量x将是包含这些值的单元格数组。好的 现在,如果用户键入[sqrt(2)sin(pi/3)],变量x将被分配结果值:[1.414213562373095 0.866025403784439]。这是因为所提供的数据是通过以下方式评估的: 输入提示用户输入 result=input(prompt)在屏幕上显示promp
x = input('Input an array: ');
如果用户键入[1 2 3]
,变量x
将被分配该数值向量。类似地,如果它们键入{1[23],'abc'}
,变量x
将是包含这些值的单元格数组。好的
现在,如果用户键入[sqrt(2)sin(pi/3)]
,变量x
将被分配结果值:[1.414213562373095 0.866025403784439]
。这是因为所提供的数据是通过以下方式评估的:
输入
提示用户输入result=input(prompt)
在屏幕上显示prompt
字符串,等待
对于键盘输入,计算输入中的任何表达式,
并返回结果中的值。[……]
这可能会导致问题。例如,如果用户键入addpath('c:\path\to\folder')
作为输入,会发生什么?因为输入是经过计算的,所以它实际上是一个
该命令将由Matlab执行。因此,用户可以在路径中添加文件夹。更糟糕的是,如果他们输入路径(“”)
,路径将有效地变为零,Matlab将停止正常工作
另一个潜在的问题来源是
[…]要计算表达式,input
访问当前工作区中的变量
例如,如果用户输入的fprintf(1,'%f',varname)
和varname
是现有的数值数组,则用户将知道其当前值
这种行为可能是故意的。Matlab程序的用户在输入数据时是受信任的,就像他们被信任不按Control-C停止程序一样(然后发出所有命令或检查所有他们喜欢的变量!)
但在某些情况下,程序员可能希望有一个更“安全”的输入功能,我的意思是
在评估用户时防止任何函数调用
输入;及
防止输入访问程序变量
因此[12]
将是有效的输入,但是[sqrt(2)sin(pi/3)]
或路径(“”)
将不会因为第1项而生效;而[1 2 3 varname(1)]
也将因第2项而无效。我发现了一个不太令人满意的解决方案(我想了解一个更好的解决方案)。它使用一个半文档化的功能,并意味着将用户输入保存到一个临时文件。中提到的函数是getcallinfo
。根据帮助获取CallInfo
:
getcallinfo
返回被调用函数及其第一行和最后一行
此函数不受支持,可能会更改或删除,而无需
请在将来的版本中注意
此函数解决问题1(防止函数调用)。至于问题2(阻止访问变量),在函数中计算输入就足够了,这样就看不到其他变量了。显然(参见下面的示例2),getcallinfo
不仅检测调用的函数,还检测变量。无论如何,在函数的隔离范围内进行计算可能是个好主意
程序如下:
使用输入的字符串版本来防止计算:
x = input('Input an array: ', 's');
将字符串保存到文件:
filename = 'tmp.m';
fid = fopen(filename,'w');
fprintf(fid, '%s',x);
fclose(fid);
使用getcallinfo
检查输入字符串以检测可能的函数调用:
gci = getcallinfo(filename);
if ~isempty(gci.calls.fcnCalls.names)
%// Input includes function calls: ignore / ask again / ...
else
x = evalinput(x); %// evaluate input in a function
end
其中evalinput
是以下函数
function x = evalinput(x)
x = eval(x);
例1
考虑
x = input('Input an array: ', 's');
用户输入
[sqrt(2) sin(pi/3)]
然后
生成非空的gci.calls.fcnCalls.names
>> gci.calls.fcnCalls.names
ans =
'sqrt' 'sin' 'pi'
这告诉我们,如果进行计算,用户输入将调用函数sqrt
、sin
和pi
。请注意,诸如/
之类的运算符不会被检测为函数
例2
用户输入
[1 y y.^2]
然后
产生
>> gci.calls.fcnCalls.names
ans =
'y' 'y'
因此,变量被getcallinfo
检测,就好像它们是函数一样。如果我正确理解了您的问题,就可以使用正则表达式来完成您要做的事情
没有函数或变量调用
最简单的方法是检查输入字符串中是否没有字母字符。对于包含输入的x
,表达式将是:
expr = '[a-zA-Z]';
x = input('Input an array: ', 's');
valid = isempty(regexp(x,expr));
仅此一点就适用于上面给出的几个示例
允许某些函数或变量
'[1+2i, 34e12]'
'''this is a path'''
'[cos(5), sin(3+2i)]'
'[1+2ii, 34e12]'
'this is not a path'
'''this is a path'' this is not'
假设您希望允许用户访问一些变量或函数,可能是简单的trig函数,或pi
或您拥有的其他函数,那么它就不再那么简单了。我一直在玩弄下面这样的表达:
expr='(?!cos\(| pi | sin\()[a-zA-Z]+
但是它并没有达到预期的效果。它将在(
insin
中匹配。如果你比我更了解regex,你可以通过按摩使其正常工作
否则,另一种方法是:
isempty(regexp(regexprep(x,'(sin\(|cos\(|pi|x)',''),expr))
这样您就可以删除感兴趣的字符串
希望这有帮助
更新:为了允许虚拟/exp值和路径
'[1+2i, 34e12]'
'''this is a path'''
'[cos(5), sin(3+2i)]'
'[1+2ii, 34e12]'
'this is not a path'
'''this is a path'' this is not'
要匹配的新表达式变为
expr = '[iIeE][a-zA-Z]+';
这忽略了i/i和e/e(您可以根据自己的需要进行扩展)。您也可以通过切换到\{2,}
,来限制两个字符,尽管i-people仍然可以使用一个字符的匿名函数
检查输入的另一部分变成:
isempty(regexp(regexprep(x,'(sin\(|cos\(|pi|x|''(.*?)'')',''),expr))
现在您可以排除自定义函数(您可以始终将其作为一个数组,并通过|
将它们连接在一起)和路径
以下是一些与常规测试一起测试的示例:
通过
'[1+2i, 34e12]'
'''this is a path'''
'[cos(5), sin(3+2i)]'
'[1+2ii, 34e12]'
'this is not a path'
'''this is a path'' this is not'
失败
'[1+2i, 34e12]'
'''this is a path'''
'[cos(5), sin(3+2i)]'
'[1+2ii, 34e12]'
'this is not a path'
'''this is a path'' this is not'
感谢分享!如果只是关于读取一组数字,您可以再次