#java #xml #algorithm #logic #flowchart
#java #xml #алгоритм #Логические #блок-схема
Вопрос:
Хорошо, я знаю, что это расплывчатый вопрос, но, похоже, я застрял здесь с логикой…Я хочу создать блок-схемы входных программ. Я думал об этом два дня и не могу найти наилучшего общего подхода…Итак, я отчаянно прошу вас, ребята, помочь мне здесь …. может быть, есть что-то маленькое, чего мне не хватает….
У меня есть XML-файл, который содержит информацию о данной Java-программе и выглядит следующим образом:
<Method modifier="publicstatic" type="void" name="main" >
<FormalParameter modifier="" type="String[]" var_name="args" />
<Throw>NullPointerException</Throw>
<Throw>
IndexOutofBoundException
</Throw>
<Field modifier="" type="int" name="x,y,z" />
<Field modifier="" type="int" name=" sum[] " />
<If>
condition><![CDATA[(x==0)]]></condition>
<Statement>
<![CDATA[System.out.Println("I am in true")]]></Statement>
<If>
<condition><![CDATA[(y==2)]]></condition>
<Statement>
<![CDATA[System.out.Println("I am in
true of y==2")]]></Statement>
</If>
<Statement>
<![CDATA[System.out.prnitln("I am in
true again")]]></Statement>
</If>
<else>
<If>
<condition><![CDATA[(x==2)]]></condition>
<Statement>
<![CDATA[System.out.println("I am in
x==2 true")]]></Statement>
</If>
<else>
<Statement>
<![CDATA[System.out.println("I am in
else 2")]]></Statement>
</else>
</else>
<Statement>
<![CDATA[c=b d]]></Statement>
<Statement>
<![CDATA[a=b c]]></Statement>
</Method>
Теперь это часть сгенерированного XML-файла …. для фрагмента кода:
public static void main(String[] args) throws NullPointerException,IndexOutofBoundException {
int x,y,z;
int sum[]={1,2,3,4};
if(x==0)
{
System.out.Println("I am in true");
if(y==2)
{
System.out.Println("I am in true of y==2");
}
System.out.prnitln("I am in true again");
}
else if(x==2)
{
System.out.println("I am in x==2 true");
}
else
{
System.out.println("I am in else 2");
}
c=b d;
a=b c;
}
Теперь мой способ сделать это таков:
У меня есть класс reader, который считывает XML-файл, и один класс createFLowChart, который занимается рисованием. Я начинаю обход узла метода… Если я нахожу инструкцию, я вызываю функцию FundStatement, которая рисует прямоугольную рамку и соединяет ее с узлом prv. Выполнение этого для конструкций If-else без добавления большого количества логических переменных состояния. Итак, может ли кто-нибудь помочь мне в этом?
Теперь проблема с конструкциями if-else. Я не могу найти простой способ обхода деревьев if -else и корректного установления граничных соединений между узлами без добавления ряда переменных, содержащих информацию о состоянии, т.Е. if запущен или else запущен и т.д. Вот мой подход, но я нахожу трудности с настройками глубины, т.е. соединением листьев вложенных операторов if-else :
public void traverse(String path,CreateFlowChart parent)
{
xPath = XPathFactory.newInstance().newXPath();
XPathExpression expr;
//ArrayListamp;<dataObjects.Interfaceamp;> parentInterfaces=new ArrayListamp;<dataObjects.Interfaceamp;>();
//dataObjects.Class[] classes=new dataObjects.Class[90];
try {
expr = xPath.compile(path);
Object result = expr.evaluate(document, XPathConstants.NODESET);
NodeList MethodNodes = (NodeList) resu<
NodeList childNodes=MethodNodes.item(0).getChildNodes();
JOptionPane.showMessageDialog(null, "No of children of " path " is " childNodes.getLength());
for(int i=0;iamp;<=childNodes.getLength()-1;i )
{
Node node=childNodes.item(i);
JOptionPane.showMessageDialog(null, "Found Child " node.getNodeName());
traverse(node,parent);
}
} catch (XPathExpressionException e) {
JOptionPane.showMessageDialog(null,"error: " e.toString());
e.printStackTrace();
}
}
private void traverse(Node root ,CreateFlowChart parent)
{
if(root.getNodeName()=="If")
{
String condition="";
NodeList childNodes=root.getChildNodes();
for(int i=0;iamp;<childNodes.getLength();i )
{
Node child=(Node)childNodes.item(i);
if(child.getNodeName()=="condition")
{
Element ele=(Element)child;
condition=ele.getTextContent();
}
}
dataObjects.ControlStatements ifstmt=new dataObjects.ControlStatements(condition,null,true);
parent.foundIf(ifstmt);
NodeList childs=root.getChildNodes();
for(int i=0;iamp;<childs.getLength();i )
{
Node child=(Node)childs.item(i);
traverse(child,parent);
}
parent.foundEndIf();
}
else if(root.getNodeName()=="else")
{
parent.foundElse();
NodeList childNodes=root.getChildNodes();
for(int i=0;iamp;<childNodes.getLength();i )
{
Node child=(Node)childNodes.item(i);
traverse(child,parent);
}
parent.foundEndElse();
}
else if(root.getNodeName()=="Statement")
{
parent.foundStatement(root.getTextContent());
}
}
Теперь три функции, вызываемые из программы чтения, являются:
public void foundIf(dataObjects.ControlStatements Ifstatement)
{
JOptionPane.showMessageDialog(null,"Drawing If");
graph.getModel().beginUpdate();
try
{
Object v1 = graph.insertVertex(start, null, "If " Ifstatement.condition, 20, 20, 150,60,"Branch");
if(isInIf==false amp;amp; isInElse==false)
{
JOptionPane.showMessageDialog(null,"Drawing normally");
graph.insertEdge(start, null, "", currentNode,v1);
}
else if(isInIf==true)
{
JOptionPane.showMessageDialog(null,"Drawing inside a previous If");
graph.insertEdge(start, null, "True", currentNode,v1);
isInIf=false;
}
else if(isInElse==true)
{
JOptionPane.showMessageDialog(null,"Drawing inside a previous else");
graph.insertEdge(start, null, "False", currentNode,v1);
isInElse=false;
}
currentNode=(mxCell)v1;
JOptionPane.showMessageDialog(null,"Pushing if node inside stack");
lastIfNode.push(currentNode);
isInIf=true;
}
finally
{
graph.getModel().endUpdate();
}
}
public void foundElse()
{
currentNode=lastIfNode.pop();
isInElse=true;
}
public void foundStatement(String st)
{
JOptionPane.showMessageDialog(null,"Drawing a statement");
graph.getModel().beginUpdate();
try
{
Object v1 = graph.insertVertex(currentNode, null, st, 20, 20, 150,60,"Statement");
if(isInIf==false amp;amp; isInElse==false)
{
JOptionPane.showMessageDialog(null,"Drawing normally");
graph.insertEdge(start, null, "", currentNode,v1);
}
else if(isInIf==true)
{
JOptionPane.showMessageDialog(null,"Drawing inside a prv If");
graph.insertEdge(start, null, "True", currentNode,v1);
isInIf=false;
}
else if(isInElse==true)
{
JOptionPane.showMessageDialog(null, "Drawing inside else");
graph.insertEdge(start, null, "False", currentNode,v1);
isInElse=false;
reTraceIf=false;
}
if(reTraceIf==true)
{
JOptionPane.showMessageDialog(null, "Drawing false part");
graph.insertEdge(start, null, "False", lastIfNode.pop(),v1);
reTraceIf=false;
}
if(branchEnded==true)
{
JOptionPane.showMessageDialog(null, "Linking brancehs");
graph.insertEdge(start, null, "", prvBranchNode,v1);
branchEnded=false;
}
currentNode=(mxCell)v1;
}
finally
{
graph.getModel().endUpdate();
}
}
public void foundEndIf()
{
prvBranchNode=currentNode;
isInIf=false;
reTraceIf=true;
}
public void foundEndElse()
{
branchEnded=true;
}
Это отлично работает для операторов if else на один уровень глубже, но ухудшается после этого, я понимаю, это потому, что глобальная переменная prvNode может одновременно управлять только одним узлом, может быть списком, который я сделаю, но все же могут возникнуть некоторые проблемы…Может ли кто-нибудь улучшить это, пожалуйста??
Комментарии:
1. Если вы делаете это не для того, чтобы узнать, как создать программу для рисования блок-схемы, вы могли бы рассмотреть возможность взглянуть на GraphViz ( graphviz.org ), и ваша программа преобразует ваш XML в формат graphviz и позволяет ему отображать чертеж.
2. хорошее предложение, я попробую……
Ответ №1:
Вы можете использовать рекурсивный подход для обхода DFS, например —
1 For each line in block
2 If it is an if statement
3 Render condition in a Diamond shape
4 Get the statement block inside the if statement and go to #1
5 else
6 Render it in a rectangle shape
Это всего лишь идея, вам также нужно будет отслеживать глубину, помимо учета расположения элементов на двумерной плоскости. Но вы должны сначала потренировать алгоритм обхода, а затем подогнать макет позже.
Комментарии:
1. да, это был мой подход .. сначала фактическая проблема с глубиной … и я думаю, что это может усложниться с включением операторов for-while do while-switch……..:(