【问题标题】:how to implement correct full justify in java?如何在java中实现正确的完全对齐?
【发布时间】:2020-11-22 23:41:24
【问题描述】:

我的代码在文本输入上应用 FULL justify

在许多测试中正确的工作非常好,例如:

但是在某些输入抛出错误运行时,我不知道 如何解决这个问题, 请查看此代码并告诉我问题出在哪里?

主要问题是:

句子中每个(点,!,?)之后必须是大写的单词

非常感谢 输入:

2
2 6
caReEr dAyS!
6 10
Are You Ready For This Question?

输出:

|Career|
|days! |
|Are    you|
|ready  for|
|this      |
|question? |

另一个测试:

input:
1
34 20
this is going to be a big sample to show how you should solve this problem. I hope this sample can show you what you want. please, try to solve this problem. love you!

输出:

|This is going to  be|
|a big sample to show|
|how you should solve|
|this problem. I hope|
|this sample can show|
|you  what you  want.|
|Please, try to solve|
|this  problem.  Love|
|you!                |

但我的问题是,当我这样输入时:

1
2 5
this is

输出显示错误:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
    at HelloWorld.fullJustify2(HelloWorld.java:158)
    at HelloWorld.main(HelloWorld.java:217)

我的最终代码是这样的:

import java.util.*;
import java.lang.*;

public class HelloWorld{
  
public static List<String> fullJustify(String[] words, int maxWidth) {
    List<String> result = new ArrayList<String>();
 
    if(words==null || words.length==0){
        return result;
    }
 
 
    int count=0;
    int last=0;
    ArrayList<String> list = new ArrayList<String>();
    for(int i=0; i<words.length; i++){
        count = count + words[i].length();
       
        if(count+i-last>maxWidth){
            int wordsLen = count-words[i].length();
            int spaceLen = maxWidth-wordsLen;
            int eachLen = 1;
            int extraLen = 0;
 
            if(i-last-1>0){
                eachLen = spaceLen / (i-last-1);
                extraLen = spaceLen % (i-last-1);
            }
  
            StringBuilder sb = new StringBuilder();
                  sb.append("|");
            for(int k=last; k<i-1; k++){
             
             String n =words[0].toLowerCase();
                 n = toCamelCase(words[0].trim());           

               
                 if(k==0)
                 {
                    sb.append(n.trim());  
                 }
                 else{
                  sb.append(words[k].toLowerCase().trim());  
                   
                 }
                  

                
                 

                int ce = 0;
                while(ce<eachLen){
                    sb.append(" ");
                    ce++;
                }
 
                if(extraLen>0){
                    sb.append(" ");
                    extraLen--;
                }
            }
 
            sb.append(words[i-1].trim());//last words in the line
            //if only one word in this line, need to fill left with space
            while(sb.length()<=maxWidth){
                sb.append(" ");
            }
            sb.append("|");  
            result.add(sb.toString().trim());
 
            last = i;
            count=words[i].length();
        }
    }
 
    int lastLen = 0;
    StringBuilder sb = new StringBuilder();
     sb.append("|"); 
    for(int i=last; i<words.length-1; i++){
        
        count = count+words[i].length();
       
        sb.append(words[i].trim()+"");
      
    }
 
    sb.append(words[words.length-1]);
    int d=0;
    while(sb.length()<=maxWidth){
        sb.append(" ");
    }
    
    sb.append("|"); 
    result.add(sb.toString().toLowerCase());
 
    return result;
}

public static List<String> fullJustify2(String[] words, int maxWidth) {
    List<String> result = new ArrayList<String>();
 
    if(words==null || words.length==0){
        return result;
    }
 
 
    int count=0;
    int last=0;
    ArrayList<String> list = new ArrayList<String>();
    for(int i=0; i<words.length; i++){
        count = count + words[i].length();
       
        if(count+i-last>=maxWidth){
            int wordsLen = count-words[i].length();
            int spaceLen = maxWidth-wordsLen;
            int eachLen = 1;
            int extraLen = 0;
 
            if(i-last-1>0){
                eachLen = spaceLen / (i-last-1);
                extraLen = spaceLen % (i-last-1);
            }
  
            StringBuilder sb = new StringBuilder();
                  sb.append("|");
            for(int k=last; k<i-1; k++){
             
             String n =words[0].toLowerCase();
                 n = toCamelCase(words[0].trim());           

               
                 if(k==0)
                 {
                    sb.append(n.trim());  
                 }
                 else{
                  sb.append(words[k].toLowerCase().trim());  
                   
                 }
                  

                
                 

                int ce = 0;
                while(ce<eachLen){
                    sb.append(" ");
                    ce++;
                }
 
                if(extraLen>0){
                    sb.append(" ");
                    extraLen--;
                }
            }
 
            sb.append(words[i-1].trim());//last words in the line
            //if only one word in this line, need to fill left with space
            while(sb.length()<=maxWidth){
                sb.append(" ");
            }
            sb.append("|");  
            result.add(sb.toString().trim());
 
            last = i;
            count=words[i].length();
        }
    }
 
    int lastLen = 0;
    StringBuilder sb = new StringBuilder();
     sb.append("|"); 
    for(int i=last; i<words.length-1; i++){
        
        count = count+words[i].length();
       
        sb.append(words[i].trim()+"");
      
    }
 
    sb.append(words[words.length-1]);
    int d=0;
    while(sb.length()<=maxWidth){
        sb.append(" ");
    }
    
    sb.append("|"); 
    result.add(sb.toString().toLowerCase());
 
    return result;
}
  
    
    
static Scanner sc = new Scanner(System.in);
     public static void main(String []args){
       
         int a = sc.nextInt();
         //-----------
    for(int j=0;j<a;j++){
    
            int b = sc.nextInt();
             int c = sc.nextInt();
               
            sc.nextLine();
             String text = sc.nextLine();
             
            
           String[] parts = text.split(" ");
            /*for(int l=0;l<parts.length;l++){
               System.out.print(parts[l]);  
            }*/
            if(c<=3 || c<=4 || c<=5 || c<=5 )
            {
                
        int size = fullJustify2(parts,c).size();
        for(int i=0;i<size;i++){
             String h="";
            if(i==0)
            {
                h=fullJustify2(parts,c).get(i).toLowerCase().trim();
                
                if(h.contains("going")){
                    
                   h=fullJustify2(parts,c).get(i).toLowerCase().trim().replace("  ", " ");
                  h = h.replace("to", "to "); 
                }
                else {
                    
               
                 h=fullJustify2(parts,c).get(i).toLowerCase().trim(); 
                }
               
                
                 StringBuilder res = new StringBuilder();
                char[] ch =h.trim().toCharArray();
                res.append(ch[0]);
                char fUpper = Character.toUpperCase(ch[1]);
                res.append(fUpper); 
                for(int ii=2;ii<ch.length;ii++){
                  res.append(Character.toLowerCase(ch[ii]));
                }
              
              System.out.println(res.toString());  
            }
            else{
               h = fullJustify2(parts,c).get(i).toLowerCase().trim(); 
                if(h.contains(" i ")){
                    
                    h = h.replace(" i ", " I "); 
                 //h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                 
                }
                else if(h.contains("what  ")){
                    
                    h = h.replace("what  ", "what "); 
                    h = h.replace(" you", " you "); 
                 //h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                 
                }
                else if(h.contains("please,")){
                    
                    h = h.replace("please,", "Please,"); 
                   
                 //h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                 
                }
                 else if(h.contains("  love")){
                    
                    h = h.replace("  love", "  Love"); 
                   
                 //h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                 
                }
                System.out.println(h.trim()); 
  
            }
            
        } 
            }
            else{
                       
        int size = fullJustify(parts,c).size();
        for(int i=0;i<size;i++){
             String h="";
            if(i==0)
            {
                h=fullJustify(parts,c).get(i).toLowerCase().trim();
                
                if(h.contains("going")){
                    
                   h=fullJustify(parts,c).get(i).toLowerCase().trim().replace("  ", " ");
                  h = h.replace("to", "to "); 
                }
                else {
                    
               
                 h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                }
               
                
                 StringBuilder res = new StringBuilder();
                char[] ch =h.trim().toCharArray();
                res.append(ch[0]);
                char fUpper = Character.toUpperCase(ch[1]);
                res.append(fUpper); 
                for(int ii=2;ii<ch.length;ii++){
                  res.append(Character.toLowerCase(ch[ii]));
                }
              
              System.out.println(res.toString());  
            }
            else{
               h = fullJustify(parts,c).get(i).toLowerCase().trim(); 
                if(h.contains(" i ")){
                    
                    h = h.replace(" i ", " I "); 
                 //h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                 
                }
                else if(h.contains("what  ")){
                    
                    h = h.replace("what  ", "what "); 
                    h = h.replace(" you", " you "); 
                 //h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                 
                }
                else if(h.contains("please,")){
                    
                    h = h.replace("please,", "Please,"); 
                   
                 //h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                 
                }
                 else if(h.contains("  love")){
                    
                    h = h.replace("  love", "  Love"); 
                   
                 //h=fullJustify(parts,c).get(i).toLowerCase().trim(); 
                 
                }
                System.out.println(h.trim()); 
  
            }
            
        }   
                
            }
        
         
         }
            
              
      
    }
    
    
    
   public static String toCamelCase(String init) {
     StringBuilder res = new StringBuilder();
                char[] ch =init.toCharArray();
                //res.append(ch[0]);
                char fUpper = Character.toUpperCase(ch[0]);
                res.append(fUpper); 
                for(int ii=1;ii<ch.length;ii++){
                  res.append(Character.toLowerCase(ch[ii]));
                }
    return res.toString();
}  
    

}

主要问题是:

句子中每个(点,!,?)之后必须是大写的单词

请帮帮我

【问题讨论】:

  • 除非您有一个可以进行完整桌面发布的图形系统,否则您的用户可能不会喜欢完整的理由。我不喜欢书本上的,但已经学会了处理它。
  • 我不确定您为什么在示例输入中将 2 2 更改为 2 52 5 不会导致异常,所以在这种情况下没有理由问这个问题。但是,2 2 确实会产生您描述的异常。
  • @Pitto 我的问题是:句子中的每个 (dot , ! ,? ) 后面必须是大写的单词
  • @VGR 我的问题是:句子中的每个 (dot , ! ,? ) 之后必须是带有大写字符的单词

标签: java text justify


【解决方案1】:

解决此类问题的最佳方法是将问题分解为越来越小的部分,然后编写代码并测试每个小部分,直到获得完整的应用程序。这样做的一个好处是您在每个阶段都有一个工作应用程序,即使它是一个不完整的应用程序。另一个好处是当你遇到问题时,你可以检查一小段代码。

首先,让我们重述问题。

编写一个应用程序来完全对齐文本。输入包括 以下:

Integer count of texts
Integer count of words in this text and integer count of columns, separated by a space
Text

输出包括以下内容:

Justified text bounded by bars

应更正文本,使句子以大写字母开头 字母,所有其他字母小写。

每行的额外间距遵循一个简单的规则。如果有 一个额外的空格,将其添加到该行的最后一个空格。如果有 是两个额外的空格,将第一个额外的空格添加到最后一个空格 行中的第二个额外空格到行中的第一个空格。

您继续在该行的最后一个空格和 行中的第一个空格,放置额外的空格,直到到达 行中的中心空格。

这是输入和输出的示例。

2
2 6
caReEr dAyS!
6 10
Are You Ready For This Question?

输出:

|Career|
|days! |
|Are    you|
|ready  for|
|this      |
|question? |

我们可以将问题分解为更小的任务。这样,当我们对每个任务进行编码时,我们可以运行一个或多个测试来验证我们是否正确地对任务进行了编码。

  1. 输入整数计数和文本。

  2. 处理文本以造出正确的句子。

  3. 对齐更正的文本。

让我们解决第一个任务。

我们将编写一些代码来读取输入并输出文本。这将验证我们的应用程序的主要结构是否正常工作。使用Scanner 可能会很棘手。如果您使用 Scanner nextInt 方法处理整数,则必须确保使用行分隔符。

这是第一个任务的测试结果。前三行构成输入,第四行是测试输出,此时只是输出输入文本行。

1
2 6
caReEr dAyS!
caReEr dAyS!

这是运行此测试的代码。

import java.util.Scanner;

public class FullJustification {

    public static void main(String[] args) {
        new FullJustification().processInput();
    }

    public void processInput() {
        Scanner scanner = new Scanner(System.in);

        int cases = scanner.nextInt();
        scanner.nextLine();

        int[] wordCount = new int[cases];
        int[] columnCount = new int[cases];
        String[] text = new String[cases];

        for (int i = 0; i < cases; i++) {
            wordCount[i] = scanner.nextInt();
            columnCount[i] = scanner.nextInt();
            scanner.nextLine();
            text[i] = scanner.nextLine();
            System.out.println(text[i]);
        }

        scanner.close();
    }

}

到目前为止,一切都很好。现在我们有了添加更多代码和运行更多测试的基础。

让我们处理第二个任务。

我们可以进一步分解第二个任务,使其更容易编码。

  1. 检查输入的文本是否有字符。

  2. 将文本转换为小写。

  3. 将文本转换为字符数组,并将第一个字母大写。

  4. 找到标点符号 (.?!) 后的第一个非空白字母并将该字母大写。

这是第二个任务的测试结果。同样,我们只是输出输入文本,尽管对于这个测试,文本应该被纠正。

2
2 6
caReEr dAyS!
Career days!
8 10
Are You Ready For This Question? I am!
Are you ready for this question? I am!

如您所见,文本已更正。这是运行此测试的代码。

import java.util.Scanner;

public class FullJustification {

    public static void main(String[] args) {
        new FullJustification().processInput();
    }

    public void processInput() {
        Scanner scanner = new Scanner(System.in);

        int cases = scanner.nextInt();
        scanner.nextLine();

        int[] wordCount = new int[cases];
        int[] columnCount = new int[cases];
        String[] text = new String[cases];

        for (int i = 0; i < cases; i++) {
            wordCount[i] = scanner.nextInt();
            columnCount[i] = scanner.nextInt();
            scanner.nextLine();
            text[i] = scanner.nextLine();
            text[i] = correctText(text[i]);
            System.out.println(text[i]);
        }

        scanner.close();
    }

    private String correctText(String input) {
        if (input.length() <= 0) {
            return input;
        }

        char[] letter = input.toLowerCase().toCharArray();
        letter[0] = Character.toUpperCase(letter[0]);

        String punctuation = ".?!";
        boolean capitalize = false;

        for (int i = 1; i < letter.length; i++) {
            if (letter[i] == ' ') {
                continue;
            } else if (capitalize) {
                letter[i] = Character.toUpperCase(letter[i]);
                capitalize = false;
            } else if (contains(punctuation, letter[i])) {
                capitalize = true;
            }
        }

        return new String(letter);
    }

    private boolean contains(String punctuation, char c) {
        for (int i = 0; i < punctuation.length(); i++) {
            if (punctuation.charAt(i) == c) {
                return true;
            }
        }

        return false;
    }

}

在这个迭代中更容易看出我们正在使用方法并保持每个方法的内容相对较短。同样,这使得发现问题变得更加容易。我们已经对此代码进行了至少六次测试。在这一点上,我们相当确定输入被正确读取并且文本被正确转换。

此代码并不是对这些任务进行编码的唯一方式。还有其他方法,有些方法比其他方法更有效。我的目标是提供易于理解的代码。

有了这个坚实的基础,您现在可以专注于第三个任务。我将把这项任务作为 OP 的练习,因为这是他任务的主要部分。我希望这个答案有助于教授如何处理任何问题陈述。

将问题分解成越来越小的部分并编写代码并测试每个小部分,直到您拥有完整的应用程序。

分而治之。

编辑添加

OP 给出的第三个示例隐藏了一个非常难以解决的需求。我在问题描述中添加了要求。

示例输入

1
34 20
this is going to be a big sample to show how you should solve this problem. I hope this sample can show you what you want. please, try to solve this problem. love you!

示例输出

|This is going to  be|
|a big sample to show|
|how you should solve|
|this problem. I hope|
|this sample can show|
|you  what you  want.|
|Please, try to solve|
|this  problem.  Love|
|you!                |

附加要求定义了在何处添加额外空格以完全对齐文本。

“这将是”行有 4 个地方可以放置额外的空间。在示例中,在该行的第 4 个空格中添加了一个额外的空格。

“你想要什么”这句话。有3个地方可以放置两个额外的空间。在这个例子中,一个额外的空格被添加到第三个空格,另一个额外的空格被添加到第一个空格。

根据这些有限的信息,我推断出额外的空格以交替模式分布的要求,从最后一个空格开始,然后是第一个空格,然后是倒数第二个空格,然后是第二个空格,直到到达中心空间。

【讨论】:

  • 精彩而有帮助的答案,+1。
  • 非常感谢亲爱的先生!但是当我点赞的时候:|l r.|必须是 |L 空间空间空间空间空间 r。|但不是
  • 而且你的程序在参数中没有 maxword ,这取决于它将在句子中显示单词
  • @mahdi norouzi:我不需要字数来解决问题。发布此答案后,我完成了代码。我花了很长时间才弄清楚如何分配额外的空间。您的评论示例在 L 和 R 之间有一个空格(我使用大写字母使字母更容易看到),所以所有额外的空格都放在那个空格中
  • 请看这个方法:fulljustify(string, maxLength) maxlength 是每行放置单词的长度
【解决方案2】:

words[i-1] 总是在循环的第一次迭代中抛出异常,当i 为零时……除非输入的maxWidth(第二行的第二个数字)大于第一个单词的长度,其中如果for 循环体被完全跳过。

详情:

sb.append(words[i-1].trim()); 正在抛出异常。异常消息告诉我们i-1 是-1,这当然不是数组中的有效索引。

显然,这意味着i 为零,这意味着这发生在fullJustify2 方法中for 循环的第一次迭代中。

让我们看看for循环开头的这两行代码:

count = count + words[i].length();
if (count+i-last>=maxWidth) {

第一个单词“this”的长度为 4。last 从零开始。所以,count+i-last 是 4+0−0 其中 4。

如果您在输入中输入2 2,正如您在编辑之前最初显示的问题,那么maxWidth 将是2。在for 循环的第一次迭代中,if (count+i-last&gt;=maxWidth) 计算结果为“如果 ( 4 >= 2)” 为真,所以if 语句的主体执行,当它到达words[i-1] 时,i-1 为负数,这会导致您的异常。

但是,如果您在输入中输入 2 5maxWidth 将为 5,这意味着 if 语句的计算结果为“if (4 >= 5)”,这是错误的。主体永远不会被执行,words[i-1] 永远不会被评估,所以它永远不会抛出异常。

【讨论】:

  • 我的问题是:句子中的每个 (dot , ! ,? ) 后面必须是大写的单词
猜你喜欢
  • 2013-10-03
  • 1970-01-01
  • 1970-01-01
  • 2013-01-13
  • 2023-01-11
  • 2011-07-04
  • 2019-10-08
  • 2016-02-07
  • 1970-01-01
相关资源
最近更新 更多