tags:

views:

798

answers:

9

I'm trying to read in a multi line string then split it then print it .. here is the string :

1T1b5T!1T2b1T1b2T!1T1b1T2b2T!1T3b1T1b1T!3T3b1T!1T3b1T1b1T!5T1*1T

11X21b1X
4X1b1X

When I split the string with ! I get this without the last line string :

1T1b5T
1T1b5T1T2b1T1b2T
1T2b1T1b2T1T1b1T2b2T
1T1b1T2b2T1T3b1T1b1T
1T3b1T1b1T3T3b1T
3T3b1T1T3b1T1b1T
1T3b1T1b1T5T1*1T
5T1*1T11X21b1X
11X21b1X

Here is my code :

import java.io.BufferedInputStream;
import java.util.Scanner;

public class Main {

    public static void main(String args[]) {
        Scanner stdin = new Scanner(new BufferedInputStream(System.in));
        while (stdin.hasNext()) {
            for (String line : stdin.next().split("!")) {
                System.out.println(line);

                for (int i = 0; i < line.length(); i++) {
                    System.out.print(line.charAt(i));
                }
            }
        }
    }

}

Where did I make the mistake, why is not reading in the last line? After I read in all lines properly I should go trough each line if I encounter number I should print the next char the n times the number I just read, but that is long way ahead first I need help with this. Thank you

UPDATE :

Here is how the output should look like :

1T1b5T
1T2b1T1b2T
1T1b1T2b2T
1T3b1T1b1T
3T3b1T
1T3b1T1b1T
5T1*1T

11X21b1X
4X1b1X

Here is a solution in C(my friend solved it not me), but I'd stil wanted to do it in JAVA :

#include <stdio.h>

int main (void)
{
    char row[134];
    for (;fgets (row,134,stdin)!=NULL;)
    {
        int i,j=0;
        for (i=0;row[i]!='\0';i++)
        {
            if (row[i]<='9'&&row[i]>='1')
                j+=(row[i]-'0');
            else if ((row[i]<='Z'&&row[i]>='A')||row[i]=='*')
                for (;j;j--)
                    printf ("%c",row[i]);
            else if (row[i]=='b')
                for (;j;j--)
                    printf (" ");
            else if (row[i]=='!'||row[i]=='\n')
                printf ("\n");
        }
    }
    return 0;
} 
+9  A: 

Maybe because you didn't hit enter after the last input line?

Update: tested it here and confirmed it. You need to hit enter after the last input line. Only this way the while (stdin.hasNext()) will return true and proceed with the line.

BalusC
@BalusC When I hit the `Enter` the last line `4X1b1X` two times in the next two rows.
Gandalf StormCrow
Groovy key stroke markup! I forgot all about `<kbd>`!
Adam Paynter
@Gandalf: your code indeed duplicates **all** splitted parts. Is that another problem? If so, then just get rid of the whole second `for`-loop. It does exactly like `System.out.print(line);` (thus without a newline), but you already have a `System.out.println(line);`.
BalusC
@BalusC It kind of work and not, I updated my question.
Gandalf StormCrow
Etaion already answered it. In the future, please ask better questions. Your initial question namely insinuates that the duplicates are expected: it was too obvious from the coding and the result, but you didn't say any word about it. I would otherwise have answered/remarked about that as well.
BalusC
@BalusC sorry for not formatting question properly, I think its clear now, there is even solution in C, how can I do this in JAVA?
Gandalf StormCrow
@BalusC still waiting for that answer of yours :D
Gandalf StormCrow
Etaion already answered the question.
BalusC
@BalusC no he didn't I'm getting this http://pastebin.com/CsFVtMqw result instead of http://pastebin.com/b4H242Mb
Gandalf StormCrow
I got the right result with `stdin.useDelimiter("(!|\\r?\\n|\\r)")`.
BalusC
@BalusC it doesn't work for me
Gandalf StormCrow
Sorry, I retested it again, it just works. I copypasted Etaoin's code example, updated the `useDelimiter()` accordingly, ran it in Eclipse, copypasted your entire string in the console, it outputs just fine. I even replaced `System.in` by `FileInputStream` to read it from file instead, it works as fine. Your problem lies somewhere else.
BalusC
+15  A: 

You seem to be doing more work than necessary. The Scanner can use a custom delimiter; in your case, you want it to break up the input on either a newline or a bang, so:

