对于此分配,规范很简单。您将获得一个任意长度的文本文件
(可能有数千个字符)。要被认为是正确的,它必须包含匹配的对
括号{ }
,[ ]
和( )
。支架对可以嵌套到任意深度(但不是那么深
你需要担心堆栈溢出)括号内任意数量的文本。一份文件
不包含括号是非常正确的。当你发现一对不匹配的括号时,
您必须在文件中报告括号及其索引。文件中的第一个字符是索引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) ;
}
}
我遇到的问题是创建递归和迭代器方法,以便找到括号并报告缺少括号所在的索引。我真的不明白我应该怎么做。任何帮助都将不胜感激! 谢谢。
答案 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();
}
}
}