扫描器帮助 - Java

3

我希望您能为我提供一些帮助,因为我已经不知道该如何完成这个任务了。

这项任务是读取一个包含州名、该州州长和他的薪酬信息的文件。

文件示例:

California Tim John $50,000 $78,890 $30,000
North Dakota John Jones $30,000 $40,000 $56,000
Washington Susan K. Bones $30,000 $40,000 $56,000

正如您所看到的,一个名字可以包含超过三个单词(包括中间的缩写)

我需要得到的输出是总补偿金额后面跟着总统的姓名…

输出示例:

Susan K. Bones $126,000

我已经编写了打印总补偿的代码。但是我卡在了读取姓名上。如何忽略最多只包含两个单词的州名,只取州长的名字呢?

这是我的总补偿代码。

还要注意:我必须在此使用Scanner。

Scanner in = new Scanner(file);
            in.nextLine();      
                do {
                    double totalCompensation = 0.0; 
                    String readLine = in.nextLine();
                    readLine = readLine.replaceAll(",", "").replace("$", " ");
                    String presidentName = "";
                    Scanner readNumber = new Scanner(readLine);
                    while(readNumber.hasNext()) {                               
                        if (readNumber.hasNextDouble()) 
                            totalCompensation += readNumber.nextDouble();
                        else {
                            readNumber.next();
                        }
                    }

另外一点提示:不用担心,我代码中有一个 while(in.hasNextLine()) 来关闭 do 循环。我只是不想复制整个代码。

任何提示都会很受欢迎!感谢!

4个回答

2
如果你事先知道只会看到美国州名,你可以让代码首先查找州名。由于你知道哪部分是州名,哪部分是补偿,剩下的一定是州长的名字。只有50个州,所以这并不难。
如果这更通用,可以是城市/国家/任何地方,而不仅仅是美国,则没有办法在没有更好的分隔符(或引号来定义“州名”和“州长名字”)的情况下区分。
编辑:你提到还有一个要求,即“领导者”的姓名将是“名字 姓氏”、“名字 M. 姓氏”或“F. 中间名 姓氏”的形式。现在你已经有足够的条件来解决答案了。
当你用扫描器从字符串中提取出字符时,将它们放在列表中(如果你学过这种数据类型,栈更合适)。向后遍历列表。如果第二个元素是缩写,你就知道名字有三个部分。如果第三个元素是缩写,你就知道名字有三个部分。如果两个部分都不是缩写,你就知道名字有两个部分。不是领导人名字的那部分就是地名。

是的,它们也可能包含城市名称 :( 但一定有办法...我被分配为这个作业!作业提示告诉我们要从美元符号开始倒推... - watabou

1

文件是否可以修改以包含除空格之外的其他分隔符,例如分号。否则,我能想到的一个选项是存储状态列表并迭代它们并检查,否则它将是一个名称。例如。

List<String> stateNames={"Alabama","Alaska","Texas"};

是的,我们可以使用分隔符,但我们无法修改文件...我不想列出州名,因为它可能是任何东西,比如国家或城市名称,这将是一个巨大的麻烦。 :( - watabou

1

我的上一个答案完全没有使用Scanner,这是一个明确的要求。和以前一样,我使用“New”,“North”等前缀来区分两个单词的州名。

static String[] TWO_WORD_STATE_PREFIXES = new String[] {"New", "Rhode", "North", "West", "South"};

public static void scanLine(String line) {
    Scanner s = new Scanner(line);
    String stateName = s.next();

    for (String prefix : TWO_WORD_STATE_PREFIXES)
        if (stateName.equals(prefix))
            stateName += " " + s.next();

    String governorName = "";

    String nextToken;
    while (!(nextToken = s.next()).startsWith("$"))
        governorName += nextToken + " ";

    governorName = governorName.trim();

    int compensation = 0;
    while (s.hasNext())
        compensation += Integer.parseInt(s.next().replaceAll("[\\$, ]", ""));

    System.out.println(stateName + " - " + governorName + " : " + compensation);
}

public static void main(String[] args) {
    scanLine("California Tim John $50,000 $78,890 $30,000");
    scanLine("Virginia Some Guy $55,000 $71,890 $30,000");
    scanLine("South Carolina Bill F. Gates $91,000 $1,200");
    scanLine("Vermont Joan Smith $60,000 $78,890 $30,000");
    scanLine("North Dakota Tim John $50,000 $78,890 $30,000");
}

嗯,谢谢!我会试一试看看。天啊,我真希望我能点赞一些帖子,可惜我还差一个点才能投票,抱歉:( 唯一让我感到困扰的是我的老师说我应该期待城市名称而不是州名,所以这可能是我最难的编程作业,而且我只有一周时间完成它!耶! - watabou
我不明白如何在不提前知道城市列表或添加其他分隔符的情况下,使用城市完成这项任务。至少对于州来说,有一个明确定义且容易获取的州名列表。 - cutchin
是的,我得想出解决方法。显然,其他人已经完成并且使用城市名称使其正常工作,所以这应该很容易。我们的老师说:“从第一个美元金额开始向后推,然后将前两个单词作为名称,除非第一个单词的形式为X.,其中X是一个字母,或者前面的单词的形式为X.,在这种情况下,名称有三个部分。”不过我不知道如何“向后推”。 - watabou
关于您上面提到的“向后走”的评论,这意味着您被告知州长/市长的姓名将采用“名字 姓氏”或“名字 M.I. 姓氏”的格式。但这仍然不是一个非常明确的格式,因为它不能适用于使用三个名称的州长。比如西弗吉尼亚州的Earl Ray Tomblin。如果是这种情况,我的代码显然无法工作。您需要查找中间的缩写并相应地进行操作。 - cutchin

0

这个问题与高效字符串搜索有关。让我们确定字符串的哪一部分是城市或州名,因为一旦你确定了这一点,其余的就很简单了。

首先,您需要一个城市和州的列表。这里有一个城市列表(应该很容易解析出实际的城市名称)http://www.census.gov/tiger/tms/gazetteer/places2k.txt,我相信您可以在某个地方找到一个州的列表。

一旦您拥有了这些,这里是一个高效解决方案的简单策略:

  • 将城市和州的列表放入哈希表中
  • 通过空格拆分输入字符串(例如“Califonia John Doe $213 $1232”)
  • 对于此列表的每个前缀,请检查相应的字符串是否在哈希表中 - 如果是,则假定那是州/城市,并相应地解析输入的其余部分。

编辑:算了 - 你在问题中添加了一些信息,使得解决它变得容易多了。现在不再是一个高效的字符串搜索问题,而是一个简单的Java循环练习题。请参考Kane的答案。

有趣的是,仅仅一点点的信息就能彻底改变一个问题的范围 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接