Scanner stdin = new Scanner(System.in);
stdin.useDelimiter("[!\\s]*"); // Break on any combination of whitespace characters and !s

while (stdin.hasNext()) {        // While there's a next token,
    String line = stdin.next();  // read it in
    System.out.println(line);    // and print it out.
}

You're doing something wonky with your print statements -- the code above assumes that all you want to do is print out each line. You seem to be trying to do it twice, in your code, so if I've misinterpreted your intent, modify appropriately.

Edit per your UPDATE: Okay, so you want to allow empty tokens and pass them through. That's easy: just modify the delimiter so that it only matches one character, like so:

stdin.useDelimiter("(!|\\r?\\n|\\r)")

With no asterisk, we'll match only one thing at a time: a bang, or a newline (of any of the three flavors found on different operating systems).

Etaoin
I think `stdin.setDelimiter("[!\\s]*");` should actually be `stdin.useDelimiter("[!\\s]*");`
c0mrade
Whoops! You're right. Fixed, thanks.
Etaoin
@Etaoin I fixed that eclipse suggestted that. I updated my question. thank you
Gandalf StormCrow
+1 For using Scanner delimiter functionality.
Andrei Ciobanu
@Gandalf: Revised my answer per your revision of the question.
Etaoin
@Etaoin here http://pastebin.com/KZifpDQX my output now looks like this which is very strange skipping so many lines
Gandalf StormCrow
My mistake; revised again.
Etaoin
@Etaoin you are very close to solution, here is how my output looks now http://pastebin.com/CsFVtMqw .. just last 2 lines should be seperated by line they should be like this http://pastebin.com/b4H242Mb
Gandalf StormCrow
A: 

It works for me, regardless of whether there is a trailing newline or not. Of course the definition of "works" is unclear, except that you expected to see the lastline "4X1b1X", I assume. I did see it.

C:\>java Main < test.txt
1T1b5T
1T1b5T1T2b1T1b2T
1T2b1T1b2T1T1b1T2b2T
1T1b1T2b2T1T3b1T1b1T
1T3b1T1b1T3T3b1T
3T3b1T1T3b1T1b1T
1T3b1T1b1T5T1*1T
5T1*1T11X21b1X
11X21b1X4X1b1X
4X1b1X
mrjoltcola
@mrjoltcola yes it "works" except that it doesn't look like the output I want to achieve, I updated my question. tnx
Gandalf StormCrow
+1  A: 
public static List<String> ppp(final String source) {
    final ArrayList<String> result = new ArrayList<String>();
    final Scanner scan = new Scanner(source);
    scan.useDelimiter("!");
    while (scan.hasNext()) {
    result.add(scan.next());
    }
    return result;
}

private static void printout(final List<String> someArgs) {
    final Iterator<String> i = someArgs.iterator();
    while (i.hasNext()) {
    System.out.println(i.next());
    }
} 
public static void main(final String[] args) throws IOException {
    final String lineSeparator = System.getProperty("line.separator");
    final String test = "1T1b5T!1T2b1T1b2T!1T1b1T2b2T!1T3b1T1b1T!3T3b1T!1T3b1T1b1T!5T1*1T"
            + lineSeparator + lineSeparator + "11X21b1X" + lineSeparator + "4X1b1X" + lineSeparator;
    System.out.println("Source: ");
    System.out.println(test);
    System.out.println("Result as List: ");
    System.out.println(ppp(test));
    System.out.println("Result in lines:");
    printout(ppp(test));}

The String test is a multiline String with LineSeparators in it. The method ppp returns an array with elements separated by "!". The method prinout just print the elements of the array to stdout in separat lines.

The whole main() generates the following output:

Source: 
1T1b5T!1T2b1T1b2T!1T1b1T2b2T!1T3b1T1b1T!3T3b1T!1T3b1T1b1T!5T1*1T

11X21b1X
4X1b1X

Result as List: 
[1T1b5T, 1T2b1T1b2T, 1T1b1T2b2T, 1T3b1T1b1T, 3T3b1T, 1T3b1T1b1T, 5T1*1T

11X21b1X
4X1b1X
]
Result in lines:
1T1b5T
1T2b1T1b2T
1T1b1T2b2T
1T3b1T1b1T
3T3b1T
1T3b1T1b1T
5T1*1T

