简体   繁体   中英

JAVA- Read integers from txt file and compute integers

I need some help with the code below. What I'm trying to do is to write a program that reads in the file and computes the average grade and prints it out. I've tried several methods, like parsing the text file into parallel arrays, but I run into the problem of having the % character at the end of the grades. The program below is meant to add integers up too but the output is "No numbers found."

This is a clip of the text file (the whole file is 14 lines of similar input):

 Arthur Albert,74% Melissa Hay,72% William Jones,85% Rachel Lee,68% Joshua Planner,75% Jennifer Ranger,76% 

This is what I have so far:

final static String filename = "filesrc.txt";

public static void main(String[] args) throws IOException {

          Scanner scan = null;
          File f = new File(filename);
          try {
             scan = new Scanner(f);
          } catch (FileNotFoundException e) {
             System.out.println("File not found.");
             System.exit(0);
          }

          int total = 0;
          boolean foundInts = false; //flag to see if there are any integers

          while (scan.hasNextLine()) { //Note change
             String currentLine = scan.nextLine();
             //split into words
             String words[] = currentLine.split(" ");

             //For each word in the line
             for(String str : words) {
                try {
                   int num = Integer.parseInt(str);
                   total += num;
                   foundInts = true;
                   System.out.println("Found: " + num);
                }catch(NumberFormatException nfe) { }; //word is not an integer, do nothing
             }
          } //end while 

          if(!foundInts)
             System.out.println("No numbers found.");
          else
             System.out.println("Total: " + total);

          // close the scanner
          scan.close();
       }            
}

Any help would be much appreciated!

Here's the fixed code. Instead of splitting the input using

" "

you should have split it using

","

That way when you parse the split strings you can use the substring method and parse the number portion of the input.

For example, given the string

Arthur Albert,74%

my code will split it into Arthur ALbert and 74% . Then I can use the substring method and parse the first two characters of 74%, which will give me 74.

I wrote the code in a way so that it can handle any number between 0 and 999, and added comments when I made additions that you didn't already have. If you still have any questions however, don't be afraid to ask.

final static String filename = "filesrc.txt";

public static void main(String[] args) throws IOException {

          Scanner scan = null;
          File f = new File(filename);
          try {
             scan = new Scanner(f);
          } catch (FileNotFoundException e) {
             System.out.println("File not found.");
             System.exit(0);
          }

          int total = 0;
          boolean foundInts = false; //flag to see if there are any integers
             int successful = 0; // I did this to keep track of the number of times
             //a grade is found so I can divide the sum by the number to get the average

          while (scan.hasNextLine()) { //Note change
             String currentLine = scan.nextLine();
             //split into words
             String words[] = currentLine.split(",");

             //For each word in the line
             for(String str : words) {
                 System.out.println(str);
                try {
                    int num = 0;
                    //Checks if a grade is between 0 and 9, inclusive
                    if(str.charAt(1) == '%') {
                        num = Integer.parseInt(str.substring(0,1));
                        successful++;
                        total += num;
                       foundInts = true;
                       System.out.println("Found: " + num);
                    }
                    //Checks if a grade is between 10 and 99, inclusive
                    else if(str.charAt(2) == '%') {
                        num = Integer.parseInt(str.substring(0,2));
                        successful++;
                        total += num;
                       foundInts = true;
                       System.out.println("Found: " + num);
                    }
                    //Checks if a grade is 100 or above, inclusive(obviously not above 999)
                    else if(str.charAt(3) == '%') {
                        num = Integer.parseInt(str.substring(0,3));
                        successful++;
                        total += num;
                       foundInts = true;
                       System.out.println("Found: " + num);
                    }
                }catch(NumberFormatException nfe) { }; //word is not an integer, do nothing
             }
          } //end while 

          if(!foundInts)
             System.out.println("No numbers found.");
          else
             System.out.println("Total: " + total/successful);

          // close the scanner
          scan.close();
       }

Regex : ^(?<name>[^,]+),(?<score>[^%]+)

Details:

  • ^ Asserts position at start of a line
  • (?<>) Named Capture Group
  • [^] Match a single character not present in the list
  • + Matches between one and unlimited times

Java code :

import java.util.regex.Pattern;
import java.util.regex.Matcher;

final static String filename = "C:\\text.txt";

public static void main(String[] args)  throws IOException 
{
    String text = new Scanner(new File(filename)).useDelimiter("\\A").next();
    final Matcher matches = Pattern.compile("^(?<name>[^,]+),(?<score>[^%]+)").matcher(text);

    int sum = 0;
    int count = 0;
    while (matches.find()) {
        sum += Integer.parseInt(matches.group("score"));
        count++;
    }

    System.out.println(String.format("Average: %s%%", sum / count));
}

Output:

Avarege: 74%

If you have a small number of lines that adhere to the format you specified, you can try this (IMO) nice functional solution:

double avg = Files.readAllLines(new File(filename).toPath())
            .stream()
            .map(s -> s.trim().split(",")[1]) // get the percentage
            .map(s -> s.substring(0, s.length() - 1)) // strip off the '%' char at the end
            .mapToInt(Integer::valueOf)
            .average()
            .orElseThrow(() -> new RuntimeException("Empty integer stream!"));

System.out.format("Average is %.2f", avg);

Your split method is wrong, and you didn't use any Pattern and Matcher to get the int values. Here's a working example:

private final static String filename = "marks.txt";

public static void main(String[] args) {
    // Init an int to store the values.
    int total = 0;

    // try-for method!
    try (BufferedReader reader = Files.newBufferedReader(Paths.get(filename))) {
        // Read line by line until there is no line to read.
        String line = null;
        while ((line = reader.readLine()) != null) {
            // Get the numbers only uisng regex
            int getNumber = Integer.parseInt(
                    line.replaceAll("[^0-9]", "").trim());
            // Add up the total.
            total += getNumber;
        }
    } catch (IOException e) {
        System.out.println("File not found.");
        e.printStackTrace();
    }
    // Print the total only, you know how to do the avg.
    System.out.println(total);
}

You can change your code in the following way:

     Matcher m;
     int total = 0;
     final String PATTERN = "(?<=,)\\d+(?=%)";
     int count=0;
     while (scan.hasNextLine()) { //Note change
        String currentLine = scan.nextLine();
        //split into words
        m =  Pattern.compile(PATTERN).matcher(currentLine);
        while(m.find())
        {
            int num = Integer.parseInt(m.group());
            total += num;
            count++;
        }
     } 

     System.out.println("Total: " + total);
     if(count>0)
         System.out.println("Average: " + total/count + "%");

For your input, the output is

Total: 450
Average: 75%

Explanations:

I am using the following regex (?<=,)\\\\d+(?=%) n to extract numbers between the , and the % characters from each line.

Regex usage: https://regex101.com/r/t4yLzG/1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM