用于定位缺失括号的递归和迭代方法

时间:2013-07-11 02:56:42

标签: java eclipse recursion iterator

对于此分配,规范很简单。您将获得一个任意长度的文本文件 (可能有数千个字符)。要被认为是正确的,它必须包含匹配的对 括号{ }[ ]( )。支架对可以嵌套到任意深度(但不是那么深 你需要担心堆栈溢出)括号内任意数量的文本。一份文件 不包含括号是非常正确的。当你发现一对不匹配的括号时, 您必须在文件中报告括号及其索引。文件中的第一个字符是索引0。 例如,如果文件包含 此文件具有打开的{ and another { followed by ) and }和一些文本。 您的程序应报告不匹配,因为索引为50的{ at index 36 is closed by the )。 您可以将文件的开头视为与任何文件不匹配的超级opening bracket 关闭括号。如果文件包含太多关闭括号,则不匹配的opening bracket是文件的开头。您应该使用字符串STX(旧的ascii start of text)来报告此情况。例如,此结束]没有匹配的打开[。 在这种情况下,您的程序应报告不匹配,因为 索引为-1的STX由索引13处的]关闭。同样,您可以将文件末尾视为与任何左括号不匹配的超级closing bracket。文件可能包含太多的左括号。报告此情况,好像不匹配的closing bracket在文件结束后真的是(不存在)关闭括号。例如,这个打开(没有匹配重新将此作为不匹配,因为索引10处的(由索引24处的EOF关闭。您的任务是编写两个方法,递归方法,recursiveMatch和迭代方法, iterativeMatch,处理文件并检查括号是否匹配。当任何一种方法时 检测到括号不匹配,它应该抛出类的异常 Matchfail。 Matchfail对象中的信息应包括文件中不匹配的括号及其索引。

这是我到目前为止的代码:

import java.io.File ;
import java.io.FileReader ;
import java.io.IOException ;

/**
* Development driver for Assignment #4, matching brackets.
 * 
 * @author lou
 * @param args[0]
 *            name of a file to check
 */
public class Assign4 {

 public static void main(String[] args) {
/*
 * Check that the user has supplied a file name, and that the file
 * exists and is readable.
 */
if (args.length <= 0) {
  System.out.println("Usage: java Assign4 <filename>") ;
  System.exit(1) ;
}
String fileName = args[0] ;
File handle = new File(fileName) ;
if (!(handle.exists() && handle.canRead())) {
  System.out.println("Please check that file \"" + fileName
      + "\" exists and is readable.") ;
  System.exit(2) ;
}
/*
 * Create an input stream of type FileReader to read the file character
 * by character. This can throw a (checked) IOException so we need to
 * wrap it in a try/catch block.
 *
 * It's good practice to always close a FileReader to avoid
 * a resource leak (resources that are allocated but not released). If
 * src is not null, resources may have been allocated even if creation of
 * the FileReader fails and we should attempt a close to free them.
 * Closing a file reader can itself throw an IOException, so we need a
 * nested try/catch block.
 */
FileReader src = null ;
try {
  src = new FileReader(handle) ;
} catch (IOException ex) {
  System.out.println("Exception while opening file \"" +
      fileName + "\" for read.") ;
  System.out.println("Exception: " + ex) ;
  try {
if (src != null) src.close() ;
  } catch (IOException closeEx) {
System.out.println(
    "Exception while closing file \"" + fileName + "\".") ;
System.out.println("Exception: " + closeEx) ;
  }
  System.exit(3) ;
}
/*
 * Try the recursive match method first. A MatchFail exception is
 * certainly a possibility. Allow that other exceptions might be thrown
 * but don't attempt to do anything.
 */
MatchBrackets matcher = new MatchBrackets() ;
try {
  matcher.recursiveMatch(src) ;
  System.out.println("Brackets match (recursive)!") ;
} catch (MatchFail ex) {
  System.out.println("A bracket on its own is up to no good!") ;
  System.out.println(ex) ;
} catch (Exception ex) {
  System.out.println("Unexpected exception "+ex) ;
}
/*
 * We need to return to the beginning of the file to test the iterative
 * match. For a FileReader, this requires closing and reopening the file.
 */
try {
  System.out.println("Attempting close and reopen.") ;
  src.close() ;
  src = new FileReader(handle) ;
} catch (IOException ex) {
  System.out.println("Exception while reopening file \"" + fileName
  + "\" for read.") ;
  System.out.println("Exception: " + ex) ;
  try {
if (src != null) src.close() ;
  } catch (IOException closeEx) {
System.out.println(
    "Exception while closing file \"" + fileName + "\".") ;
System.out.println("Exception: " + closeEx) ;
  }
  System.exit(3) ;
}
/*
 * Try the iterative match method.
 */
try {
  matcher.iterativeMatch(src) ;
  System.out.println("Brackets match (iterative)!") ;
} catch (MatchFail ex) {
  System.out.println("A bracket on its own is up to no good!") ;
  System.out.println(ex) ;
} catch (Exception ex) {
  System.out.println("Unexpected exception "+ex) ;
}
/*
 * Close the file and we're done.
 */
try {
  src.close() ;
} catch (IOException ex) {
  System.out.println(
      "Exception while closing file \"" + fileName + "\".") ;
  System.out.println("Exception: " + ex) ;
  System.exit(3) ;
}
return ;
}
}

import java.io.FileReader ;
import java.io.IOException ;
import java.util.ArrayDeque ;

/**
  Skeleton for the MatchBrackets class.
*/
public class MatchBrackets {

  /**
   * Make a constant so it's clear we're recognising end-of-file.
   */
  private final int EOF = -1 ;

  /**
   * A helper method to encapsulate the activity of reading a
   * character.
   * 
   * The FileReader class uses a common convention in character i/o:
   * return each character as an int; this allows the value -1 to be
   * used to indicate EOF. This little helper routine simply hides the
   * try/catch statement that's required to handle the possibility
   * that FileReader.read might throw an IOException.
   * 
   * @param source
   *        source of characters
   * @return EOF on end-of-file or exception, or a single character
   *         (as an int)
   */
  private int getOneChar (FileReader source)
  {
    int charAsInt = EOF ;
   try {
  charAsInt = source.read() ;
    } catch (IOException ex) {
   System.out.println("Exception: " + ex) ;
  charAsInt = EOF ;
   }
   return (charAsInt) ;
  }

/**
 * Recursive method to match brackets.
 * 
 * @param src
 *        source of characters
 */
public void recursiveMatch (FileReader src)
       throws MatchFail 
{
/*
  You must write a proper body for recursiveMatch. The bit of code below
  is just to show you how to use getOneChar and throw an exception.
*/
int charAsInt = getOneChar(src) ;
if (charAsInt != EOF) {
  char firstChar = (char) charAsInt ;
  System.out.println(
      "The first character of the file is '" + firstChar + "'.") ;
} else {
  System.out.println("This file is empty!") ;
}
throw new MatchFail("You must write recursiveMatch!",42,
            Character.toString('}'),42) ;
}

/**
 * Iterative method to match brackets.
 * 
 * @param src
 *        source of characters
 */
public void iterativeMatch (FileReader src) throws MatchFail
{
  /*
    You must write a proper body for this method, too.
  */
  throw new MatchFail() ;
}

}

/**
 Exception class for use by the bracket matching methods.
 <p>
 When a bracket mismatch is detected, this exception object should be
 created, loaded with information about the mismatched pair of brackets, and
 thrown.
 </p><p>
 The information provided should include the opening bracket and its index in
 the file, and the closing bracket and its index in the file.
 For a file containing K characters, character indices range from 0 to K-1.
 By definition,
 <ul>
 <li> the `character' before the start of the file has index -1 and is
 represented by the string "STX" (start of text).</li>
 <li> the `character' after the end of the file has index K and is
     represented by the string "EOF" (end of file).</li>
 </ul>
 </p><p>
 MatchFail is subclassed from Exception, hence it is a checkable exception
 and methods that might throw MatchFail must declare the exception with a
 throws clause.
  */

 public class MatchFail extends Exception
 {

/**
Index of opening bracket of the mismatched pair.
*/
private int openNdx ;

/**
String representation of the opening bracket of the mismatched
pair.
*/
private String openBkt ;

/**
Index of closing bracket of the mismatched pair.
*/
private int closeNdx ;

/**
String representation of the opening bracket of the mismatched
pair.
*/
private String closeBkt ;

/**
Convenience constructor to set all attributes.
*/
public MatchFail (String openBkt, int openNdx,
        String closeBkt, int closeNdx)
{ this.openBkt = openBkt ;
this.openNdx = openNdx ;
this.closeBkt = closeBkt ;
this.closeNdx = closeNdx ;
}

/**
Constructor.
<p>
Initialise the attributes to values that are obviously invalid so it's
easy to detect algorithm errors.
</p>
*/
public MatchFail ()
{
  this("invalid",-10,"invalid",-10) ;
}

/** Retrieve the opening bracket. */
public String getOpenBkt () { return (openBkt) ; }

/** Retrieve the index of the opening bracket. */
public int getOpenIndex () { return (openNdx) ; }

/** Retrieve the closing bracket. */
public String getCloseBkt () { return (closeBkt) ; }

/** Retrieve the index of the opening bracket. */
public int getCloseIndex () { return (closeNdx) ; }

/** Set the opening bracket. */
public void setOpenBkt (String openBkt) { this.openBkt = openBkt ; }

/** Set the index of the opening bracket. */
public void setOpenIndex (int openNdx) { this.openNdx = openNdx ; }

/** Set the closing bracket. */
public void setCloseBkt (String closeBkt) { this.closeBkt = closeBkt ; }

/** Set the index of the closing bracket. */
public void setCloseIndex (int closeNdx) { this.closeNdx = closeNdx ; }

/** Return a string representation of the exception. */
public String toString ()
{
  String rep = "'"+openBkt+"' at index "+openNdx+" matched to '" +
         closeBkt+"' at index "+closeNdx ;
   return (rep) ;
}

}

我遇到的问题是创建递归和迭代器方法,以便找到括号并报告缺少括号所在的索引。我真的不明白我应该怎么做。任何帮助都将不胜感激! 谢谢。

2 个答案:

答案 0 :(得分:0)

在解析文档时,每次遇到启动程序时都会创建一个新文档,并使用当前计数器循环变量值将它们添加到堆栈中。

public class Bracket {
    int location;
    char bracket;

    public Bracket(int loc, char b) {
        location = loc;
        bracket = b;
    }

    public char getBracket() { return bracket; }
            public int getLoc() { return location; }

    public static boolean isStarter(char b) {
        return b == '(' || b == '{'; // || etc....
    }

    public boolean equals(Bracket other) {
        return bracket == other.getBracket();
    }

    public char getMatching() {
        switch(bracket) {
            case '(': return ')';
            // so on and so forth
        }
    }

    public boolean matches(char other) {
      return (getMatching() == other);
    }
}

然后,在你的代码中: 堆栈堆栈=新堆栈&lt;&gt;();

// in your loop
if (Bracket.isStarter(currentCharacter)) {
  stack.push(new Bracket(currentLocation, currentCharacter));
} else {
   if (stack.peek().matches(currentCharacter))
     stack.pop();
   else {
     Bracket b = stack.pop();
     System.out.println("Mismatch error " + b.getBracket() + 
       " at character position " + b.getLoc() + 
       " followed by a " + currentCharacter + 
       " at position " + currentPosition + ".");
   }
} // something on this order at least

答案 1 :(得分:0)

//Below Code is for checking if given string is well formatted with Brackets
// 123{456}[1+2] is well formatted and a valid Input/String/Expression
//123{[456}] is not well formatted and not a valid Input/String/Expression  
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace CodeProject
    {
        class JsonFormattingCheck
        {
            Stack<char> CheckStack;
            public JsonFormattingCheck()
            {
                CheckStack = new Stack<char>();
            }

            public bool ValidInput(string input)
            {
                bool valid = true;
                char currentliteral;
                if (input.Contains("(") == true || input.Contains("[") == true || input.Contains("}") == true || input.Contains(")") == true || input.Contains("]") == true || input.Contains("}") == true)
                {
                    foreach (char literal in input)
                    {
                        if(literal == '{' || literal == '(' || literal == '[')
                        {
                            CheckStack.Push(literal);
                        }
                        else if (literal == '}' || literal == ')' || literal == ']')
                        {                        
                            if (CheckStack.Count() == 0 )
                                valid = false;
                            else 
                            {
                                currentliteral = CheckStack.Pop();
                                for (; currentliteral != '{' && currentliteral != '(' && currentliteral == '['; )
                                {
                                    currentliteral = CheckStack.Pop();
                                }

                                switch(currentliteral)
                                {
                                    case '{':
                                        if (literal != '}')
                                            valid = false;
                                            break;
                                    case '[':
                                            if (literal != ']')
                                                valid = false;
                                            break;
                                    case '(':
                                            if (literal != ')')
                                                valid = false;
                                            break;
                                }
                            }
                        }
                        if (valid == false)
                            break;
                    }
                }
                return valid;
            }
        }
    }


    ----
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;

    namespace CodeProject
    {
        class Program
        {
            static void Main(string[] args)
            {
                JsonFormattingCheck json = new JsonFormattingCheck();

                //Test Data
                string s = "123(233){212}";
                s = "{{2247]}}[";

                bool valid = json.ValidInput(s);
                if (valid == true)
                    Console.WriteLine(s+" valid");
                else
                    Console.WriteLine(s + " Invalid");
                Console.ReadLine();
            }
        }
    }