提问人:oresky 提问时间:3/21/2023 更新时间:3/21/2023 访问量:40
循环访问文本文件时,For 循环比预期更早终止
For loop terminates earlier than expected when iterating over a text file
问:
我一直在读这本书,Sedgewick 和 Wayne 的算法,这是第 1 章中给出的练习之一:
1.3.4 编写一个堆栈客户端括号,用于从标准输入中读取文本流,并使用堆栈来确定其括号是否正确平衡。例如,程序应为 [()]{}{()()()} 打印 true,为 [(]) 打印 false。
现在,我的解决方案在使用 while 循环时有效(尽管它并不完全按照要求执行):
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
public class Parenthesis {
public static void main(String[] args) {
In input = new In("parenthesis.txt");
LinkedListStack<String> stack = new LinkedListStack<>();
while (!input.isEmpty()) {
String s = input.readLine();
if (s.equals("("))
stack.push(s);
else if (s.equals(")"))
if (!stack.isEmpty())
stack.pop();
else
stack.push(s);
}
if (stack.isEmpty())
StdOut.println("Balanced");
else
StdOut.println("Unbalanced");
}
}
但是当我用 for 循环替换 while 循环时,循环在到达最后一个“)”之前就终止了:
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.StdOut;
public class Parenthesis {
public static void main(String[] args) {
In input = new In("parenthesis.txt");
LinkedListStack<String> stack = new LinkedListStack<>();
for (String s = input.readLine(); !input.isEmpty(); s = input.readLine()) {
if (s.equals("("))
stack.push(s);
else if (s.equals(")"))
if (!stack.isEmpty())
stack.pop();
else
stack.push(s);
}
if (stack.isEmpty())
StdOut.println("Balanced");
else
StdOut.println("Unbalanced");
}
}
我以为我使用的 for 循环只是 while 循环的紧凑版本,但显然我做错了什么。我尝试一遍又一遍地调试代码,但无法弄清楚为什么会发生这种情况。
P.S. 如果有更有效的方法来解决这个问题,请分享。谢谢!
答:
0赞
tgdavies
3/21/2023
#1
因为 for 循环在执行增量后会检查其终止条件,如果它为 false,则会终止它,因此永远不会使用 which 将 移动到空的结果。readLine
In
运行此代码以查看:
public class X {
public static void main(String[] args) {
In in = new In();
for (String s = in.readLine(); !in.isEmpty(); s = in.readLine()) {
System.out.println("body");
}
}
}
class In {
private int count = 0;
public String readLine() {
System.out.println("readLine " + count);
return ""+count++;
}
public boolean isEmpty() {
System.out.println("isEmpty " + count);
return count > 2;
}
}
输出为:
readLine 0
isEmpty 1
body
readLine 1
isEmpty 2
body
readLine 2
isEmpty 3
看到最后一个 .body
readLine
程序中的另一个错误是至少调用一次 - 即使 已经是空的。readLine
In
如果你真的想使用一个循环,你可以创建一个并使用一个foreach循环:for
Iterable
import java.util.Iterator;
public class X {
public static void main(String[] args) {
In in = new In();
for (String s: new InIterable(in)) {
System.out.println("body " + s);
}
}
}
class InIterable implements Iterable<String> {
private final In in;
InIterable(In in) {
this.in = in;
}
@Override
public Iterator<String> iterator() {
return new Iterator<>() {
@Override
public boolean hasNext() {
return !in.isEmpty();
}
@Override
public String next() {
return in.readLine();
}
};
}
}
评论
0赞
oresky
3/21/2023
有没有办法在递增之前进行 for 循环检查条件?
评论
for (String s = input.readLine(); !input.isEmpty(); s = input.readLine()) {
edu.princeton.cs.algs4.In
String s = input.readLine()
s
!input.isEmpty()
input.readLine()
s
In