我目前正在尝试对从txt文件中读取伪代码的程序进行编码,并将伪代码的Big O表示法输出为新的txt文件。我正在努力寻找一种解析for循环的方法,以获取查找代码时间复杂度所需的关键信息。例如:
"input02.txt"
n m /* The estimate variable */
i j /* The control variable in the for loop */
tmp x j /* Variable(s) appeared in the loop body */
for (i=0; i<n*m; i*=2) {
for (j=0; j<n; j++) {
tmp = tmp + 3;
x--;
j++;
}
}
"input02_BigO.txt"
O( n * log(n*m) )
为了尝试简化我要求的内容,这里是我分配的项目描述:
描述: 编写一个程序来分析嵌套的Java'&#34; for&#34;循环并为输入文件中提供的代码提供Big-O表示法估计。特别是,输入文件包含嵌套的&#34; for&#34;以适当的Java语法循环,并且限于(1)最多2&#34;对于&#34;循环和“for”循环(所以没有&#34;而#34;或&#34; do-while&#34;循环)(2)简单操作+(加号), - (减号),*(乘法)和/(分裂)。请注意,缺少操作&#34; ++&#34;,&#34; - &#34;,&#34; + =&#34;,&#34; - =&#34;,&# 34; =&#34;,&#34; / =&#34;也是允许的。为简单起见,您可以假设输入代码使用Java语言,并且没有语法错误,也没有涉及任何方法/函数。
输入/输出: 输入文件&#34; .txt&#34;是一个文本文件,其中前三行描述不同的变量集。第1行描述了应该在BigO估计结果中使用的估计变量。第2行描述了每个循环中的控制变量。第3行描述了循环/嵌套循环体中出现的变量。输出写入文件&#34; _BigO.txt&#34;名为&#34; .txt&#34;的文件中给出的代码的Big-O估计值。如果你不能给出估计,请在该文件中解释原因。
实施例: 如上所示
到目前为止我所拥有的:
import java.util.*;
import java.io.*;
public class Big_O_Analysis {
public static void main(String[] args) throws FileNotFoundException {
/* ASKS USER TO INPUT NAME OF TXT FILE TO BE READ */
Scanner keyboard = new Scanner(System.in);
System.out.println("Enter file name (without '.txt': ");
/* STORES FILE NAME TO READ INPUT FILE AND CREATE OUTPUT FILE*/
String fileName = keyboard.nextLine();
String inputFile = fileName + ".txt";
String outputFile = fileName + "_BigO.txt";
/* READS INPUT FILE AND ANALYZES FOR LOOPS AND ASSIGNMENT STATEMENTS */
File file = new File(inputFile);
Scanner input = new Scanner(file);
String line = input.nextLine();
String[] complexity = new String[10]; // Holds time complexity
while (input.hasNext()) // Search for line with for loop
{
while (!line.startsWith("for"))
{
line = input.nextLine();
}
// PARSE THROUGH LOOP
String[] forLoop = line.split(";"); // Splits loop into 3 parts by the ';', ex: "for (i=0", "i<10","i++)"
// Keeps control variable part of for loop
String[] forLoopStart = forLoop[0].split("("); // Splits "for (i=0" into "for " and "i=0"
String initialization = forLoopStart[1]; // Stores the start of the for loop "i=0"
char control = initialization.charAt(0); // Stores control variable 'i'
int start = Integer.parseInt(initialization.substring(2)); // Stores start value of control '0'
// Keeps estimate variables
String termination = forLoop[1].substring(2); // Stores termination of loop. "i<10" -> "10" or "i<n" -> "n" or "i<n*m" -> "n*m"
int end; // Initializes termination value for loop
int index = 0;
for (int i = 0; i<termination.length(); i++) // Gets termination value when it is a number: "i<10"
{
index++;
}
end = Integer.parseInt(termination);
// Keeps increment values
String increment = forLoop[2].substring(0,forLoop[2].length()-1); // Stores increment section of loop. "i++)" -> "i++" or "i+=10" or "i*=i"
String inc = increment.substring(1,3); // Stores increment. "++", "*=", etc
if (inc == "++" || inc == "--")
complexity[1] = termination;
else if(inc == "*=" || inc == "/=") // Log
complexity[1] = "log(" + termination + ")";
else if (inc == "+=" || inc == "-=") // Jump
complexity[1] = termination + "/" + increment.substring(3);
String factor = ""; // Stores factor of increment. "2", "10", "n"
boolean factorDigits = false; // The following boolean values test to see if the factor is just a number, variable by itself, or variable with number
boolean factorVar = false;
boolean factorMix = false;
int fac; // If factor is just a number
for (int i = 3; i<increment.length(); i++)
{
if (Character.isDigit(increment.charAt(i)))
factorDigits = true;
else if (Character.isLetter(increment.charAt(i)))
factorVar = true;
}
if (factorDigits == true && factorVar == false)
{
factor = factor + increment.substring(3);
fac = Integer.parseInt(factor);
}
else if (factorDigits == false && factorVar == true)
{
factor = factor + increment.substring(3);
}
else if (factorDigits == true && factorVar == true)
{
factorMix = true;
factor = factor + increment.substring(3);
}
// Reads for assignment statements
line = input.nextLine();
int assignments = 0;
while (input.hasNext() && !line.startsWith("for"))
{
assignments++;
line = input.nextLine();
}
complexity[0]= Integer.toString(assignments);
// Analyzes loop
}
/* FORMS COMPLEXITY */
String timeComplexity = "";
/* FORMS COMPLEXITY INTO BIG O NOTATION */
String bigO = "O(" + timeComplexity + ")";
/* CREATES AND WRITES A FILE OF THE BIG O ESTIMATE */
PrintWriter output = new PrintWriter(outputFile);
output.print(bigO);
}
}
答案 0 :(得分:0)
即使解析完成,这也很棘手:)
如果你想正确地做,你可以使用StreamTokenizer进行标记化,并在顶部为整个语言构建递归下降解析器。
或者,您可以进行一些额外的假设并逐行处理块。在这种情况下,您可以将循环初始化器,条件和增量提取到&#34;部件&#34;使用此代码段:
if (line.startsWith("for") {
int cut0 = line.indexOf('(');
int cut1 = line.lastIndexOf(')');
String parts = line.substring(cut0+1, cut1).split(";");
...
根据您希望的复杂程度,您可以在部件上使用现有的表达式解析器 - 或者只是验证它们是否符合您能够处理的情况的某些假设...