LPString insert Solution

Our goal is to experience how pictures can help us see problem details and develop the general algorithms necessary to write program statements. It may not be necessary to draw a detailed picture for each statement, but it can help us solve particularly challenging problems. The following step-by-step solution follows the steps outlined in Figure 19. As you study each figure, focus on the articulation between the picture and the C++ statement. Our overarching goal is not merely writing the function but understanding how to solve the problem with a C++ member function. Ask yourself, "How does the code help solve the overall problem?"

void LPString::insert(const LPString& s, int index)
Two LPStrings represented as a sequence of boxes. this string is 'Hello world!' where the length, 12, is saved in text[0], 'H' is in text[1], and '1' is in text[12]. String s is 'new ' with the length, 4, in s.text[0], 'n' in s.text[1], and a blank or space in s.text[4].
The insert starting point. The function header establishes the two LPString objects involved in the insert operation. The parameter string, s, cannot change, implying that the function inserts s into this LPString. Both LPString objects have an array member variable named text. The second parameter, index, is the index location where the function inserts s into this. The first array element, text[0], stores the length of both strings.
Step 1
  • Verify that the total length of the two strings will not overflow the target; throw an exception if the total is too long.
  • The sum of the two string lengths must not exceed the maximum length of an LPString
  • if (text[0] + s.text[0] >= LENGTH)
    	throw "LPStrings are too long for insertion.";
Step 2
  • Verify that the index parameter is valid (i.e., inbounds or inside the target string).
  • The function can't insert characters at array[0] because that location stores the string's length.
  • The function can insert characters in anywhere in this or even one space beyond the end: 1 ≤ index ≤ array[0] + 1. Why isn't it appropriate to insert characters two or more spaces beyond the end of this?
  • if (index < 1 || index > text[0] + 1)
    	throw "index location is too large";
Including these tests at the beginning of the function has two pronounced advantages. First, if either error occurs, the tests provide diagnostic messages that help users correct the problem, and they cannot ignore it. Second, the tests simplify subsequent statements. The function uses for-loops to complete the following shifting and copying operations. The loops do not require code to prevent overflow or out-of-bounds errors because they only run if the strings pass the tests in this figure.
A picture showing the function shifting 'world!' to the right four positions. The shift begins with '!' and works to the left, ending with 'w'.
for (int i = text[0] - index; i >= 0; i--)
	text[index + s.text[0] + i] = text[index + i];
Step 3: shifting text. The insert operation may occur anywhere in this string. The function must shift some characters to the right to make room for the inserted text. The shift begins at the insertion point right, index, and proceeds to the end of the string. It's easier to illustrate the shift operation with two arrays, but there is only one array, and the shift operation copies a character from one location in the array to a different location in the same array. Before we can copy a character into an array element, we must "save" the element's contents to an unused location in the array. So, we start the shift operation at the right end of this string, location 12 in this example, and work from right to left - from 12 to 7. Tables are often a good way to track all the operations in a loop, especially in a for-loop where the operations depend on the loop control variable. Notice that i goes from 5 down to 0, which makes the shift operation work from right to left.
i 1
i = text[0] - index
From 2
index + i
Character Shifted
text[index + i]
To 3
index + s.text[0] + i
12 - 7 = 5 7 + 5 = 12 ! 7 + 4 + 5 = 16
4 7 + 4 = 11 d 7 + 4 + 4 = 15
3 7 + 3 = 10 l 7 + 4 + 3 = 14
2 7 + 2 = 9 r 7 + 4 + 2 = 13
1 7 + 2 = 8 o 7 + 4 + 1 = 12
0 7 + 0 = 7 w 7 + 4 + 0 = 11
  1. The for-loop runs or iterates once for each character it shifts to the right. This value is the number of characters from the index to the end of the string: length - index + 1. The "=" part of the ">=" accounts for the +1.
  2. The index location of the next character the loop shifts right. The assignment operation copies the character from the source location to the destination, leaving the source unchanged (illustrated by the unshaded characters).
  3. The index location where the loop copies the character.
The picture shows the function copying the characters 'new ' in s.text to 'this' string. The function copies the character 'n' to 'tex[7], 'e' to 'text[8], 'w' to text[9], and the space to the space to 'text[10].
for (int i = 0; i < s.text[0]; i++)
	text[index + i] = s.text[i + 1];
Step 4: copying the characters. Once we've made space in the target string, the copy operation is quite straightforward.
The function updates the length of 'this' string: 'text[0]' is set to 16.
text[0] += s.text[0];
Step 5: update this string's length. The final result when the insert function finishes.
void LPString::insert(const LPString& s, int index)
{
	if (text[0] + s.text[0] >= LENGTH)				// prevent overflow
		throw "LPStrings are too long for insertion.";
	if (index < 1 || index > text[0] + 1)				// validate index in bounds
		throw "index location is too large";

	for (int i = text[0] - index; i >= 0; i--)			// shift characters right
		text[index + s.text[0] + i] = text[index + i];

	for (int i = 0; i < s.text[0]; i++)				// copy characters
		text[index + i] = s.text[i + 1];

	text[0] += s.text[0];						// update the size
}
The complete LPString insert function.