### Text formatting: Format one line of text

• Solving Sub-problem 2: right-adjust one line of text

• Question:

• What would you do if someone as you to "right-adjust" a given line ???

• Recall the requirements:

 The difference in number of spaces between 2 words on a line is at most 1 (one) space

To get a sense of the problem, use a concrete example:

• Here is a line before the right-adjust operation:

 ``` 012345678901234567890123456789 >WE hold these Truths to be ```

Notice there are 4 space between the end of the line and the right-margin of the text.

• Here is a line after the right-adjust operation:

 ``` 012345678901234567890123456789 >WE hold these Truths to be ```

Notice the 4 trailing space are distributed semi-evenly into the gaps in the text.

• Question: How would you right-adjust a line ???

• Sketch of the algorithm:

 ``` S = number of trailing spaces in the line G = number of gaps between the words in the line Distribute S spaces evenly over the G gaps (need refining) ```

• Determining the number of trailing space in the line

• This problem is very easy to solve.

Example:

 ``` 012345678901234567890123456789 >WE hold these Truths to be length of the string "WE hold these Truths to be" = 26 characters ```

• Determine the number of trailing space in the line: line

 ``` S = 30 − line.length(); ```

• Determining the number of gaps in the line

• Note:

 In order to insert extra spaces into the line, we must break up the line into individual words

• We will use the following class in the Java library to do this job:

 ``` java.util.StringTokenizer ```

Check out the Java documentation page of the StringTokenizer class: click here

• Summary of the StringTokenizer class:

• The StringTokenizer class breaks a string into tokens that are separated by spaces

The StringTokenizer class contains methods to count the number of tokens (words) and retrieve the tokens (words)

 StringTokenizer T = StringTokenizer( SomeString ) will initialize a StringTokenizer object T with the words in the string SomeString. T.countTokens() returns the number of words in the StringTokenizer object T. T.nextToken() returns the next word stored inside in the StringTokenizer object T.

• Example usage:

 ``` StringTokenizer T = new StringTokenizer("Hello, Mr. Smith"); int N = T.countTokens(); // Number of token in the string (= 3) String s; for ( int i = 0; i < N; i++ ) { s = T.nextToken(); // Get next token System.out.println( s ); // Print it } Will print: Hello, Mr. Smith ```

• Example Program: (Demo above code)

How to run the program:

 Right click on link and save in a scratch directory To compile:   javac StringTokenizer1.java To run:          java StringTokenizer1

• How to determine the number of gaps in a line using the StringTokenier class:

• The number of gaps in a line of text = the number of tokens (words)   −   1

Example:

 ``` WE hold these Truths to be (6 tokens) ^ ^ ^ ^ ^ 5 gaps (5 = 6 - 1) ```

• Therefore:

 ``` StringTokenizer T = new StringTokenizer( line ); G = T.countTokens() - 1; // G = # gaps in line ```

• Distribute S spaces "evenly" over G gaps

• First consider 2 examples:

• Let's use an analogy to figure out what to do:

• Suppose you have 4 bottles of milk and 3 children

You want to distribute (share) the bottless of milk evenly among the children (without opening any bottle of milk)

How many bottles will each child get ?

• How to share 8 bottles of milk among 3 children ?

• How to share 12 bottles of milk among 3 children ?

• How to share 13 bottles of milk among 3 children ?

• How to share S bottles of milk among 3 children ?

 Every child gets S/3 bottles And then: S%3 of the children get one extra bottle.

• In general: How to share S bottles of milk among G children ?

 Every child gets S/G bottles And then: S%G of the children get one extra bottle.

• Pseudo code: right-justify a line

 ``` NTrailingSpaces = MAXLINELENGTH - line.length() ; // # trailing spaces StringTokenizer T = new StringTokenizer( line ); // Break "line" into tokens NGaps = T.countTokens() - 1; // # gaps between words NSpacesPerGap = NTrailingSpaces / NGaps; NExtra = NTrailingSpaces % NGaps; /* ----------------------------------------------- Construct the right-adjusted line ----------------------------------------------- */ Add 1 + NSpacesPerGap spaces between 2 words in StringTokenizer T Add ONE MORE space to the first NExtra gaps ```

