WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

Anzahl der Treffer von strfind speichern

 

bmtil
Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 01.05.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.12.2016, 14:41     Titel: Anzahl der Treffer von strfind speichern
  Antworten mit Zitat      
Hallo,
ich möchte mit der Funktion strfind nach Variablen in einem String suchen. Der String stellt dabei eine Zeile eines Codes dar, die Variablen stehen in einer containers.Map.
Ich lasse mein Programm innerhalb einer For-Schleife nach den entsprechenden Variablen im String suchen und die äußere For Schleife dient der Auswahl der Variablen aus der containers.Map. Wenn in einer Codezeile, ein und die selbe Variable insgesamt drei mal vorkommt, dann möchte ich dieses Ergebnis speichern und mir dann die Gesamtanzahl solcher Ereignisse rausgeben lassen. Leider bleibt meine Zählvariable "stellen" auf 0, und ich weiss nicht was ich falsch mache. Vodcode ist dabei ein Cell Array.
Hier ist mein Code:
Code:

function voddi_test(graph)

global vodcode
global vod_vars

stellen = 0;

rev_vodcode = fliplr(vodcode);

for elementidx = 1 : length(vod_vars)   %eine variable nach der anderen
     for codeidx = 1 : length(rev_vodcode) %zeilenweise den code durchsuchen
         k = numel(strfind(rev_vodcode{codeidx}, vod_vars{elementidx}));
          if k == 3
            stellen = stellen + 1;
         end    
     end
     
end
 stellen
 


Vielen Dank und liebe Grüße, bmtil.

EDIT: habe die Zeile k = length(match) zu k = numel(match) geändert, da mir length nicht die Anzahl der Elemente im match Array liefern würde. Trotzdem war das leider nicht der Fehler (oder vllt. doch), das Ergebnis bleibt 0.
EDIT2: natuerlich muss stellen = 0, auch stellen = stellen heißen, sonst wird die Variable ja immer auf 0 gesetzt bei jedem Durchlauf, wo der gewuenschte Fall nicht eintrifft.

EDIT 3: ich bin der Meinung, ich weiss wo das Problem liegt. die Funktion strfind weiss zwar, was mit "rev_vodcode{codeidx}" gemeint ist, und dass sie immer den String zeilenweise aus rev_vodcode Array nehmen soll, aber sie kennt den Inhalt von "vod_vars{elementidx}" nicht, hat somit keinen Vergleichswert und liefert deswegen immer 0.

EDIT4: ich habs gelöst. vod_vars war in Wahrheit keine containers.Map, sondern eine Cell. Das war die ganze Zeit der Denkfehler. Code entsprechend geändert.

Zuletzt bearbeitet von bmtil am 05.12.2016, 16:13, insgesamt 3-mal bearbeitet
Private Nachricht senden Benutzer-Profile anzeigen


Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 05.12.2016, 15:57     Titel: Re: Anzahl der Treffer von strfind speichern
  Antworten mit Zitat      
Hallo bmtil,

Die Nutzung globaler Variablen ist immer ein ausgesprochen schlechter Programmierstil. Davon wird grundsätzlich abgeraten.

Du kannst mit dem Debugger Zeile für Zeile durch den Code gehen und so genau herausfinden, was passiert.

Die Zeile "stellen = stellen;" ist sinnlos. Lasse sie einfach weg.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
bmtil
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 01.05.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.12.2016, 16:07     Titel:
  Antworten mit Zitat      
Wie kann ich ohne der Übergabe von globalen Variablen arbeiten? Ich merke ja selber, dass es zu Schwierigkeiten führt, vorallem was die Übersicht angeht.
Mein Problem ist, ich habe zwei Arrays, die irgendwo im Projekt von dem Vorarbeiter erstellt werden. Ich weiss nicht, wie ich ohne global sonst an die rankomme.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 05.12.2016, 16:29     Titel:
  Antworten mit Zitat      
Hallo bmtil,

