Line Justification

Pages: 12
Hello,
So i am working on an assignment for Line justification for any string that is input. The line has to be 75 characters long and the code has to include a getline(), find_first_of, find_first_not_of. This is the outline he gave us.
loop until the string is the right size
locate the end of the next word
obtain a random Boolean value (conditional operator is useful here)
if true
insert space
locate the beginning of the next word,
if end of the string is reached, start from the beginning of the string

I am really lost on how to do this and I really don't know much about strings yet. I know the getline should look something like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

#include <string>
#include <iostream>
using std::cout; using std::cin; using std::endl; using std::string;
  
int main() {
	string s;
	string quit = "y";

	do {
		cout << "Enter string and hit return: ";
		getline(cin, s);
		cout << "done? ";
		getline(cin, quit);

	} while (quit != "y");
Last edited on
"Line justification" is pretty vague. I'm not sure what you mean.
Sorry! So I have to space out lines like so input line:
Contrary to popular belief, Lorem Ipsum is not simply random text.
your line justified:
Contrary to  popular belief,        Lorem Ipsum  is not       simply    random      text.


First by punctuation (.,?!;) (two spaces) then between words at random if the line is not 75 characters after spacing out the punctuation but a line that is shorter than 40 characters is considered the end of a paragraph is not justified.
Last edited on
So you read a string:
1) You replace all single spaces by double spaces.
2) You add two spaces after every punctuation found.

I didn't understand the other part ;p
Is it
-> If string after inserting is greater than 75 characters then something?
-> If string after inserting is shorter than 40 characters then something?
What is the something?

Are you just checking (after inserting spaces) whether the string is greater than 40 words, between 40 and 70words or greater than 70 words?

What output do you want for each of the three cases?
So I need each line of a string that is input to be 75 characters long, First you need to check if the string is shorter than 75 characters but longer than 40 then if it is between those to add 2 spaces after the punctuation but after that is done and the string still is not 75 characters random spaces are inserted between words in the string to make it 75 characters long.
So since Contrary to popular belief, Lorem Ipsum is not simply random text. is 63 characters long 2 spaces will be added after each punctuation then random spaces will be added to the string between words making it
Contrary to  popular belief,   Lorem Ipsum  is not   simply  random    text.
Last edited on
What happens if the inputted string is greater than 40?

What if the user inputs something like: Hello(3 whitespace)Dude, how are you. Would the output be 'Hello(1whitespace)Dude' or 'Hello(4whitespace)Dude'?

What if the beginning character is a whitespace?

So do we need to trim all whitespaces (multiple whitespaces to one whitespace) or just the whitespaces at terminal ends?

And so when the string is not 75 characters we start inserting white spaces from left to right


Hint: You need to iterate through the string using for-loop and use conditionals
Last edited on
So if the input was Hello(3 whitespace) Dude, how are you it would just output Hello(3 white space)Dude, how are you since since the string is less than 40 characters long.
Last edited on
So if it's less than 40 character we don't modify the string at all?
And what if we have 'Hello(3whitespace)Dude' in a string greater than 40characters? Does it become Hello(4whitespace)Dude or Hello(2whitespace)Dude?
Last edited on
Correct if the string is less than 40 characters is does not get modified.

If 'Hello(3whitespace)Dude' is in a string greater than 40 characters the whitespace is still counted in each but it was change the punctuation first and randomly add other whitespace if needed between words so it could change to 'Hello(4whitespace)Dude' or stay 'Hello(3whitespace)Dude' or even change to 'Hello(5whitespace)Dude' if if needed to go through again to add more whitespace to satisfy the 75 characters.

Okay assuming that we don't have to deal with trimming whitespaces,
-> Use .length() to check the length of the string. And then use conditionals to decide whether you are going to justify the line or not.

If you're going to justify the line,
-> Use a for-loop to iterate over the string indexes.
-> Initialize a variable by assigning the length of the string to it.