• Refined pseudo code: right-justify a line

 ``` NTrailingSpaces = MAXLINELENGTH - line.length() ; // # trailing spaces StringTokenizer T = new StringTokenizer( line ); // Break "line" into tokens NGaps = T.countTokens() - 1; // # gaps between words NSpacesPerGap = NTrailingSpaces / NGaps; NExtra = NTrailingSpaces % NGaps; /* ----------------------------------------------- Construct the right-adjusted line ----------------------------------------------- */ outputLine = T.nextToken( ); // First word for ( k = 1; k <= NGaps; k++ ) { /* ------------------------------------------- Add 1+NSpacesPerGap spaces to a gap ------------------------------------------- */ for (i = 1; i <= 1+NSpacesPerGap; i++) outputLine = outputLine + " "; /* ------------------------------------------- Add 1 more space to the first NExtra gaps ------------------------------------------- */ if (k <= NExtra) outputLine = outputLine + " "; /* ------------------------------------------- Add the next word... ------------------------------------------- */ outputLine = outputLine + T.nextToken(); } ```

Note:

• There are 2 special cases where we do not need to make adjustment to the input line:

 Case 1: the input line has the no trailing spaces (i.e., the line is already right-adjusted) Case 2: the input line contains only one word on the entire line...

• How to handle these special cases:

 If we detect one of the abovce case, we return the original input as the output.

• The modified right-adjustment algorithm as a Java Method:

 ``` public static String fixLine(String s, int maxLineLength) { int NGaps; int NTrailingSpaces; int NSpacesPerGap; // # spaces to insert in each gap int NExtra; // # gaps that gets ONE extra space String outputLine; // Output string... StringTokenizer T; // Help variables... int i, k; /* ------------------------------------------------- Check if line already fits perfectly.... ------------------------------------------------- */ if ( s.length() == maxLineLength ) return(s); // Already right-justified /* -------------------------------------- Compute: NTrailingSpaces and NGaps -------------------------------------- */ NTrailingSpaces = maxLineLength - s.length(); // # trailing spaces T = new StringTokenizer(s); NGaps = T.countTokens() - 1; // # gaps /* ------------------------------------------------- Check if line has > 1 word.... (Lines with 1 word can't be right-adjusted !) ------------------------------------------------- */ if ( NGaps == 0 ) return( s ); // Can't adjust line, return as is... /* ================== The right adjust line algorithm ============== */ NSpacesPerGap = NTrailingSpaces / NGaps; NExtra = NTrailingSpaces % NGaps; /* ------------------------------------- Construct the right-adjusted line ------------------------------------- */ outputLine = T.nextToken(); // Put first word in output for ( k = 1; k <= NGaps; k++ ) { /* ------------------------------------------- Add 1+NSpacesPerGap spaces to a gap ------------------------------------------- */ for (i = 1; i <= 1+NSpacesPerGap; i++) outputLine = outputLine + " "; /* ------------------------------------------- Add 1 more space to the first NExtra gaps ------------------------------------------- */ if (k <= NExtra) outputLine = outputLine + " "; /* ------------------------------------------- Add the next word... ------------------------------------------- */ outputLine = outputLine + T.nextToken(); } return(outputLine); } ```

• Example Program: (Demo above code)

How to run the program:

 Right click on link and save in a scratch directory To compile:   javac FormatText3.java To run:          java FormatText3 inp1 Or:               java FormatText3 inp2

Example:

• Input file 1:

 ```WE hold these Truths to be self-evident, that all Men are created equal, that they are endowed by their Creator with certain unalienable Rights, that among these are Life, Liberty and the Pursuit of Happiness. ```

• Output:

 ``` 012345678901234567890123456789 Before:>WE hold these Truths to be After: >WE hold these Truths to be 012345678901234567890123456789 Before:>self-evident, that all Men are After: >self-evident, that all Men are 012345678901234567890123456789 Before:>created equal, that they are After: >created equal, that they are 012345678901234567890123456789 Before:>endowed by their Creator with After: >endowed by their Creator with 012345678901234567890123456789 Before:>certain unalienable Rights, After: >certain unalienable Rights, 012345678901234567890123456789 Before:>that among these are Life, After: >that among these are Life, 012345678901234567890123456789 Before:>Liberty and the Pursuit of After: >Liberty and the Pursuit of 012345678901234567890123456789 Before:>Happiness. After: >Happiness. ```