-2

I hate to bother on here, but a personal project of mine is persistently returning a stubborn error. Since I'm a computer science major, I've had a few fellow students look over it as well as my professor, to no avail.

The issue is I'm trying to write a program that takes a String, and at every 40 characters stores that segment into a spot in an array, so that the final print statement only needs to print out each element in the array on a new line and the whole text length will stay within 40 characters.

The errors arose once I modified said program, so that if the 40th character in the string was a letter, then the program will know that it is cutting off a word. Thus, to contravene this, I searched backward from that spot to the last index that was a space, and cut the line there instead. The remaining word is then added to the new line, and the program continues on.

However, that is not the case. For whichever reason, it cannot find a space character when searching back through the String, despite many being there.

Here's the particular segment the issue arises from:

//the following while loop searches for the last index in the string that
// was a space, therefore finding the beginning of the cut word. 
//Also account for the chance the index reaches the start of the string
                while(cutChar != ' ' && temp > 0){
                    temp--;
                    cutChar = sentence.charAt(temp);

                    //minuses the line of the char to be added to the next line
                    newLine = newLine.substring(0, newLine.length() - 1);
                }

And here is the program in it's entirity, comment-coded to the high heavens:

import java.util.*;
public class errorCheck{
    public static void main (String [] args) {

    //original sentence
    String sentence = "This test sentence should cut off properly at every 40th character and add any cut words to the next line.";

    //array to store each line
    ArrayList <String> words = new ArrayList<String>();

    //current line being filled
    String newLine = "";

    //individual character being read from the sentance string
    char character = ' ';

    //string to preserve any word severed when a new line is created
    String cutWord = "";

    //int to keep track of how many indexes to move over
    int cutAdd = 0;

    //char to keep track of the chars in the word being cut off at the end of the line
    char cutChar = ' ';

    //int to keep track of temporary place when searching for the beginning of the cut word
    int temp = 0;

    for (int i = 0; i < sentence.length(); i++){
        //examines the chars one by one in the sentance
        character = sentence.charAt(i);

        //makes sure each line is max 40 chars long
        if(i%40 == 0 && i > 1){
            //if the char at the 40 mark is a space or coma, add it to the line and start a new line
            if (character == ' ' || character == ','){
                newLine += character;
                words.add(newLine);
                newLine = "";
            }
            //else (aka the line stops in the middle of a word)
            else{
                //sets temporary character and index to current one
                cutChar = character;
                temp = i;

                //the following while loop searches for the last index in the string that was a space, therefore finding the beginning of the cut word. Also account for chance the index reaches the start of the string
                while(cutChar != ' ' && temp > 0){
                    temp--;
                    cutChar = sentence.charAt(temp);

                    //minuses the line of the char to be added to the next line
                    newLine = newLine.substring(0, newLine.length() - 1);
                }

                //once a space was found and the while loop broken, add a index to begin reading the severed word completely
                temp++;
                cutWord = "";
                //this while loop makes sure to read until it comes across another space or reaches the end of the string (in the even that this cut word happens to be the final word)
                while(cutChar != ' ' && sentence.length() >= temp){
                    //examines the chars in the sentance, adds it to the cut word, and increases the index
                    cutChar = sentence.charAt(i);
                    cutWord += cutChar;
                    temp++;
                    if (temp >= 40){
                        //counts the additional indexes to be added to the normal index when resumed
                        cutAdd++;
                    }
                }

                //after exiting the loop, the string "cutWord" should be the full word cut between the two lines

                //adds the new line (minus the chars taken for the cut word) 
                words.add(newLine);
                //starts a new line with cutWord being the start
                newLine += cutWord;
                //increases index by amount of new characters
                i += cutAdd;

                //resets the cut variables
                cutWord = "";
                cutAdd = 0;
            } 
        }

        //This loop makes sure that the final char is always added
        else if (i == (sentence.length() - 1)){
            newLine += character;
            words.add(newLine);
        }

        //if no other condition is met, the current character is simplily added to newLine
        else{
            newLine += character;
        }
    }

    //after all that, there should be an arraylist with a line for each element
    String[] wordsArray = new String[words.size()];
    //turn that arraylist to a regular one (because ideally in the end it's going to be sent over somewhere else)
    wordsArray = words.toArray(wordsArray);

    //should print out the sentance in lines that are 40 chars or less
    for (int i = 0; i < wordsArray.length; i++){
        System.out.println(wordsArray[i]);
    }

}
}

Currently, the while loop fails to stop at a space character in the String, and the output looks like this:

ERROR

Anyone knows a fix for this?

