Im working on programming for class, and we are looking at the sample code provided that takes the daily earnings for 4 weeks and prints out the day with the highest earnings. The program uses a dat file to read in the information and print the results. What I would like to understand is what exactly does String[ ]s = t.split(" ") do? It doesn't seem to be an array..
Data File
4
1300 1500 1200 1600 1800 900 1400
1200 1400 1500 1600 1100 1450 1475
1745 2534 2000 2100 2400 1975 1823
2231 1992 2000 2345 2435 1982 2500
The first number in the data file lists the number of lines (Weeks) to follow. Each line after that contains 7 numbers each correlating to a day of the week Sunday - Saturday.
Main Code from practice set. I added comments for each line, to fully explain my problem.
The line I dont understand is String []s = t.split(" ");
import java.io.*;
import java.util.*;
import static java.lang.System.*;
public class BestDay {
public static void main(String args[]) throws IOException
{
Scanner kb = new Scanner(new File("bestday.dat")); //Imports File
int count = 0; //Basic Counter for While loop
int totalWeeks = Integer.parseInt(kb.nextLine().trim()); //Number of Weeks from First Line of Data File (4)
while(count < totalWeeks) { //Runs While loop as long as times is greater than count
count++; //Increments Count
String t = kb.nextLine().trim(); // pulls in the next line as a string and trims blank spaces
String []s = t.split(" "); //Not Sure what is happening here) Someone Explain pls.
int most = Integer.parseInt(s[0]); //Takes each number and registers it as Int
int day = 0; //Sets an int for later comparison
for(int i=1; i<7; i++) { //for loop runs 7 times one for each day of the week for every 1 while loop run
int next = Integer.parseInt(s[i]); //brings in each other integer.
if (next > most) {// compares it
most=next; //If next is more than most then sets most to next
day=i; //sets day to i basically telling which day was the highest value on
}
}
switch (day) {
case 0: out.println("SUNDAY"); break; //looks at each case with Day and prints out the right case.
case 1: out.println("MONDAY"); break;
case 2: out.println("TUESDAY"); break;
case 3: out.println("WEDNESDAY"); break;
case 4: out.println("THURSDAY"); break;
case 5: out.println("FRIDAY"); break;
case 6: out.println("SATURDAY"); break;
}
}
}
}
Expected Output
THURSDAY
WEDNESDAY
MONDAY
SATURDAY
From the Javadocs for String.split(String):
Splits this string around matches of the given regular expression.
Essentially, it tokenizes the target string into separate strings which were joined by the argument regular expression.
For example:
"foo bar gah".split(" "); // => { "foo", "bar", "gah" }
"Mississipian".split("i"); // => { "M", "ss", "ss", "pp", "an" }
See the documentation for String.split: it splits a string using a regular expression. Specifically (as per the docs):
Splits this string around matches of the given regular expression.
This method works as if by invoking the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are therefore not included in the resulting array.
In this case it simply splits a line from your file (such as 1300 1500 1200 1600 1800 900 1400) on the specified pattern (in this case a " ") and returns an array of the individual strings. e.g.
{"1300", "1500", "1200", "1600", "1800", "900", "1400"}
Your first port of call for any "what does this java function do" question should be the java documentation at http://docs.oracle.com/javase/7/docs/api/overview-summary.html
String.split splits the given string using a delimiter and stores it in an array. In your case, its space. So using it on the 2nd line would provide you this array s[] = { 1300, 1500, 1200, 1600, 1800, 900, 1400 }
From javadoc
String.split(String regex)
Splits this string around matches of the given regular expression.
(Next time read the docs)
Take a look at official java documentation here.
Small snipped:
String[] parts = "123 156";
String[] parts = string.split(" ");
parts will be an array of 2 elements containing "123" and "456" string respectively. The argument passed as input is used by split method to match the given regular expression (in my example a simple token string).
Related
Im trying to make an if statement that deducts 2 points for each time the verb 'me' or 'I' is found in a string. To do this I have split the string into separate words. To test I changed the string to have 2x "me". But the score is only deducted once instead of twice (as there are 2 x "me"). Tried adding a while loop but it just kept deducting until negative. Baby language please, I am a beginner coder. Thanks in advance
public static void main(String[] args) { //getWordLength() { // Checking word length. Less than 6 means reviewer can't weigh out positives and negatives
// TODO Auto-generated method stub
int ReviewScore = 30;
String Review = "me I me, from Montreal";
String[] words = Review.split("\\s+");
System.out.println("Word Count is: "+words.length);
int wordlength = Integer.valueOf(words.length);
if (wordlength< 6) {
ReviewScore -=4; // deducts 4pts if review less than 6 words
System.out.println("Score is "+ ReviewScore);
}
verbCount( ReviewScore,Review);
}
public static void verbCount (int ReviewScore, String Review) { //Count verbs 'I' or 'me'
for (String s : Review.split("\n") ) { // splits review into separate words
if (s.contains("me" )){ // Checks for 'me' or 'I'
ReviewScore -= 2;
System.out.println("Score is "+ ReviewScore); // deducts by 2 pts
if ( s.contains ("I")) {
ReviewScore -= 2;
System.out.println("Score is "+ ReviewScore);
}
}
}
}
}
First you should return the review score from your method verbcount.
Second you split the text twice, once by word boundaries ("\s+"), but inside your method verbcount you split it by newlines ("\n") and therefore the method is not working as intended.
Instead of the string to review, pass the words array into that method and don't split it again!
Third your ifs are nested, so the s.contains ("I") will only be checked, if also s.contains("me") - this can happen because you split by lines, but only once per line. Also once you split words, you will never get into that second if-branch.
Pull it up one level to be in parallel to the first if inside the method.
I do not get the Error when I run my code on IntelliJ. However, when I try to hand in my Code for the assignement Im working on, I get NFE for both test cases. I deleted all of my Code and let only the bellow code run through the test cases. Somewhere in here must be a NumberFormatException.
public class Search {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine();
int[] list = new int[n];
String [] tokens = sc.nextLine().trim().split(" ");
for (int i=0; i<tokens.length;i++){
list[i]=Integer.parseInt(tokens[i]);
}
}
}
I read about double spaces and checked this with: System.out.println(Arrays.asList(tokens).contains(""));
Output was false so this is not an option. As you can see I'm already using trim().
I'd appreciate your help.
Louis
Eddit:
Alright something is fishy here. I added
System.out.println(Arrays.asList(tokens).contains(""));
System.out.println(Arrays.toString(tokens));
To my Code and handed it in to the test cases. While IntelliJ would deliver false followed by an array of integers, the test case outputs:
true
[]
.
Therefore you all are right and I just falsely assumed that the input in my test cases would be similar to the example Input I was given in the assignment.
Edit2:
ALRIGHT!
I figured it out. The Input of the test cases was simply not the same format as the one in my test Input which looked a bit like this:
10
8 8 9 12 110 111 117 186 298 321
2
8 13
I assume that the sc.nextLine() that I included skipped integers that I needed to make my list.
So the actual problem was not that extra spaces or anything, it was simply that I advanced past the input I wanted through my usage of sc.nextLine().
The answer that gave me the hint I needed, even tho I dont think this was intended came from Andronicus.
Thanks to everybody else anyways.
If you know, that there is going to be an integer as an input and you're not worried about parsing, why not using this instead?
int input = sc.nextInt();
In your solution you would have to do:
Arrays.stream(sc.nextLine().trim().split(" ")).filter(s -> !s.matches("\\s")).toArray(String[]::new);
\\ or simplier
sc.nextLine().trim().split("\\s+")
There's a number of possible causes:
There's a non-number in tokens -- eg. 9 1! 3 x 3 ...
The tokens are split by more than one space -- eg 9 3
You should be able to tell by the text of the Number Format Exception. For example, in the case of multiple spaces, you'd get:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
And for non-numbers (eg "a"), you'd get:
Exception in thread "main" java.lang.NumberFormatException: For input string: "a"
There are, of course, numerous possible solutions depending on what you want to do when you run into invalid input (do you ignore it? throw a special exception? try to strip out non-numbers?)
When you know your inputs are separated by whitespace, but don't know how much white-space, you can use a regular expression to target multiple whitespaces in your split command:
str.split("\\s+"); // splits on one or more whitespace including tabs, newlines, etc.
Then, to handle non-digits in your token list, you can add a check in your for-loop:
for(int i = 0; i < tokens.length; i++) {
if(tokens[i].matches("\\d+")) {
list[i] = Integer.parseInt(tokens[i]);
} else {
// Handle error case for non-digit input
}
}
It is likely due to the extra bunch of spaces between the numbers.
For Example,
9 8 7 9 1
^^ ^^
*Note: You have more than one spaces here.
This is how your array will look after splitting,
tokens = {"9", "", "", "", "8", "7", "9", "", "", "", "1"}
Above will throw the NumberFormatException because of extra spaces.
You can try trimming the contents again,
int i = 0;
for (String token : tokens){
token = token.trim();
if (!"".equals(token)) {
list[i++] = Integer.parseInt(token);
}
}
Please modify your code to this :
public class Example {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the size of the array : ");
int n = sc.nextInt();
sc.nextLine();
int[] list = new int[n];
System.out.println("Enter a string : ");
/** This regex will work for string having more than one space. */
String trimmedToken = sc.nextLine().replaceAll("\\s+", " ");
String[] tokens = trimmedToken.split(" ");
for (int i = 0; i < tokens.length; i++) {
list[i] = Integer.parseInt(tokens[i]);
System.out.println(list[i]);
}
sc.close();
}
}
Console Input :
Enter the size of the array :
5
Enter a string :
1 2 3 4 5
Output :
1
2
3
4
5
Chandu is a bad student. Once his teacher asked him to print the reverse of a given string. He took three hours to solve it. The teacher got agitated at Chandu and asked you the same question. Can you solve it?
Input
The first line contains an integer T, denoting the number of test cases.
Each test case contains a string S, comprising of only lower case letters.
Output
For each test case, print the reverse of the string S.
Constraints
1 <= T <= 10
1 <= |S| <= 30
Input Sample Output(Plaintext Link)
2
ab ba
aba aba
Time Limit
1 sec(s) for each input file.
Memory Limit
256 MB
Source Limit
1024 KB
MyApproach1
MyApproach2
To reverse a string I used XOR logic to reverse the string.
#Edit
public static void main(String args[] ) throws Exception
{
Scanner sc = new Scanner(System.in);
int T = sc.nextInt();
for (int i = 1; i <= T; ++i)
{
String input = sc.next();
int len = input.length();
StringBuilder input1 = new StringBuilder(len);
int end = input.length()-1;
int start = 0;
while (start<end)
{
input1.setCharAt(start,input.charAt(start)^input.charAt(end));
input1.setCharAt(end,input.charAt(end)^input.charAt(start));
input1.setCharAt(start,input.charAt(start)^input.charAt(end));
++start;
--end;
}
System.out.println(input1.toString());
}
}
I am still getting the following error.
How do I correct this?
For approach 1, all you need to do is remove the call to sc.nextLine() and everything will be fine. That's because each line contains a "token" i.e. a word, delimited by whitespace. That's what sc.next() will return. No need to call nextLine() after that.
For your approach 2, you should carefully read the API documentation of StringBuilder. This shows you how to create a String from a StringBuilder, and vice versa. (Whenever I write Java code, I have a browser window with the API documentation for quick reference next to my editor window. It's very useful.)
Edit (after the latest edit to the question):
There is a compilation problem and a runtime problem. First, the XOR operator produces a result of type int, even if its operands are char. So you should put your expression in parentheses and cast it to char. Once you've done that, you'll get a runtime error because you are trying to index an element of a StringBuilder which does not yet exist. When you created the StringBuilder like this:
StringBuilder input1=new StringBuilder(len);
len is the initial capacity. The value of the StringBuilder instance is initially "". You then call setCharAt() but the current size of the StringBuilder is 0, so you get an index-out-of-bounds exception. You need to initialise the StringBuilder with the string itself:
StringBuilder input1=new StringBuilder(input);
Now you won't get an exception, but you'll get the wrong answer. That's because of a problem with your XOR logic.
After
sc.nextInt();
write
sc.nextLine();
before starting first loop.
For the two lines of your code
String s1 = sc.next();
sc.nextLine();
write just
String s1 = sc.nextLine();
The next() function gives you characters before a space while next line gives you whole line.
It'll work Fine.
I want to save multiple strings in one. Thing is, I don't know how many strings it may be.
I'm creating a program that reads calories from a text file and stores them in corresponding arrays.
Here are parts of the text:
Description of food Fat Food Energy Carbohydrate Protein Cholesterol Weight Saturated Fat
(Grams) (calories) (Grams) (Grams) (Milligrams) (Grams) (Grams)
APPLES, RAW, PEELED, SLICED 1 CUP 0 65 16 0 0 110 0.1
APPLES, RAW, UNPEELED,2 PER LB1 APPLE 1 125 32 0 0 212 0.1
APPLES, RAW, UNPEELED,3 PER LB1 APPLE 0 80 21 0 0 138 0.1
APRICOT NECTAR, NO ADDED VIT C1 CUP 0 140 36 1 0 251 0
Now for the food name, I have an array foodName. I will read the whole string until I reach an int which is the amount.
Here is what I've done so far:
Scanner input = new Scanner("Calories.txt");
while (input.hasNext()) {
String[] words = input.next().split(" ");
int lastI;
for (int i=0; i < words.length; i++) {
if (isNumeric(words[i])) {
lastI = i;
for(int j=lastI; j>=0; j++){
//What should I put here?
}
}
}
}
public static boolean isNumeric(String str) {
try {
double d = Double.parseDouble(str);
} catch (NumberFormatException nfe) {
return false;
}
return true;
}
for the inner most for loop, I kept track of the last index so I could start from it and go backwards.
Problem 1: If I go backwards in the second line, I will copy both lines.
Problem 2: How to save all the strings of the name in one index of foodName?
All help is appreciated :)
What you are looking for in Java is called a StringBuilder. You can use this essentially like a string and keep appending onto it.
File file = new File("output.txt");
Scanner input = new Scanner(file);
StringBuilder sb = new StringBuilder();
while (input.hasNextLine()) {
String[] words = input.nextLine().split(" ");
for (int i = 0; i < words.length; i++) {
if (isNumeric(words[i])) {
break;
}
sb.append(words[i] + " ");
}
System.out.println(sb);
sb = new StringBuilder();
}
input.close();
What this does is read the file line by line, creating an array of strings splitting the line on " ". Then, it iterates over each of the strings in the array and checks if it is a number, if it is, it will break the current loop and move onto the next line.
I had the StringBuilder print after each line, and then reset, you should replace this with whatever functionality that you want.
A couples suggestions also for you:
Use a CSV file. Separate everything with commas instead of spaces, it makes parsing extremely easy.
Use regex to check if the string is a number instead of catching exceptions, it is more elegant.
The output of this comes out a little funny because of how you formatted your file. You are parsing on " ", but you added a bunch of extra " " characters in the file to make the format look nice. This messes up your parsing very badly. BUT, this method will parse for you correctly when you fix the format of your flat file.
Output from this was: (note that each line is a separate string. You can see how the file formatting messed up the output)
Description of food Fat Food Energy Carbohydrate Protein Cholesterol Weight Saturated Fat
(Grams) (calories) (Grams) (Grams) (Milligrams) (Grams) (Grams)
APPLES, RAW, PEELED, SLICED
APPLES, RAW, UNPEELED,2 PER LB1 APPLE
APPLES, RAW, UNPEELED,3 PER LB1 APPLE
APRICOT NECTAR, NO ADDED VIT C1 CUP
I have a program that will read a text file starting on line number 29. If the line contains the words "n.a" or "Total" the program will skip those lines.
The program will get the elements [2] and [6] from the array.
I need to get element [6] of the array and print it underneath its corresponding value.
Element[2] of the array is where all the analytes are and element[6] contains the amount of each analyte.
The files that the program will read look like this:
12 9-62-1
Sample Name: 9-62-1 Injection Volume: 25.0
Vial Number: 37 Channel: ECD_1
Sample Type: unknown Wavelength: n.a.
Control Program: Anions Run Bandwidth: n.a.
Quantif. Method: Anions Method Dilution Factor: 1.0000
Recording Time: 10/2/2013 19:55 Sample Weight: 1.0000
Run Time (min): 14.00 Sample Amount: 1.0000
No. Ret.Time Peak Name Height Area Rel.Area Amount Type
min µS µS*min % mG/L
1 2.99 Fluoride 7.341 1.989 0.87 10.458 BMB
2 3.88 Chloride 425.633 108.551 47.72 671.120 BMb
3 4.54 Nitrite 397.537 115.237 50.66 403.430 bMB
4 5.39 n.a. 0.470 0.140 0.06 n.a. BMB
5 11.22 Sulfate 4.232 1.564 0.69 13.064 BMB
Total: 835.213 227.482 100.00 1098.073
The program needs to read that type of files and stores the element[6] of the array under a heading in a separate file in a folder. That file will have a heading like this:
Fluoride,Chloride,Nitrite,Sulfate,
The amount of fluoride should go under fluoride, the amount of chloride should go under chloride and so on and if there isn`t Nitrite or any other analyte it should put a zero for each analyte.
I just need to know how to match that and then I know I have to make write to the file which I will do later, but for know I need help matching.
The final output should looe like this.
The first line will be written in the textfile and then the second line will be values that will be match under its corresponding analyte like this:
Sample#,Date,Time,Fluoride,Chloride,Nitrite,Sulfate,9-62-1,10/2/2013,19:55,10.458,671.120,403.430,13.064,
Also again if an analyte isnt present on the file or it is null it should put a 0.
Here is my code:
//Get the sample#, Date and time.
String line2;
while ((line2 = br2.readLine()) != null) {
if (--linesToSkip2 > 0) {
continue;
}
if (line2.isEmpty() || line2.trim().equals("") || line2.trim().equals("\n")) {
continue;
}
if (line2.contains("n.a.")) {
continue;
}
if (line2.contains("Total")) {
continue;
}
String[] values2 = line2.split("\t");
String v = values2[2];//Stored element 2 in a string.
String v2 = values2[6];//Stored element 6 in a string.
String analytes = "Fluoride,Chloride,Nitrite,Sulfate";//Stored the analytes into an array.
if (analytes.contains(v)) {
System.out.println(v2);
}
int index2 = 0;
for (String value2 : values2) {
/*System.out.println("values[" + index + "] = " + value);*/
index2++;
}
System.out.print(values2[6] + "\b,");
/*System.out.println(values[6]+"\b,");*/
br.close();
}
Thanks in advance!
So if i understand your task right and every element is in new line.
Where is a lot of ways how to solve this, but with your code simpliest way to solve it in my opinion would be with StringBuffer.
//In your code i saw you have to arrays one of them with element name
//other with element code or smth
StringBuffer firstLine = new StringBuffer();
StringBuffer secondLine = new StringBuffer();
public static void printResult(String[] Name, String[] Code){
//First we gona make first line
//Here we are adding data before Names
firstLine.append("Stuff before Names");
for(int i =0;i<name.length;i++){
//Here we gona add all names in the list which is good
//Dont forget spaces
firstLine.append(name[i]+ " ");
}
//And same goes for second line just change loop array and data added before loop.
//And in the end this should print out your result
System.out.println(firstLine+"\n" + secondLine);
}
Call this method after all file reading is done.
Hope it helps!