the for condition will loop till the initialized variable is less than 76.
-> If the loop comes across a whitespace and the previous character was non-whitespace, you insert a whitespace (Use [index-1] to get previous index)
-> If the loop comes across a punctuation, you insert a whitespace (the loop above will also add a whitespace so you will have the required cumulative of 2whitespaces after the punctuation.
^ Use conditionals.
Whenever you insert a whitespace, increment the initialized variable by one.

If you want priority for the punctuation, then you have a separate for-loop before the above for-loop which is responsible for inserting whitespaces after punctuation. Then you won't have to bother about punctuations in the second for-loop.

Last edited on
So to start it would it be something like this? and how can i change it since s.find_first_of() has to many characters?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main() {
	string s;
	int pos;
	string quit = "y";

	do {
		cout << "Enter string and hit return: ";
		getline(cin, s);
		cout << "done? ";
		getline(cin, quit);

	} while (quit != "y");
	if (s.length < 75) {
		while (pos != string::npos) {
			int pos = s.find_first_of('.,?!;');

			s.insert('  ');
		}
	}
	else return s;
Last edited on
You can solve this with find_first_of too.

What to do since s.find_first_of() has too many characters? Just change single quotes to double quotes hehe ;P, that should still work.

int pos = s.find_first_of(".,?!;"); should be outside the while loop
followed by int pos = s.find_first_of(".,?!;", pos+1); inside the while loop

Without the first line the while condition won't work and without the second like the function will keep finding the same character ^_^

Good thinking though!

You can use find_first_of for inserting whitespaces between words as well, in a similar manner but then make sure the previous index is a non-whitespace.
Last edited on
so for inserting whitespace between words with a find_first_of would it be another if while loop?
I take it that you want to give the punctuations priority, so yes that would be another if while loop (with another if condition inside to make sure previous index is non-whitespace) . ^_^

Even otherwise it would make sense to use two while loops with this approach.

Good luck ;)
here is what I have so far
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <string>
#include <iostream>
using std::cout; using std::cin; using std::endl; using std::string;


int main() {
	string s;
	int pos;
	string quit = "y";

	do {
		cout << "Enter string and hit return: ";
		getline(cin, s);
		cout << "done? ";
		getline(cin, quit);

	} while (quit != "y");
	int pos = s.find_first_of(".,?!;");
	if (s.length < 75) {
		while (pos != string::npos) {
			int pos = s.find_first_of(".,?!;", pos+1);
			s.insert('  ');
		}
	}
	if (s.length < 75) {
		if () { //condition to ignore nonwhitespace
			s.find_first_of(" ");
			s.insert(' ');
		}

	}
	if (s.length < 40 || s.length>75) {
		cout << "Incorrect, The string is not between 40 and 75 characters.";
	}
	
 
}


but what if condition would I put to ignore the nonwhitespace?
Last edited on
Inside the second while loop, use isspace (accounts for all kinds of whitespaces)

-> After you've found position of white space inside the while loop, write
1
2
if(!(isspace(s[pos-1])))
   s.insert(' ');


s[pos-1] is the index previous to the found index (index of the whitespace that was found).
isspace(s[pos-1]) checks whether the position is a whitespace character.
and lastly we enclose the entire expression with parenthesis and negate it with !.

So the if statement becomes: If the previous index is not whitespace, execute block (which is s.insert in this case)

This is a good approach for the most part but is slower than iterating over every character manually, which you don't have to worry about but I'm just mentioning it so you know when find_first_of is not ideal.


Oh and one more thing. You haven't even mentioned a position for the insert! ;P

Have you tried compiling it?

Oh and another thing, you want to add an if condition inside the while loop itself to make sure that pos has a value. (pos gets -1 when no matches are found)
Last edited on
so lines 25-30 would look like this?
1
2
3
4
5
if (s.length < 75) {
		if (!(isspace(s[pos-1]))) { //condition to ignore nonwhitespace
			s.insert(' ');
		}
	}
urawrath where is the while loop? But that's how the condition would look like.

I added a few things to my last post so make note of them and try writing the entire code once and for all now that you have what you need. Try compiling and let us know.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <string>
#include <iostream>
using std::cout; using std::cin; using std::endl; using std::string;

const int maxwidth = 75;
const int minwidth = 40;
int main() {
	string s;
	int pos;
	string quit = "y";

	do {
		cout << "Enter string and hit return: ";
		getline(cin, s);
		cout << "done? ";
		getline(cin, quit);

	} while (quit != "y");
	int pos = s.find_first_of(".,?!;");
	if (s.length() < maxwidth) {
		while (pos != string::npos) {
			int pos = s.find_first_of(".,?!;", pos+1);
			s.insert(pos, '  ');
			
	
		}
	}
	if (s.length() < maxwidth) {
		while (isspace(s[pos - 1])) {
			if (!(isspace(s[pos - 1]))) {
				s.insert(pos, ' ');
			}
		}
	}
	if (s.length() < minwidth || s.length() > maxwidth) {
		cout << "Incorrect, The string is not between 40 and 75 characters.";
	}
	cout << s;
}


I have 5 errors with this,

Error C2086 'int pos': redefinition line 19
Error C2059 syntax error: 'constant' line 23

Error C2664 'std::_String_iterator<std::_String_val<std::_Simple_types<char>>> std::basic_string<char,std::char_traits<char>,std::allocator<char>>::insert(std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>,std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>,std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>)': cannot convert argument 1 from 'int' to 'std::_String_const_iterator<std::_String_val<std::_Simple_types<char>>>' line 31


Error abc no instance of overloaded function "std::basic_string<_Elem, _Traits, _Alloc>::insert [with _Elem=char, _Traits=std::char_traits<char>, _Alloc=std::allocator<char>]" matches the argument list line 23



Error abc no instance of overloaded function "std::basic_string<_Elem, _Traits, _Alloc>::insert [with _Elem=char, _Traits=std::char_traits<char>, _Alloc=std::allocator<char>]" matches the argument list line 31



Last edited on
Okay try this. You can ask me if you didn't get any part.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <string>
#include <iostream>
#include <limits>  
using std::cout; using std::cin; using std::endl; using std::string;

const int maxwidth = 75;
const int minwidth = 40;

int main() {
	string s;
	int pos = -1;
	char quit = 'y';

	do {
		cout << "Enter string and hit return: ";
		getline(cin, s);
		cout << "done? ";
		cin.get(quit);
		cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

	} while (quit != 'y');
	if (s.length() < minwidth || s.length() > maxwidth) {
		cout << "Incorrect, The string is not between 40 and 75 characters.";
		cout << "\nit was: '" << s.length() << "' characters long";
	}
	else {
		pos = s.find_first_of(".,?!;");
		while (pos != string::npos) {
			s.insert(pos, " ");
			pos = s.find_first_of(".,?!;", pos + 2);
		}
		if (s.length() < maxwidth && s.length() > minwidth) {
			while (s.length() < 75) {
				pos = s.find_first_of(' ');
				while (pos != string::npos && s.length() < 75) {
					if (!(isspace(s[pos - 1])))
						s.insert(pos, " ");
					pos = s.find_first_of(' ', pos + 2);
				}
			}
		}
		cout << s;
	}
	cin.get();
	return 0;
}
Last edited on
Pages: 12