Eris Novae
  • 29
  • 1
  • 9
  • 2
    Have you tried stepping through the program with your debugger? – Jacob G. Apr 21 '18 at 00:29
  • 2
    If your current output does not match your desired output, and you don't know why, then it's time to start debugging. If you're not sure how to go about doing this, then please have a look at: [How to Debug Small Programs](http://ericlippert.com/2014/03/05/how-to-debug-small-programs/). It won't solve your direct problem, but it will give you steps that you can follow that should help you solve it yourself, or even if that is not successful, then at least help you to better isolate your problem so that your question can be more focused and easier to answer. – Hovercraft Full Of Eels Apr 21 '18 at 00:31
  • I code in Notepad++ (lame I know) but I do know that that first while loop is the source of the bug, since it's not seeming to read any spaces – Eris Novae Apr 21 '18 at 00:32
  • I know the reason why it's not working: the while loop is failing to exit at the condition that it comes across a space. The probably is that the .charAt doesn't seem to be returning a space, or else the while loop would've picked it up – Eris Novae Apr 21 '18 at 00:35
  • 3
    I can assure you that `String#charAt` functions correctly; it's highly unlikely that you found a bug in code that has functioned correctly for the last two decades. Because you *code* in Notepad++, you essentially have two options: switch to a modern IDE with debugging abilities, or print the state of each variable at every location in your code so you're able to trace every instruction. – Jacob G. Apr 21 '18 at 00:39
  • I have updated my comment but not sure if it works, please let me know! – Charis Moutafidis Apr 21 '18 at 00:43
  • @ErisNovae See my answer below. It significantly reduces the complexity of your code by deleting about 1/3 of it. It still works and produces the desired output by only changing a line or two otherwise. So a pretty significant improvement IMO. – Jeffrey Phillips Freeman Apr 21 '18 at 01:09

3 Answers3

0

I think the if statement that checks if the char is space or comma should actually be a while loop. And keep decreasing i while the char is space again.

   if (character != ' ' && character != ','){
            i--;
            character = sequence.charAt(i);
            while(character != ' ' && character != ','){
                i--;
                character = sequence.charAt(i);
            }
        }
    newLine += character;
    words.add(newLine);
    newLine = "";

And you get rid of the else clause. Can't test it right now so tell me id it works.

Charis Moutafidis
  • 363
  • 1
  • 4
  • 17
  • Thanks! You're definitely closer than me, but I can't seem to get that segment to work. If the character ended on a letter, then it'll be unable to enter the "if" segment of code entirely – Eris Novae Apr 21 '18 at 01:01
  • You are right! I changed the if statement, can you have a look at it now? – Charis Moutafidis Apr 21 '18 at 01:06
0

So first off a lot of your code wasnt needed. I removed the following section entirely. I also eliminated the temp variable.

            //once a space was found and the while loop broken, add a index to begin reading the severed word completely
            temp++;
            cutWord = "";
            //this while loop makes sure to read until it comes across another space or reaches the end of the string (in the even that this cut word happens to be the final word)
            while(cutChar != ' ' && sentence.length() >= temp){
                //examines the chars in the sentance, adds it to the cut word, and increases the index
                cutChar = sentence.charAt(i);
                cutWord += cutChar;
                temp++;
                if (temp >= 40){
                    //counts the additional indexes to be added to the normal index when resumed
                    cutAdd++;
                }
            }

            //after exiting the loop, the string "cutWord" should be the full word cut between the two lines

            //adds the new line (minus the chars taken for the cut word) 
            words.add(newLine);
            //starts a new line with cutWord being the start
            newLine += cutWord;
            //increases index by amount of new characters
            i += cutAdd;

            //resets the cut variables
            cutWord = "";
            cutAdd = 0;

Furthermore your issue is in how you kept track of where you read sentence. If you move back a few spaces then it is now <40 so will retrigger prematurely on the next line which will cause odd behavior. So instead i added a separate variable called readChars. Problem solved the following code now works.

import java.util.*;
public class errorCheck{
    public static void main (String [] args) {

    //original sentence
    String sentence = "This test sentence should cut off properly at every 40th character and add any cut words to the next line.";

    //array to store each line
    ArrayList <String> words = new ArrayList<String>();

    //current line being filled
    String newLine = "";

    //individual character being read from the sentance string
    char character = ' ';

    //string to preserve any word severed when a new line is created
    String cutWord = "";

    //int to keep track of how many indexes to move over
    int cutAdd = 0;

    //char to keep track of the chars in the word being cut off at the end of the line
    char cutChar = ' ';

    int charsRead = -1;
    for (int i = 0; i < sentence.length(); i++){
        charsRead++;

        //examines the chars one by one in the sentance
        character = sentence.charAt(i);

        //makes sure each line is max 40 chars long
        if(charsRead >= 40 && i > 1){
            //if the char at the 40 mark is a space or coma, add it to the line and start a new line
            if (character == ' ' || character == ','){
                newLine += character;
                words.add(newLine);
                newLine = "";
            }
            //else (aka the line stops in the middle of a word)
            else{
                //sets temporary character and index to current one
                cutChar = character;

                //the following while loop searches for the last index in the string that was a space, therefore finding the beginning of the cut word. Also account for chance the index reaches the start of the string
                while(cutChar != ' ' && i > 0){
                    i--;
                    cutChar = sentence.charAt(i);

                    //minuses the line of the char to be added to the next line
                    newLine = newLine.substring(0, newLine.length() - 1);
                }

                //after exiting the loop, the string "cutWord" should be the full word cut between the two lines

                //adds the new line (minus the chars taken for the cut word) 
                words.add(newLine);
                newLine = "";
            } 

            charsRead = 0;
        }

        //This loop makes sure that the final char is always added
        else if (i == (sentence.length() - 1)){
            newLine += character;
            words.add(newLine);
        }

        //if no other condition is met, the current character is simplily added to newLine
        else{
            newLine += character;
        }
    }

    //after all that, there should be an arraylist with a line for each element
    String[] wordsArray = new String[words.size()];
    //turn that arraylist to a regular one (because ideally in the end it's going to be sent over somewhere else)
    wordsArray = words.toArray(wordsArray);

    //should print out the sentance in lines that are 40 chars or less
    for (int i = 0; i < wordsArray.length; i++){
        System.out.println(wordsArray[i]);
    }

}
}

