gui - output matlab
Evitar que la funciĆ³n de "entrada" llame funciones o acceda a variables (2)
Si entiendo tu pregunta correctamente, es posible usar expresiones regulares para lograr lo que estás tratando de hacer.
Sin función o llamadas variables
En su forma más simple, esto comprueba para asegurarse de que no haya caracteres alfabéticos en la cadena de entrada. La expresión sería entonces, para x
contiene entrada:
expr = ''[a-zA-Z]'';
x = input(''Input an array: '', ''s'');
valid = isempty(regexp(x,expr));
Esto solo funciona para los pocos ejemplos que das arriba.
Permitir algunas funciones o variables
Supongamos que quiere permitir que el usuario acceda a algunas variables o funciones, tal vez funciones trigonométricas simples, o pi
o lo que tenga, entonces ya no es tan simple. He estado jugando con una expresión como la siguiente:
expr = ''(?!cos/(|pi|sin/()[a-zA-Z]+
Pero no hace exactamente lo que se espera. Coincidirá in(
en sin
. Si conoce la expresión regular mejor que yo, puede darle un masaje para que funcione correctamente.
De lo contrario, una alternativa sería hacer esto:
isempty(regexp(regexprep(x,''(sin/(|cos/(|pi|x)'',''''),expr))
para que elimines las cadenas que te interesan
Espero que esto ayude.
Actualización: para permitir valores imaginarios / exp, y rutas
La nueva expresión para coincidir se convierte
expr = ''[iIeE][a-zA-Z]+'';
Esto ignora i / I y e / E (puede aumentar esto como mejor le parezca). También puede hacer un límite de dos caracteres al cambiar a /{2,}
, aunque las personas todavía pueden tener funciones anónimas de un carácter.
La otra parte, para verificar la entrada se convierte en:
isempty(regexp(regexprep(x,''(sin/(|cos/(|pi|x|''''(.*?)'''')'',''''),expr))
ahora puede excluir funciones personalizadas (siempre puede tener esto como una matriz y unirlas mediante a |
) y rutas.
Aquí hay algunos ejemplos probados junto con el habitual:
Pases
''[1+2i, 34e12]''
''''''this is a path''''''
''[cos(5), sin(3+2i)]''
Falla
''[1+2ii, 34e12]''
''this is not a path''
''''''this is a path'''' this is not''
Teniendo en cuenta el siguiente código
x = input(''Input an array: '');
Si el usuario escribe [1 2 3]
, a la variable x
se le asignará ese vector numérico. De manera similar, si escriben {1, [2 3], ''abc''}
, la variable x
será una matriz de celdas que contiene esos valores. Multa.
Ahora, si el usuario escribe [sqrt(2) sin(pi/3)]
, a la variable x
se le asignarán los valores resultantes: [1.414213562373095 0.866025403784439]
. Eso es porque los datos proporcionados se evalúan por input
:
Indicación de
input
para la entrada del usuario.
result = input(prompt)
muestra la cadena deprompt
en la pantalla, espera la entrada del teclado, evalúa cualquier expresión en la entrada y devuelve el valor enresult
. [...]
Esto puede causar problemas. Por ejemplo, ¿qué ocurre si el usuario escribe addpath(''c:/path/to/folder'')
como entrada? Dado que la entrada se evalúa, en realidad es un comando que será ejecutado por Matlab. Entonces el usuario puede llegar a agregar una carpeta a la ruta. Peor aún, si ingresan la path('''')
, la ruta se cambiará efectivamente a nada y Matlab dejará de funcionar correctamente.
Otra posible fuente de problemas es que
[...] Para evaluar expresiones,
input
variables de acceso en el espacio de trabajo actual .
Por ejemplo, si el usuario fprintf(1,''%f'', varname)
y varname
es una matriz numérica existente, el usuario conocerá su valor actual.
Este comportamiento es probablemente por diseño. Los usuarios de un programa Matlab son de confianza cuando ingresan datos, al igual que se les confía que no presionen Control - C para detener el programa (¡y luego emiten todos los comandos o inspeccionan todas las variables que les gustan!).
Pero en ciertos casos, el programador puede querer tener una función de input
más "segura", con lo que quiero decir
- prevenir cualquier llamada a la función cuando se evalúa la entrada del usuario ; y
- evitar que la entrada acceda a las variables del programa .
Entonces [1 2]
sería una entrada válida, pero [sqrt(2) sin(pi/3)]
o la path''''
no lo haría a causa del ítem 1; y [1 2 3 varname(1)]
sería inválido debido al ítem 2.
He encontrado una solución no muy satisfactoria (y me gustaría leer acerca de una mejor). Utiliza una función semi documentada e implica guardar la entrada del usuario en un archivo temporal . La función, a la que se hace referencia en el blog de Yair Altman , es getcallinfo
. De acuerdo con help getcallinfo
:
getcallinfo
Devuelve funciones llamadas y sus primeras y últimas líneas
Esta función no es compatible y puede cambiar o eliminarse sin previo aviso en una versión futura.
Esta función resuelve el problema 1 (evita llamadas a funciones). En cuanto al problema 2 (impedir el acceso a las variables), bastaría con evaluar la entrada dentro de una función, para que no pueda ver otras variables. Aparentemente (vea el ejemplo 2 a continuación), getcallinfo
detecta no solo llamadas funciones, sino también variables . De todos modos, probablemente sea una buena idea hacer la evaluación en el ámbito aislado de una función.
El procedimiento es entonces:
Use la versión de cadena de
input
para evitar la evaluación:x = input(''Input an array: '', ''s'');
Guarde la cadena en un archivo:
filename = ''tmp.m''; fid = fopen(filename,''w''); fprintf(fid, ''%s'',x); fclose(fid);
Compruebe la cadena de entrada con
getcallinfo
para detectar posibles llamadas a funciones: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
donde evalinput
es la siguiente función
function x = evalinput(x)
x = eval(x);
Ejemplo 1
Considerar
x = input(''Input an array: '', ''s'');
con la entrada del usuario
[sqrt(2) sin(pi/3)]
Entonces
filename = ''tmp.m'';
fid = fopen(filename,''w'');
fprintf(fid, ''%s'',x);
fclose(fid);
gci = getcallinfo(filename);
produce un gci.calls.fcnCalls.names
no vacío,
>> gci.calls.fcnCalls.names
ans =
''sqrt'' ''sin'' ''pi''
que nos dice que la entrada del usuario llamaría a funciones sqrt
, sin
y pi
si se evaluara. Tenga en cuenta que los operadores como /
no se detectan como funciones.
Ejemplo 2
y = [10 20 30];
x = input(''Input an array: '', ''s'');
El usuario entra
[1 y y.^2]
Entonces
filename = ''tmp.m'';
fid = fopen(filename,''w'');
fprintf(fid, ''%s'',x);
fclose(fid);
gci = getcallinfo(filename);
produce
>> gci.calls.fcnCalls.names
ans =
''y'' ''y''
Entonces getcallinfo
detecta las getcallinfo
como si fueran funciones.