I'm writing a class with a method that takes a summary string and breaks it down into a maximum number of lines (maxLines Parameter) and maximum number of characters per line (width parameter). All lines except the first line should be indented (they should start with a space character), but the second character in an indented line should not be another space (so that second space must not be included). The program should still work if you change the maxLine parameter r width.
Also, the code should check whether some special characters are in the String, like:
\' , \" , \\ , \t , \b , \r , \f , \n
How can I inspect is many spaces in String like below? If there are many spaces in the String, I want to trim them, but I don't know how to. (These underscores represent spaces.)
"9:00 John_____________________________Doe until 10 30 at Office"
9:00 Jo
_hn____
_______
_____Do
With my code, I get this result:
9:00 Jo
_hn Doe
_until 1
_0 30 at
But I want THIS this output:
9:00 Jo
_hn Doe
_until_
_10 30_
Here is my code:
public static void main(String[] args) {
String str = "9:00 John Doe until 10 30 at Office";
int width = 7;
int maxLine = 4;
List<String> lisT = new LinkedList<>(getParts(str, width, maxLine));
for (String part : lisT) {
System.out.println(part);
}
}
public static List<String> getParts(String str, int width, int maxLine) {
List<String> parts = new LinkedList<>();
int count = 0;
int len = str.length();
String indent = "";
for (int i = 0; i < len; i += width) {
parts.add(indent + str.substring(i, Math.min(len, i + width)).trim());
count++;
indent = " ";
if (count == maxLine)
break;
}
return parts;
}
So this is what you want? I really hope you don't have to implement this in something because I had to mangle this to make it work. Hopefully this is homework
public static void main(String[] args) {
String str = "9:00 John Doe until 10 30 at Office";
int width = 7;
int maxLine = 4;
List<String> lisT = new LinkedList<>(getParts(str, width, maxLine));
for (String part : lisT) {
System.out.println(part);
}
}
public static List<String> getParts(String str, int width, int maxLine){
List<String> parts = new LinkedList<>();
int endedAt = 0;
boolean firstLine = true;
boolean secondLine = true;
String indent = " ";
for (int i = 0; i < maxLine; i++) {
if(endedAt<=str.length()) {
String holder;
if(firstLine) {
holder = str.substring(endedAt, endedAt + width);
firstLine = false;
}
else {
if(secondLine){
width = width -1;
secondLine = false;
}
holder = indent + str.substring(endedAt, endedAt + width).trim();
}
parts.add(holder);
endedAt = endedAt + width;
}
}
return parts;
}
The output is
9:00 Jo
hn Doe
until
10 30
I think your rows might be too long because your width = 7 includes the indent space, so your rows have a width of 8 instead of 7. I would try replacing for (int i = 0; i < len; i += width) {... with for (int i = 1; i < len; i += width - 1) {... and add a special statement right before the for loop for the 0th row, since you do not want to indent the 0th row. Something like this:
parts.add(str.substring(0, Math.min(len, i + width)).trim());
for(...){...}
Let me know whether that seems to be the problem. If not, I can take another look. To answer your other questions:
To remove more than one space in the middle of a string, use this to replace all whitespace with exactly one space:
String result = replaceAll("\\s","");
You can remove the special characters with a regex like this:
String result = str.replaceAll("[\'\"\\\t\b\r\f\n]","");
Related
I have a string of a random address like
String s = "H.N.-13/1443 laal street near bharath dental lab near thana qutubsher near modern bakery saharanpur uttar pradesh 247001";
I want to split it into array of string with two conditions:
each element of that array of string is of length less than or equal to 20
No awkward ending of an element of array of string
For example, splitting every 20 characters would produce:
"H.N.-13/1443 laal st"
"reet near bharath de"
"ntal lab near thana"
"qutubsher near moder"
"n bakery saharanpur"
but the correct output would be:
"H.N.-13/1443 laal"
"street near bharath"
"dental lab near"
"thana qutubsher near"
"modern bakery"
"saharanpur"
Notice how each element in string array is less than or equal to 20.
The above is my output for this code:
static String[] split(String s,int max){
int total_lines = s.length () / 24;
if (s.length () % 24 != 0) {
total_lines++;
}
String[] ans = new String[total_lines];
int count = 0;
int j = 0;
for (int i = 0; i < total_lines; i++) {
for (j = 0; j < 20; j++) {
if (ans[count] == null) {
ans[count] = "";
}
if (count > 0) {
if ((20 * count) + j < s.length()) {
ans[count] += s.charAt (20 * count + j);
} else {
break;
}
} else {
ans[count] += s.charAt (j);
}
}
String a = "";
a += ans[count].charAt (0);
if (a.equals (" ")) {
ans[i] = ans[i].substring (0, 0) + "" + ans[i].substring (1);
}
System.out.println (ans[i]);
count++;
}
return ans;
}
public static void main (String[]args) {
String add = "H.N.-13/1663 laal street near bharath dental lab near thana qutubsher near modern bakery";
String city = "saharanpur";
String state = "uttar pradesh";
String zip = "247001";
String s = add + " " + city + " " + state + " " + zip;
String[]ans = split (s);
}
Find all occurrences of up to 20 chars starting with a non-space and ending with a word boundary, and collect them to a List:
List<String> parts = Pattern.compile("\\S.{1,19}\\b").matcher(s)
.results()
.map(MatchResult::group)
.collect(Collectors.toList());
See live demo.
The code is not very clear, but at first glance it seems you are building character by character that is why you are getting the output you see. Instead you go word by word if you want to retain a word and overflow it to next String if necessary. A more promising code would be:
static String[] splitString(String s, int max) {
String[] words = s.split("\s+");
List<String> out = new ArrayList<>();
int numWords = words.length;
int i = 0;
while (i <numWords) {
int len = 0;
StringBuilder sb = new StringBuilder();
while (i < numWords && len < max) {
int wordLength = words[i].length();
len += (i == numWords-1 ? wordLength : wordLength + 1);//1 for space
if (len <= max) {
sb.append(words[i]+ " ");
i++;
}
}
out.add(sb.toString().trim());
}
return out.toArray(new String[] {});
}
Note: It works on your example input, but you may need to tweak it so it works for cases like a long word containing more than 20 characters, etc.
Hello I try to print in an array of Strings
In the following way:
Input: big = "12xy34", small = "xy" output: "** xy **"
Input: big = "" 12xt34 "", small = "xy" output: "******"
Input: big = "12xy34", small = "1" output: "1 *****"
Input: big = "12xy34xyabcxy", small = "xy" output: "** xy ** xy *** xy"
Input: big = "78abcd78cd", small = "78" output: "78 **** 78 **"
What I need to write a condition to receive as up?
public static String stars(String big, String small) {
//throw new RuntimeException("not implemented yet ");
char[] arr = big.toCharArray();
for (int i = 0; i < arr.length; i++) {
if (big.contains(small) ) {
arr[i] = '*';
}
}
String a = Arrays.toString(arr);
return big+""+a;
}
Algorithm:
Convert big and small String's to char[] array's bigC and smallC respectively
Iterate over each character of big String
At every index during iteration, identify whether there is a sub-string possible beginning current character
If there is a sub-string possibility, advance the index in big String iteration by length of small String
Otherwise, replace the character by *
Code:
public class StringRetainer {
public static void main(String args[]) {
String big[] = {"12xy34", "12xt34", "12xy34", "12xy34xyabcxy", "78abcd78cd"};
String small[] = {"xy", "xy", "1", "xy", "78"};
for(int i = 0; i < big.length & i < small.length; i++) {
System.out.println("Input: big = \"" + big[i] + "\", small = \"" + small[i] + "\" output : \"" + stars(big[i], small[i]) + "\"");
}
}
public static String stars(String big, String small) {
//String to char[] array conversions
char[] bigC = big.toCharArray();
char[] smallC = small.toCharArray();
//iterate through every character of big String and selectively replace
for(int i = 0; i < bigC.length; i++) {
//flag to determine whether small String occurs in big String
boolean possibleSubString = true;
int j = 0;
//iterate through every character of small String to determine
//the possibility of character replacement
for(; j < smallC.length && (i+j) < bigC.length; j++) {
//if there is a mismatch of at least one character in big String
if(bigC[i+j] != smallC[j]) {
//set the flag indicating sub string is not possible and break
possibleSubString = false;
break;
}
}
//if small String is part of big String,
//advance the loop index with length of small String
//replace with '*' otherwise
if(possibleSubString)
i = i+j-1;
else
bigC[i] = '*';
}
big = String.copyValueOf(bigC);
return big;
}
}
Note:
This is one possible solution (legacy way of doing)
Looks like there is no straight forward way of making this happen using built-in String/StringBuffer/StringBuilder methods
I have a test for a class that displays a word randomly chosen from an array.
I'm trying to display the word with several chars hidden
I have taken the string, then converted it to an array of chars, but I'm confused as to where to go from here.
import java.util.Scanner;
public class wordTest {
public static void main (String args[])
{
Scanner scanner = new Scanner(System.in);
String readString = scanner.nextLine();
char[] stringArray;
String [] gamewords = { "dog", "cat", "coffee", "tag", "godzilla", "gamera", "lightning", "flash", "spoon", "steak", "moonshine", "whiskey", "tango", "foxtrot", "ganymede"
, "saturn", "enterprise", "reliant", "defiant", "doom", "galapagos", "jidai", "sengoku"};
arrayWords wl = new arrayWords();
// Words w = new Words();
Word n = new Word();
int a = 0;
int b = gamewords.length;
RandNum rand = new RandNum(a,b);
n.setWord(gamewords[rand.nextRandomIntegerInRange()]);
stringArray = n.getWord().toCharArray();
int blank1 = 1;
int blank2 = 4;
RandNum blanks = new RandNum(blank1,blank2);
n.setWord(gamewords[rand.nextRandomIntegerInRange()]);
do{
int i = 0;
//scanner.nextLine();
for( i = 0; i < stringArray.length; i++){
for( i = 0 ; i < blanks.nextRandomIntegerInRange() ; i++ ){
stringArray[i] = '*';
}
System.out.println(stringArray[i]);
}
}while(scanner.nextLine().equals(""));
}
}
Since you haven't given clear definition on what you want to do, here I assume for every string, you are randomly masking 2 characters, in pseudo code, it looks like:
if inputString.length < 2 {
mask all character
} else {
loop until 2 character masked {
r = random from 0 to inputString.length-1
if (inputString[r] is not masked) {
set inputString[r] to mask character
}
}
}
some hints:
to make "inputString" modifiable, make use of a StringBuilder
Way to check if certain position is masked, you can either simply check if the character in the string == mask character, or you can use a Set to keep all masked position
In order to find out number of position masked, you can keep a counter, or simply use the size of the Set in 2 if you choose to use a Set.
Okay, so I think I've found the solution:
for (int i = 0; i < stringArray.length ; i++) {
stringArray[blanks.nextRandomIntegerInRange()] = '_';
System.out.print(stringArray[i] + " " );
}
I am trying to split number but don't know how to do this.
I referred this link.
https://stackoverflow.com/a/12297231/1395259
Suppose I have a number 12345678.
using above link I am splitting by 3 places.So the output becomes 123 456 78.
But I want it as 12 345 678 And I want to take the string that was split in the form 12.345.678 .
Can anybody help me please??
java.text package provides all reasonable options for formatting numbers
DecimalFormat f = new DecimalFormat("#,###");
DecimalFormatSymbols fs = f.getDecimalFormatSymbols();
fs.setGroupingSeparator('.');
f.setDecimalFormatSymbols(fs);
String s = f.format(12345678);
System.out.println(s);
output
12.345.678
using DecimalFormat directly is very flexible, but typically we can use a shorter version
String s = NumberFormat.getNumberInstance(Locale.GERMAN).format(12345678);
which produces the same string
12.345.678
Different countries have different rules for formatting numbers (and dates). Usually we want our programs to be internationalized / localized and use default locale version
NumberFormat.getNumberInstance().format(number);
One lazy way is to reverse the string, apply above method, and then reverse it again.
You can use StringBuffer's Reverse Function, as shown in Reverse each individual word of "Hello World" string with Java
12345678
87654321
876 543 21
12 345 678
I am assuming of course that you want to split by 3s and the group with <3 digits left appears in the start rather than the end as in the method you link.
The not so lazy way would be to use string length to adapt the method you link to start with length%3 characters.
Using the solution from your link i would rephrase that as following (TESTED!):
public String[] splitStringEvery(String s, int interval) {
int arrayLength = (int) Math.ceil(((s.length() / (double)interval)));
String[] result = new String[arrayLength];
int j = s.length();
int lastIndex = result.length;
for (int i = lastIndex - 1; i > 0; i--) {
result[i] = s.substring(j - interval, j);
j -= interval;
} //Add the last bit
result[0] = s.substring(0, j);
return result;
}
Here is a method that splits an int value and returns an String in the specified format:
public static String split( int n ) {
String result = "", s = Integer.toString( n );
while ( s.length() > 3 ) {
result = s.substring( s.length() -3, s.length() ) + ((result.length() > 0)? "." + result : "" );
s = s.substring( 0, s.length() -3 );
}
return s + "." + result;
}
Input:
12345678
Output:
12.345.678
If it's a String, use StringBuilder or StringBuffer. Here's the code:
public class SplitNumber {
public static void main(String[] args){
int number = 12345678;
String numberStrBefore = Integer.toString(number);
StringBuffer numberStrAfter = new StringBuffer();
numberStrAfter.append(numberStrBefore.charAt(0));
numberStrAfter.append(numberStrBefore.charAt(1));
numberStrAfter.append('.');
numberStrAfter.append(numberStrBefore.charAt(2));
numberStrAfter.append(numberStrBefore.charAt(3));
numberStrAfter.append(numberStrBefore.charAt(4));
numberStrAfter.append('.');
numberStrAfter.append(numberStrBefore.charAt(5));
numberStrAfter.append(numberStrBefore.charAt(6));
numberStrAfter.append(numberStrBefore.charAt(7));
System.out.println("Number Before: " + numberStrBefore);
System.out.println("Number After: " + numberStrAfter.toString());
}
}
And here is the same thing with a method:
public class SplitNumber {
public static void main(String[] args){
int number = 12345678;
int[] split = {2,3,3}; //How to split the number
String numberStrAfter = insertDots(number, split);
System.out.println("Number Before: " + number);
System.out.println("Number After: " + numberStrAfter);
}
public static String insertDots(int number, int[] split){
StringBuffer numberStrAfter = new StringBuffer();
String numberStr = Integer.toString(number);
int currentIndex = 0;
for(int i = 0; i < split.length; i++){
for(int j = 0; j < split[i]; j++){
numberStrAfter.append(numberStr.charAt(currentIndex));
currentIndex++;
}
numberStrAfter.append('.');
}
numberStrAfter.deleteCharAt(numberStrAfter.length()-1); //Removing last "."
return numberStrAfter.toString();
}
}
This version, with the method, allows you to split any number into any format that you want, simply change the "split" variable into the format that you want to split the string into. (Ex: Splitting 12345678 into: 1.1234.5.67.8 would mean that "split" must be set to {1,4,1,2,1}).
well basically I have a line thats has a finial in of 40,
if a add 2 words that are 10 letters each long that leaves me with 20 spaces
thouse 20 spaces should be filled with dots ...... for example
hello................................you
or
stack...........................overflow
now I have the code working fine, I just have no idea on how to please this in a system.out.println so that the result is printed to the console.
I was thinking of using a whileloop to print the dots one at a time, after testing how many number of dots there should be once bother words are entered.
At the moment I have this which clearly doesn't work
{
System.out.println (word1 + ".." + word2);
while (wordlegnth1 + wordlegnth2 < LINELENGTH)
{
System.out.println (word1 + "." + word2);
wordlegnth1++;
}
final int LINE_LENGTH = 40;
String word1 = ...;
String word2 = ...;
StringBuilder sb = new StringBuilder(LINE_LENGTH);
sb.append(word1);
for (int i = 0; i + word1.length() + word2.length() < LINE_LENGTH; i++) {
sb.append(".");
}
sb.append(word2);
System.out.println(sb.toString());
Note: the use of StringBuilder is to avoid performance penalty due to String immutability
/**
* Formats a given string to 40 characters by prefixing it with word1 and
* suffixing it with word2 and using dots in the middle to make length of final
* string = 40.
* If string will not fit in 40 characters, -1 is returned, otherwise 0 is
* returned.
*
* #param word1 the first word
* #param word2 the second word
* #return 0 if string will fit in 40 characters, -1 otherwise
*/
public static int formatString(String word1, String word2) {
final int LINELENGTH = 40;
// determine how many dots we need
int diff = LINELENGTH - (word1.length() + word2.length());
if (diff < 0) {
// it's too big
System.out.println("string is too big to fit");
return -1;
}
// add the dots
StringBuilder dots = new StringBuilder();
for (int i = 0; i < diff; ++i) {
dots.append(".");
}
// build the final result
String result = word1 + dots.toString() + word2;
System.out.println(result);
return 0;
}
public static void main(String[] args) throws Throwable {
formatString("stack", "overflow");
String str = "";
for (int i = 0; i < 21; ++i) {
str += "a";
}
formatString(str, str);
}
Output:
stack...........................overflow
string is too big to fit
Why not start with something like:
int lengthA = word1.length();
int lengthB = word2.length();
int required = LINE_LENGHT - (lengthA + lengthB);
for(int i = 0; i < required; i++)
{
System.out.print(".");
}
It can be improved on (try strings that are very large for example, or use a StringBuilder rather than System.out.print).
add apache's commons-lang to your classpath and use StringUtils.leftPad()
System.out.println(str1 + StringUtils.leftPad(str2, 40 - str1.length(), '.'));
why write a method to do something someone else has already written + tested?