The above code produces the following output.

This test sentence should cut off
properly at every 40th character and
add any cut words to the next line.
  • 1
    Thank you so much! I knew something must've been off with my logic, but after having both my professor and peers look over it, I was getting worried. I completely overlooked that decrementing the i was not a sound choice for me to have made. Thank you so much for the explanation! – Eris Novae Apr 21 '18 at 01:17
  • @ErisNovae Happy to help. If you think this is the best answer dont forget to hit the check mark next to the question to give me credit for answering it. Upvote on any answers that helped as well. It helps me out. Regardless glad I could help. – Jeffrey Phillips Freeman Apr 21 '18 at 01:19
  • @ErisNovae BTW I just edited my question as i was able to remove the temp variable as well. So i did that here and looks even cleaner now. – Jeffrey Phillips Freeman Apr 21 '18 at 01:19
  • 1
    I really just wanna say thank you again! Usually sitting with a problem for a day or so helps me solve it, or commenting almost every line to keep track of my logic. I knew there couldn't be something wrong with the .charAt function itself, but for the life of me I couldn't find what else was causing the loop to miss all the spaces. It really means a lot to me how helpful and precise your answer was! :) – Eris Novae Apr 21 '18 at 01:27
  • @ErisNovae I'm very glad to help. I've been tutoring people in this for years and been working as a professional for well over 2 decades. It comes a lot easier to me than most at this stage so I'm happy to use that to help others. With that said, try adding debugging statements next time. Since you dont use an IDE just start adding in print statements everywhere to get a sense of the state of things. It really helps even if it gets messy. – Jeffrey Phillips Freeman Apr 21 '18 at 01:30
  • @ErisNovae Also as a side note, if you'd like you can reach me at freemo@gmail.com and if you ever have a problem where your stuck just reach out to me. I've been doing this so long I can usually spot the problem quickly and always happy to tutor, help, and teach a stuck student. – Jeffrey Phillips Freeman Apr 21 '18 at 01:31
  • @ErisNovae By the way as a side note. If I were to rewrite this entiely we could have probably done it in just a few lines. I tried to keep it as close to your original code as possible so you would learn something from it. But it might be a good exercise for you to think of alternative approaches to solving this same problem that might be more succinct. If its an exercise you want to do I can help you with that. – Jeffrey Phillips Freeman Apr 21 '18 at 01:35
  • 1
    You are too kind! I really grateful for all this, and I am slowly trying to transition to an IDE so hopefully until I get the hang of it, print statements will be able to cover me. My first computer science teacher was very old school, but because of it, I got a little too used to Notepad++ and compiling/running with the command prompt. But I'll be sure to remember to put more print statement in, even when I think my while loops are working! – Eris Novae Apr 21 '18 at 01:40
  • 1
    And I would love to practice more exercises! I spend a lot of my free time coding as it is, usually on stuff they don't teach in the classes so I have to self-learn a lot (predominantly GUI code). I want my code to be as efficient as possible, but I'm obviously still a student, so it's something I hope to get over time. But any exercises you can offer I'd be happy to take :) – Eris Novae Apr 21 '18 at 01:45
  • @ErisNovae fine me on gitter for a live chat sometime if youd like. You can message me directly here: https://42bitcrypto.slack.com/messages/D89TK1CCB/ I also have a few open source projects i run there so you can find me in this room for a chat: https://gitter.im/Syncleus/aparapi – Jeffrey Phillips Freeman Apr 21 '18 at 02:05
  • 1
    I do not have the email required for the first one, but I'll be sure to check out and jump into the second! :) – Eris Novae Apr 21 '18 at 02:19
0

This is a crazy lot of code to reinvent for this task. Why not use something like this (WordUtils is from Apache Commons Text):

String wrapped = WordUtils.wrap(theText, 40, “~~~”, true); 
String[] split = wrapped.split(“~~~”);
Ernest Friedman-Hill
  • 80,601
  • 10
  • 150
  • 186
  • Thanks for the answer, I had no clue about this! My professor was recommending StringTokenizer, so obviously there are many solutions to this problem that I was needlessly dragging out into more and more lines. – Eris Novae Apr 21 '18 at 01:50