2017-09-14 2 views
4

Ich möchte mehrere Zeilen Code ausführen, aber ich bin mir nicht sicher, ob eine Zeile einen Fehler verursacht. Wenn jedoch ein Fehler auftritt, möchte ich, dass das Skript diese Zeile ignoriert und fortfährt.sequenzieller Versuch Fang Endblock für Matlab

Eine Möglichkeit wäre, einen try-catch-end Block zu haben, der einen Block Code überspringt, der Fehler verursachen könnte. Sobald jedoch ein Fehler auftritt, wird der Rest des Codes nach dem Fehler in der try-Anweisung nicht ausgeführt.

TL; TR: Habe ich eine andere Wahl als einen try-catch-end Block für jede einzelne Zeile im folgenden Beispielcode zu schreiben?

Beispielcode:

try 
    disp('1st line'); 
    disp('2nd line'); 
    PRODUCE_ERROR; %throws an error, variable/function does not exist 
    disp('3rd line'); %%%%% 
    disp('4th line'); % these lines I would like to keep executing 
    disp('5th line'); %%%%% 
catch 
    disp('something unexpected happened'); 
end 

Ausgang:

1st line 
2nd line 
something unexpected happened 

Ausgabe, die bevorzugt werden würde:

1st line 
2nd line 
something unexpected happened 
3rd line 
4th line 
5th line 

bezogen werden: Why should I not wrap every block in "try"-"catch"?

+0

ich rekursiver Weise denken kann, dieses Problem zu lösen, ist jedoch, dass wahrscheinlich nicht die eleganteste Art und Weise ... – user2305193

+0

Sie mit dem Rest des Codes weiter durch den Fehler nicht Erneutes Auslösen. Kannst du ein [mcve] posten? – beaker

+0

Auch wenn Sie den Fehler nicht erneut auslösen, wird der Rest des 'catch'-Zweiges übersprungen. Siehe zum Beispiel 'klar, a = 1; c = 3; versuchen, disp (a), disp (b), disp (c), end' –

Antwort

4

Eine Möglichkeit ist, zu setzen jeder Codeabschnitt in einer Funktion und iterieren über eine cell array der function handles. Hier ist ein Beispiel mit einer Liste von anonymous functions:

fcnList = {@() disp('1'); ... 
      @() disp('2'); ... 
      @() error(); ... % Third function throws an error 
      @() disp('4')}; 

for fcnIndex = 1:numel(fcnList) 
    try 
    fcnList{fcnIndex}(); % Evaluate each function 
    catch 
    fprintf('Error with function %d.\n', fcnIndex); % Display when an error happens 
    end 
end 

Und hier ist die Ausgabe generiert, die zeigen, dass Funktionen noch einmal ausgewertet werden, nachdem man wirft ein Fehler:

1 
2 
Error with function 3. 
4 

Das obige Beispiel für den Fall funktioniert Wenn Sie einzelne Zeilen haben von Code, den Sie nacheinander bewerten möchten, aber Sie können mehrere Zeilen in eine anonyme Funktion nicht anpassen. In diesem Fall würde ich mit nested functions gehen, wenn sie auf Variablen im größeren Arbeitsbereich zugreifen müssen oder local functions, wenn sie unabhängig voneinander arbeiten können. Hier ist ein Beispiel mit verschachtelten Funktionen:

function fcn1 
    b = a+1;  % Increments a 
    fprintf('%d\n', b); 
end 
function fcn2 
    error();  % Errors 
end 
function fcn3 
    b = a.^2; % Squares a 
    fprintf('%d\n', b); 
end 

a = 2; 
fcnList = {@fcn1 @fcn2 @fcn3}; 

for fcnIndex = 1:numel(fcnList) 
    try 
    fcnList{fcnIndex}(); 
    catch 
    fprintf('Error with function %d.\n', fcnIndex); 
    end 
end 

Und die Ausgabe:

3 
Error with function 2. 
4 
+0

ist es eine schnelle und schmutzige Art und Weisen Sie vorschlagen würden Codezeilen in eine Liste von anonymen zu konvertieren Funktionen? – user2305193

+0

@ user2305193: Ich habe ein anderes Beispiel hinzugefügt. Ich hoffe, das hilft. – gnovice

+0

Ich meinte mehr in einfachen Begriffen, als diese Codes zu suchen und zu ersetzen. Aber ich denke, das ist mehr, was Sie mit einem einfachen Notepad-Ersetzungsbefehl tun würden (zumindest in Windows). Das Beispiel mit den mehreren Zeilen Code macht keinen Sinn für mich machen, da (soweit ich sehen kann) es etwa gleiche Mengen von Code dauern würde, um jede Kommandozeile eine Try-Catch-End-Anweisung zu schreiben. – user2305193

1

Ein einfacher Ansatz beinhaltet die Skriptdatei Zeile für Zeile zu lesen und jede Zeile wiederum zu bewerten. Dies setzt voraus, dass das Skript, das Sie ausführen möchten, keine mehrzeiligen Anweisungen (wie z. B. eine for mit der end in einer anderen Zeile oder eine Anweisung in mehrere Zeilen unter Verwendung ...) enthält. Dies ist eine starke Einschränkung, wie es z.B. initialisieren Sie eine Matrix mit mehreren Textzeilen.

Dies ist die Funktion:

function execute_script(fname) 
fid = fopen(fname,'rt'); 
n = 0; 
while ~feof(fid) 
    cmd = fgetl(fid); 
    n = n+1; 
    if ~isempty(cmd) 
     try 
     evalin('caller',cmd); 
     catch exception 
     disp(['Error occurred executing line number ',num2str(n),': ',exception.message]); 
     end 
    end 
end 

Es tut genau, wie ich oben beschrieben: es in einer Zeile liest, dann nutzt evalin diese Zeile in dem Arbeitsbereich des Anrufers zu bewerten. Jede erstellte Variable wird im Arbeitsbereich des Aufrufers erstellt. Jede verwendete Variable wird vom Arbeitsbereich des Aufrufers übernommen.

Zum Beispiel erstelle ich die Datei testscript.m mit folgendem Inhalt:

A = 1; 
B = 2+C; % This line needs a variable not defined in the script! 
D = 5; 

Als nächstes wird in der MATLAB-Eingabeaufforderung:

>> execute_script('testscript.m') 
Error occurred executing line number 2: Undefined function or variable 'C'. 
>> whos 
    Name  Size   Bytes Class   Attributes 

    A   1x1     8 double     
    D   1x1     8 double     

Die Variable A und D erstellt wurden. Wenn ich definieren C:

>> C=0; 
>> execute_script('testscript.m') 
>> whos 
    Name  Size   Bytes Class   Attributes 

    A   1x1     8 double     
    B   1x1     8 double     
    C   1x1     8 double     
    D   1x1     8 double     

Mit einer variablen C definiert ist, wird das Skript ohne Fehler und definiert B auch.

Verwandte Themen