该程序试图将文本文件分成单词,然后在每次使用每个单词时进行计数。扫描仪似乎只是读取每行的部分,我不知道为什么。这是我第一次使用这种扫描方法。
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
public class WordStats {
public static void main(String args[]){
ArrayList<String> words = new ArrayList<>(1);
ArrayList<Integer> num = new ArrayList<>(1);
Scanner sc2 = null;
try {
sc2 = new Scanner(new File("source.txt"));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
while (sc2.hasNextLine()) {
Scanner s2 = new Scanner(sc2.nextLine());
boolean set=false;
while (s2.hasNext()) {
num.add(1);
String s = s2.next().replaceAll("[^A-Za-z ]", " ").toLowerCase().trim();
for(int i=0;i<words.size(); i++){
if(s.equals(words.get(i))){
num.set(i,num.get(i)+1);
set=true;
}
}
if(!set){
words.add(s);
num.add(1);
}
}
}
for(int i=0;i<words.size();i++){
System.out.println(words.get(i)+" "+num.get(i));
}
}
}
文本文件是葛底斯堡地址:
ABRAHAM LINCOLN,“GETTYSBURG ADDRESS”(1863年11月19日)
八十年前,我们的父亲们提出了这个问题 大陆,一个新的国家,在自由中孕育,并致力于 所有人都是平等的命题。现在我们正在进行一场伟大的内战,检验那个国家, 或任何如此构想和如此奉献的国家,都可以长久忍受。我们是 在那场战争的伟大战场上相遇。我们来奉献了一个 该领域的一部分,作为在这里的人的最后安息之地 献出了生命,那个国家可能会生活。它完全合适 我们应该这样做。
但是,从更广泛的意义上说,我们不能奉献 - 我们奉献 - 我们不能 神圣 - 这个地面。勇敢的人,无论是活着的还是死去的,都在挣扎着 在这里,已经将它奉为神圣,远远高于我们增加或减少的力量。 世界将很少注意到,也不记得我们在这里所说的,但它 永远不会忘记他们在这里做了什么。这对我们来说是生活,相反, 在这里献身于他们在这里战斗的未完成的工作 迄今为止如此高尚。我们宁愿来到这里 致力于摆在我们面前的伟大任务 - 来自这些 尊敬的死者,我们更加热爱他们的事业 给出了最后一个充分的奉献精神 - 我们在这里高度解决 这些死者不会白白死去 - 这个国家,在这之下 上帝,将有一个新的自由诞生 - 和那个政府 人民,人民,不为人民灭亡。
保留原始换行符。 我的输出似乎只计算每一行的一部分,并且还将空格作为单词计算两次。 输出:
abraham 1
lincoln 1
gettysburg 1
address 1
2
november 1
fourscore 1
and 5
seven 1
years 1
ago 1
our 2
fathers 1
brought 1
forth 1
on 2
this 3
continent 1
a 7
new 2
nation 5
conceived 2
in 4
liberty 1
now 1
we 8
are 2
engaged 1
but 2
它可能不是扫描方法,但我对代码的这一部分比较熟悉,我认为不是这样。
答案 0 :(得分:1)
问题是您的代码在循环的每次迭代中无条件地将1
添加到num
列表。这会使num
与words
相关,从而产生错误的输出。
从嵌套的num.add(1);
循环中删除while
可以解决问题。但是,更好的方法是使Map<String,Integer>
跟踪计数。除了确保计数和单词始终处于同步状态之外,此更改还允许您完全删除嵌套的while
循环,并根据您的地图算法使用快速查找。
答案 1 :(得分:1)
逻辑有点偏斜。您有并行列表,它们应具有相同数量的元素,但不会并行添加。
Map<String, Integer> wordFrequencies = new TreeMap<>();
while (sc2.hasNextLine()) {
Scanner s2 = new Scanner(sc2.nextLine());
while (s2.hasNext()) {
String word = s2.next().replaceAll("[^A-Za-z ]", " ")
.toLowerCase().trim();
Integer n = wordFrequencies.get(word);
wordFrequencies.put(word, n == null ? 1 : 1 + n);
}
}
for (Map.Entry<String, Integer> entry : wordFrequencies.entrySet()) {
System.out.printf("%-40s %5d%n", entry.getKey(), entry.getValue());
}
答案 2 :(得分:1)
您需要在此while循环的开头重置布尔值
while (s2.hasNext()) {
set = false;
一旦您在每一行中遇到第一个重复的单词,则set始终为true,并且没有新单词添加到您的列表中。
空白计数是因为你的替代品如何处理&#34;(19&#34;和#34; 1863)&#34;因为那些&#34;单词&#34;。
中没有字母字符