11X21b1X
4X1b1X


Michael Konietzka
A: 

I don't know what you are doing exacly. You are reading and printing on the same time... (So I splitted input and output)

Personnaly, I HATE the Scanner class. I always use a BufferedReader.

So, I store first the input in a list. So the user can give the input without the agressif output. When you have the input, you can print it simply.

I did it like following and it works correct:

public static void main(String[] args) throws IOException {
    List<String> lines = new ArrayList<String>();
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    System.out.print("How many lines count the input? ");
    int count = Integer.parseInt(reader.readLine());
    for (int i = 0; i < count; i++)
    {
        lines.add(reader.readLine());
    }
    System.out.println("\nNow comes the output:");
    for (int i = 0; i < count; i++)
    {
        String line = lines.get(i);
        String[] splitted = line.split("!");
        for (String string : splitted) {
            System.out.println(string);
        }
    }
}

This is how I ran it:

How many lines count the input? 4
1T1b5T!1T2b1T1b2T!1T1b1T2b2T!1T3b1T1b1T!3T3b1T!1T3b1T1b1T!5T1*1T

11X21b1X
4X1b1X


Now comes the output:
1T1b5T
1T2b1T1b2T
1T1b1T2b2T
1T3b1T1b1T
3T3b1T
1T3b1T1b1T
5T1*1T

11X21b1X
4X1b1X
BUILD SUCCESSFUL (total time: 10 seconds)
Martijn Courteaux
+2  A: 

From the Java SE 6 documentation for java.util.Scanner.next():

Finds and returns the next complete token from this scanner. A complete token is preceded and followed by input that matches the delimiter pattern. This method may block while waiting for input to scan, even if a previous invocation of hasNext() returned true.

I suspect that what happened in your Java code is that the app is blocking waiting for a newline character after the last line.

MSN
+2  A: 

I wrote already an answer, that was a solution. But you are asking what you are doing wrong.

  1. You are using Eclipse. This is not bad, but if I try to do this in NetBeans the code works a litle bit else because of you are reading and writing in the same loop. So the when I do copy-paste the input in eclipse, it works as you want. But if I copy-paste line by line, it becomes one big mess. So you have to split the read and the write process.
  2. What you are doing wrong is that you first println the result and then (Why? I don't know. I think you also don't know...) do a print of each char in the result. So the result is that you have only one good line and the others are started by the previous line. So:

    [line 1]: foo
    [line 2]: foobar
    [line 3]: barbaz
    [line 4]: bazbam
    

    You see? So begin with deleting your inner loop that prints each character.
    When you did this: your output looks like this:

    1T1b5T
    1T2b1T1b2T
    1T1b1T2b2T
    1T3b1T1b1T
    3T3b1T
    1T3b1T1b1T
    5T1*1T
    11X21b1X
    4X1b1X
    

    So this is the reason why you thought the foreach loop was the problem. If you look at the end of each outputline (your wrong output: posted in the question), you can see, it was correct.

  3. Then you want in the output a blank line if there was one in the input. But like I wrote in my other answer:

    I hate Scanner

    Scanner does not really read the next line, but the next word. So you have to change it to stdin.nextLine(); Now it works!


Finally, this is the code you need:

Scanner stdin = new Scanner(new BufferedInputStream(System.in));
while (stdin.hasNext()) {
    String line = stdin.nextLine();
    for (String part : line.split("!")) {
        System.out.println(part);
    }
}
Martijn Courteaux
A: 

Scanner is better in terms of simplicity. It's worse in terms of fine-grained control. You should be using some other java.io.Reader to gain the control you are looking for.

Pointing to http://stackoverflow.com/questions/1737816/how-to-catch-blank-input-with-scanner-class-in-java

ring bearer
A: 

The problem is the scanner. It seems that all you want to do is read lines. For that you don't need a scanner (as it will not return the last part which is not delimited). Simply use the buffered reader's readLine:

import java.io.BufferedInputStream;
import java.util.Scanner;

public class Main {

    public static void main(String args[]) {
        BufferedInputStream stdin = new Scanner(new BufferedInputStream(System.in));
        String line;
        while ((line=stdin.nextLine)!=null) {
            for (String token : line.split("!")) {
                System.out.println(token);
            }
        }
    }

}
Paul de Vrieze