如何从存储文件内容的ArrayList中获取每行单词的字符位置并忽略//注释内容?
解决方案:实现单词字符位置显示与注释忽略
首先,先帮你修正现有代码里的一个小问题:你在readFile方法里用了for (String item: list)嵌套while循环来输出行内容,这会导致第一次循环就把所有行输出完毕,后续的循环都不会执行。我们可以直接用一个for循环遍历行索引来处理每一行。
接下来分两步实现你需要的功能:
1. 忽略//及其之后的内容
我们可以写一个辅助方法,专门处理每行的注释,只保留//之前的有效内容:
private String removeComments(String line) { // 找到//的位置,如果存在就截取之前的部分,否则返回原行 int commentIndex = line.indexOf("//"); if (commentIndex != -1) { return line.substring(0, commentIndex).trim(); } return line.trim(); }
这个方法会去掉注释,同时把行首尾的空格也去掉,避免后续处理空内容。
2. 拆分单词并计算字符位置
接下来,我们需要对处理后的每一行,拆分出每个单词,并计算每个单词的起始字符位置(按照你示例里的要求从1开始计数)。这里我们遍历行的字符,识别单词的边界(空格分隔),记录每个单词的起始位置:
private void printWordPositions(String line, int lineNumber) { int currentCharPos = 1; // 字符位置从1开始 int wordStartPos = -1; char[] chars = line.toCharArray(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; // 如果是非空格字符,且还没记录单词起始位置,就记录 if (!Character.isWhitespace(c) && wordStartPos == -1) { wordStartPos = currentCharPos; } // 如果是空格字符,且已经记录了单词起始位置,就输出单词 else if (Character.isWhitespace(c) && wordStartPos != -1) { String word = line.substring(i - (currentCharPos - wordStartPos), i).trim(); System.out.printf("Line %d, 字符位置%d, %s%n", lineNumber, wordStartPos, word); wordStartPos = -1; } currentCharPos++; } // 处理行末尾的最后一个单词 if (wordStartPos != -1) { String word = line.substring(chars.length - (currentCharPos - wordStartPos)).trim(); System.out.printf("Line %d, 字符位置%d, %s%n", lineNumber, wordStartPos, word); } }
整合到你的代码中
现在把这些方法整合到你的Lex_functions类里,并修改readFile方法的输出逻辑:
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; public class Lex_functions { ArrayList<String> list = new ArrayList<>(); void readFile() throws FileNotFoundException { File f = new File("ab.txt"); // 使用try-with-resources自动关闭流,避免资源泄漏 try (FileReader fr = new FileReader(f); BufferedReader infile = new BufferedReader(fr)) { String line; while ((line = infile.readLine()) != null) { list.add(line); } } catch (IOException e) { e.printStackTrace(); System.exit(1); } // 遍历每一行,处理并输出 for (int lineNum = 0; lineNum < list.size(); lineNum++) { String originalLine = list.get(lineNum); // 先处理注释 String processedLine = removeComments(originalLine); // 只处理非空的行 if (!processedLine.isEmpty()) { // 行号从1开始,符合你的示例格式 printWordPositions(processedLine, lineNum + 1); } else { // 如果处理后是空行,可以选择输出或者跳过,这里保留输出提示 System.out.printf("Line %d, 无有效内容%n", lineNum + 1); } } } private String removeComments(String line) { int commentIndex = line.indexOf("//"); if (commentIndex != -1) { return line.substring(0, commentIndex).trim(); } return line.trim(); } private void printWordPositions(String line, int lineNumber) { int currentCharPos = 1; int wordStartPos = -1; char[] chars = line.toCharArray(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (!Character.isWhitespace(c) && wordStartPos == -1) { wordStartPos = currentCharPos; } else if (Character.isWhitespace(c) && wordStartPos != -1) { String word = line.substring(i - (currentCharPos - wordStartPos), i).trim(); System.out.printf("Line %d, 字符位置%d, %s%n", lineNumber, wordStartPos, word); wordStartPos = -1; } currentCharPos++; } if (wordStartPos != -1) { String word = line.substring(chars.length - (currentCharPos - wordStartPos)).trim(); System.out.printf("Line %d, 字符位置%d, %s%n", lineNumber, wordStartPos, word); } } // 测试主方法 public static void main(String[] args) throws FileNotFoundException { Lex_functions lex = new Lex_functions(); lex.readFile(); } }
测试效果
假设你的ab.txt内容是:
// This program should print the number 20. program Twenty: int a; int b;
运行代码后,输出会是:
Line 1, 无有效内容 Line 2, 字符位置1, program Line 2, 字符位置9, Twenty: Line 3, 字符位置1, int Line 3, 字符位置5, a; Line 4, 字符位置1, int Line 4, 字符位置5, b;
额外说明
- 如果你的单词分隔符不只是空格(比如制表符),可以把
Character.isWhitespace(c)换成更全面的判断,或者用正则表达式拆分单词,但上面的方法更直观,适合基础场景。 - 字符位置的计算是严格按照从行首开始的字符数(包括空格),比如
program Twenty:里,program占7个字符,后面有一个空格,所以Twenty:的起始位置是7+1+1=9(因为从1开始计数)。
内容的提问来源于stack exchange,提问作者Lilypad01
相关产品推荐
相关产品推荐