Wenn Du ein großes Projekt bearbeitest (z.B. > 100'000 Zeilen Code und mehrere Autoren) und schon beim Design auf globale Variablen gesetzt wurde, ist das ein sogenanntes "Brownfield"-Projekt. Aus professioneller Sicht ist das kaum noch sinnvoll zu handhaben und die einzige zuverlässige Lösung ist:
Neu schreiben.

Ich meine das ganz ernst: Je länger man an so einem Code herumdoktort, desto schwieriger wird jede weitere Wartung. Da geht so lange, bis das Programm unbenutzbar wird.

Variablen übergibt man als Inputs und Outputs an jede Funktion, die sie benötigt. So kann man fest eingrenzen, welche Funktionen die Variablen lesen dürfen und welche sie ändern können. Wenn eine Variable an einer Stelle plötzlich einen unerwarteten Wert hat, kann man anhand des Programmcodes herausfinden, woher die Änderung stammt. Mit globalen Variablen geht das nicht.

Zu diesem Thema findest Du tausende Diskussionen im Netz. Es lohnt sich die Kenntnisse in Software-Engineering zu vertiefen, wenn man mit Code mit mehr als 1000 Zeilen arbeitet.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
bmtil
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 01.05.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 05.12.2016, 16:45     Titel:
  Antworten mit Zitat      
Das Projekt hat mit mir zwei Autoren, der erste Autor ist nicht mehr aufzufinden (wurde fertig mit dem Projekt vor zwei Jahren). Das Projekt beinhaltet locker an 5k Zeilen über verschiedenste .m Files verteilt. Für Neu Schreiben fehlt leider die Zeit und die Faehigkeiten, das ist mein erstes reines Software Projekt.

Ich habe einen weiteren Fehler in der ersten Code Version gefunden, die Variablen hatten als Suffix immer noch den Filenamen, der aber im Code nicht mehr vorkommt.
Deswegen habe ich mit strrep den Namen geändertt:

Code:

rem_suf = [system_name, '/'];
for elementidx = 1 : numel(vod_vars)
    new_vars = strrep(vod_vars{elementidx}, rem_suf, '');
     for codeidx = 1 : length(rev_vodcode)
         k = numel(strfind(rev_vodcode{codeidx}, new_vars{elementidx}));
         if k == 1                                                          %bestimmen Anzahl der variablenmatches in einer zeile -> read/write faelle
            stellen = stellen + 1;
         end    
     end  
end


Allerdings bekomme ich jetzt den Fehler, dass der Index die Matrixdimensionen überschreitet und zwar in der Zeile wo ich "k" bestimme. Das verwirrt mich, da ich denke dass die beiden Indezes (elementidx und codeidx) bekannt sind, und codeidx immer länger ist, als elementidx.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 06.12.2016, 11:30     Titel:
  Antworten mit Zitat      
Hallo bmtil,

Ja, das ist ein typisches Brownfield-Projekt. Schlammschlacht. Du hast mein Mitgefühl. Dein Nachfolger wird es noch schwerer haben.

"elementidx" geht bis "numel(vod_vars)". Offenbar ist "new_vars" aber kürzer als "vod_vars".
Der Debugger hilft Dir, solche Probleme zu erkennen:
Code:

im Command-Window eingeben und dann das Programm nochmal starten. Wenn Matlab dann beim Fehler stehen bleibt, kannst Du die Variablen in dieser Zeile untersuchen und herausfinden, wo es hängt.

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
bmtil
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 01.05.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 06.12.2016, 14:25     Titel:
  Antworten mit Zitat      
Die Variablennamen machen mehr Probleme als jemals erwartet. Dennoch habe ich es jetzt endlich vernünftig hinbekommen, mir die richtigen, vom Sys_namen getrennten Variablennamen in ein frisches Array reinzuschreiben.
Code:

global vodcode
global vod_vars
system_name = extract_system_name(graph);  
new_name = [];
stellen = 0;

rev_vodcode = fliplr(vodcode);    %umgekehrte reihenfolge

rem_suf = [system_name, '/'];    
for old_elementidx = 1 : length(vod_vars)
    new_name{old_elementidx} = strrep(vod_vars{old_elementidx}, rem_suf, '');   %var_namen vom sys_namen trennen
end

for new_elementidx = 1 : length(new_name)
     for codeidx = 1 : length(rev_vodcode)
         k = strfind(rev_vodcode{codeidx}, new_name{new_elementidx})
        %if k == 2                                                          %bestimmen Anzahl der variablenmatches in einer ziele -> read/write faelle
         %  stellen = stellen + 1;
        %end    
     end    
end


Leider wende ich immernoch die strfind Funktion falsch an. Momentan versuche ich mir nur die jeweiligen Stellen (Indizes) k, an denen die Variablen in den Assemblerzeilen zu stehen haben, jedoch bekomme ich entweder eine 10 oder [] für k. Mein nächstes Problem wird sein, wie kann ich aus dem Wert k rauslesen, wie oft eine Variable im String vorkommt. Dafür habe ich leider auch noch keinen Ansatz. Wenn k ein Array ist, dann ist es einfach, ich muss mir naemlich nur numel von k rausgeben lassen.

Noch zwei Fragen: entspricht find(strcmp(strA, strB)) der strfind Funktion? Wie kann ich überprüfen, dass meine Assemblerzeilen richtig eingelesen werden?
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 06.12.2016, 18:48     Titel:
  Antworten mit Zitat      
Hallo bmtil,

Zitat:
Leider wende ich immernoch die strfind Funktion falsch an. Momentan versuche ich mir nur die jeweiligen Stellen (Indizes) k, an denen die Variablen in den Assemblerzeilen zu stehen haben, jedoch bekomme ich entweder eine 10 oder [] für k.

Und was möchtest Du stattdessen bekommen?

Zitat:
Mein nächstes Problem wird sein, wie kann ich aus dem Wert k rauslesen, wie oft eine Variable im String vorkommt.

Code:
k = strfind(rev_vodcode{codeidx}, new_name{new_elementidx});
n = numel(k);


Zitat:
Wenn k ein Array ist, dann ist es einfach, ich muss mir naemlich nur numel von k rausgeben lassen.

Da liegst Du also genau richtig, den "k" ist immer ein Array.

Zitat:
Noch zwei Fragen: entspricht find(strcmp(strA, strB)) der strfind Funktion?

Nein. Hast Du mal in der Dokumentation nachgelesen? Da steht das umfassend drin: strcmp überprüft, ob 2 Strings identisch sind. Wenn man das auf Cell-Strings anwendet, bekommt man ein Array zurück.
strfind sucht nach dem Vorkommen eines Strings in einem anderen. Das ist etwas ganz anderes.

Zitat:
Wie kann ich überprüfen, dass meine Assemblerzeilen richtig eingelesen werden?

Das kann man nicht beantworten. Was sind denn "deine Assemblerzeilen" und nach welchem Kriterium wird denn "richtig" bewertet?

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
bmtil
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 01.05.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 07.12.2016, 10:22     Titel:
  Antworten mit Zitat      
Ich habe überprüft, was ich da tatsächlich an Stelle des Assemblers Codes einlese. Das, was ich dachte der "Assemblercode" zu sein (in der Variable vodcode), ist tatsächlich nur eine Ansammlung von Mnemonics, noch ohne Zusammenhang.
Der notwendige Assemblercode wird tatsächlich an einer anderen Stelle im Projekt zusammengebaut über diese Funktion:

Code:
function line = generate_code(node)
% generate assembly line from given node
% node: node object contains much required informations
% line: return assembly line
global MNEMONIC;
% node = node{1};

name = strsplit(node.arguments{1}, '/');
line = sprintf('%s %s %s %s %s %s', ...
    MNEMONIC(node.type), name{end}, node.arguments{2}, node.arguments{3}, ...
    MNEMONIC('Comment'), node.comment)
whos line
end

Schlammschlacht trifft es wohl zu 100%. "Whos" hat mir verraten, dass "line" eine char Variable ist. In der Variable "line" steht auch tatsächlich der notwendige Code, den konnte ich mir in die Kommandozeile ausgeben lassen und ich habe diesen mit den bereits generierten Codes vergliechen und es passt.

Frage: kann ich irgendwie den Inhalt der Variable "line" verwenden, ohne global zu benutzen? Idee wäre, meinen Algorithmus in die Funktion mit zu integrieren, allerdings habe ich Angst da irgednwas kaputt zu machen.

Ein Bsp. fuer eine Assemblerzeile könnte dabei in dem zu untersuchendem Code so aussehen:
Code:
Mnemonic, Ziel_var, Quell_var1, Quell_var2

Das Array k soll mir verraten an welchen Stellen in der Zeile Ziel_var, Quell_var1 und Quell_var2 stehen.

Viele Grüße und vielen Dank, der Thread hilft mir wirklich weiter.
Private Nachricht senden Benutzer-Profile anzeigen
 
Jan S
Moderator

Moderator


Beiträge: 11.057
Anmeldedatum: 08.07.10
Wohnort: Heidelberg
Version: 2009a, 2016b
     Beitrag Verfasst am: 07.12.2016, 12:55     Titel:
  Antworten mit Zitat      
Hallo bmtil,

"line" kann leicht zu Verwirrungen führen, denn das ist auch ein Matlab-Befehl.

Wenn Du "line" außerhalb der Funktion verwenden möchtest, kannst Du den Rückgabewert der Funktion verwenden:
Code:
Line = generate_code(node);

Dann steht die Zeile in der Variablen "Line" (hier jetzt mal mit großen L).

Hilft das schon weiter?

Gruß, Jan
Private Nachricht senden Benutzer-Profile anzeigen
 
bmtil
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 01.05.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 07.12.2016, 13:13     Titel:
  Antworten mit Zitat      
Leider hilft das nicht weiter, Matlab kann die Funktion in meinem .m File nicht ausführen. Ist aber schon sehr nah daran was ich haben möchte.

Diese Funktion line = generate_code(node), wird dazu benutzt um die Assemblercode Zeilen in ein File zu schreiben. Ursprünglich wollte ich auch mit das generierte File öffnen und dort nach den Variablen suchen, jedoch habe ich die Idee verworfen, da ich nicht immer die Anzahl der Codezeilen und ihre Länge nicht kenne. Deswegen habe ich gedacht, ich schau, wo der Code ursprünglich generiert wird, und lag erstmal mit meiner Vermutung vodcode falsch.

Ich versuche mir jetzt den Inhalt des generierten .asm Files zurück in ein Array zu schreiben, damit ich dann die strfind anwenden kann. Importdata(filename) quasi ausprobieren.

Grüße.
Private Nachricht senden Benutzer-Profile anzeigen
 
bmtil
Themenstarter

Forum-Anfänger

Forum-Anfänger


Beiträge: 49
Anmeldedatum: 01.05.12
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 08.12.2016, 12:49     Titel:
  Antworten mit Zitat      
Entschuldigung für den Doppelpost, ich habe endlich die Lösung. Ich habe es geschafft den vorhanden Matlab Code so zu modifizieren, dass der gewünschte Assembler Code mir in einem Array generiert wird. Und das ohne Verwendung von globals Very Happy.
Code:
function ret = write_nodes(file_name, graph, node_list, prelude)
% write cell array of nodes given file file_name
% file_name: name of file
% line: lines of codes
% ret: return value
global EXPENSIVE_OPERATIONS;
S = [];  %leeres Array vorbereiten
assembly = fopen(file_name, 'w');
if nargin < 4
    prelude = {};
end
if assembly ~= -1
    for str = prelude
        fwrite(assembly, sprintf('%s\n', str{1}));
    end
    for str = node_list
        fwrite(assembly, sprintf('%s\n', generate_code(graph(str{1}))));
        if EXPENSIVE_OPERATIONS.isKey(graph(str{1}).type)
            for c = 1 : EXPENSIVE_OPERATIONS(graph(str{1}).type)
                fwrite(assembly, sprintf('%s\n', generate_code(Node())));
            end
        end
        %In dieser Schleife wird der AsmCode generiert und meine Array gefuellt
        s = generate_code(graph(str{1}));
        s = [s ';'];    %Zeilen und Delimiter festlegen
        S = [S s];    %speichern
       
    end
     fclose(assembly);
    ret = true;
else
    ret = false;
end
end
Private Nachricht senden Benutzer-Profile anzeigen
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum posten
Du kannst Dateien in diesem Forum herunterladen
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2024 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.