Please review the following as needed:
%
()
The debugger examples build on previous examples. Please review the following as needed:
The following palnumber demonstrations follow the algorithms developed in the Palindrome-number problem section and parallel the cpalnumber.cpp programs presented previously in this chapter. However, the following demonstrations replace the C-strings used in the earlier versions with instances of the C++ string class. Presented first is a string version of the "finger" solution. The next example creates a function that converts integers into string objects, a function similar to the itoa function we wrote previously. The last demonstration presents a string version of the "reverse" solution.
#include <iostream> #include <string> using namespace std; int main() { for (int number = 1; ; number++) // (a/I.i. and I.ii.) { int square = number * number; // (b/II.) //---------------------------------------------- III. string s = to_string(square); // (c) //---------------------------------------------- IV. if (s.length() < 6) // (d/IV.i) continue; if (s[0] == '0' || s[s.length() - 1] == '0') // (e/IV.ii) continue; //---------------------------------------------- IV.iii int i; // (f) for (i = 0; i < s.length() / 2; i++) // (g) if (s[i] != s[s.length() - 1 - i]) // (h) break; if (i == s.length() / 2) // (i) { cout << number << " " << square << endl; // (j) break; } } return 0; }
to_string(square)
converts a number to an instance of the string class. So, the statement converts the square to a string.continue
skips all of the statements from there down, and the for-loop gets the next candidate number).if (s.at(0) == '0' || s.at(s.length() - 1) == '0')
if (s.find_first_of('0') == 0 || s.find_last_of('0') == s.length() - 1)
if (s.find('0') == 0 || s.rfind('0') == s.length() - 1)
at
function behaves very much like the index operator, []
, but includes a range check on the index value. The functions find
and find_first
behave the same way when the argument is a single character (see "Searching" for more detail) and return the index of the first occurrence of the argument character.i < s.length() / 2
divides the string in half, skipping the middle character if the number of characters is odd.s[i]
represents the character pointed at by our left hand, which moves to the right as i increases. s[s.length() - 1 - i]
represents the character pointed at by our right hand, which moves to the left as i increases and the indexing expression subtracts it from the string's length. The at
function may be used in place of the index operator, []
.break
statement, then the string is not a palindrome.Visual Studio 2012 added the to_string function to C++. Before then, the palnumber example included its own version of to_string. Although writing our own to_string function is no longer necessary, doing so is still a good learning exercise. Internally, computers store textual data in a coded format. Java uses Unicode, a 2-byte integer, to encode text. C++ can represent text as a 1- or 2-byte (wide) character. We focus on 1-byte characters encoded with the older American Standard Code for Information Interchange (ASCII) scheme.
Examine the ASCII table, especially the middle column; look at the codes for the characters '0' through '9' (the red characters). The character '0' is represented by the numeric code 48 (base 10), and the character '9' is represented by the numeric code 57 (base 10). Also, notice that the characters between '0' and '9' are represented by consecutive code values.
Given an integer, our task is to convert that integer into a string that looks like the number. The solution involves working with an integer one digit at a time. If we work from left to right, the string will contain the digits in the correct order. However, working from left to right is difficult because we don't know how many digits the number has. Working backward (right to the left) is easier but converts the digits in reverse order. The string concatenation operator allows us to solve this problem elegantly: we append or concatenate the new characters on the right side of the string as we build it.
Before using our conversion function, we must modify the palnumber.cpp code in Figure 1 in two ways:
string my_to_string(int n);
to_string(square);
with
my_to_string(square);
string my_to_string(int n) // (a) { string s; // (b) string sign; // (c) if (n < 0) // (d) { sign = "-"; n *= -1; // n = -n; // alternate way of making n positive } do // (e) { s = (char)(n % 10 + '0') + s; // (f) n /= 10; // (g) } while (n); // (h) return sign + s; // (i) }
string s;
instantiates an empty string object named s.string sign;
instantiates an empty string object named sign; this string will hold a "-" if n < 0.n % 10
extracts the lowest digit of the number. Remember how the mod operator works: use the value 123 as an example, 123 % 10 = 3 (123 / 10 = 12 with a remainder of 3).+ '0'
adds the ASCII code for a '0' (48) to the numeric value of the last digit. Continuing the example: 3 + 48 = 51.(char)
casts the numeric value represented by the expression inside the grouping parentheses into a character. The ASCII table indicates that 51 is the code for the character '3.' So, (char)51
converts the numeric 51 to a character '3.' Overall, (char)(n % 10 + '0')
extracts the rightmost digit from a number and converts it to a character.(char)(n % 10 + '0') + s
concatenates the character to the left side of the string. The first time through the loop, s is empty, and the expression on the left of "+" evaluates to the character '3,' so string s becomes "3." The second time through the loop, the character is '2.' The concatenation operation, 2+3 yields the string "32"n /= 10
discards the one's digit (i.e., the rightmost digit). Returning to the example of 123, 123 / 10 = 12
(using integer division). The operation with assignment stores 12 back into n.while (n)
loops until n becomes 0. Recall that C++ treats 0 as false and non-0 as true. When n becomes a single digit, then n / 10
is 0, ending the loop.return sign + s;
concatenates sign (which is either an empty string or "-1") to the left of string s and returns the resulting string as the function's return value.The definition of a palindrome is a string that reads the same forwards and backward (without considering spaces or other punctuation characters). The program described below solves the palindrome-number problem based on the definition. It reverses the candidate string and then compares it to the original string. If the two strings are the same (i.e., equal), then the candidate string is a palindrome; if the two strings are not the same, then the candidate is not a palindrome.
int main() { for (int number = 1; ; number++) // (a) { int square = number * number; // (b) string s = to_string(square); // (c) if (s.length() < 6) // (d) continue; if (s.find('0') == 0 || s.rfind('0') == s.length() - 1) // (e) continue; if (s == reverse(s)) // (f) { cout << number << " " << square << endl; break; } } return 0; }
reverse
function, detailed in the next figure, and uses the overloaded string operator ==
to test the two strings for equality.
"Traditional" For-Loop | For-Range Loop |
---|---|
string reverse(string s) { string r; for (int i = 0; i < s.length(); i++) // (a) r += s[s.length() - 1 - i]; // (b) return r; } |
string reverse(string s) { string r; for (char c : s) // (c) r = c + r; // (d) return r; } |
s.length() - 1 - i
indexes into the string beginning with the last character and moves backward (i.e., right to left) as the loop control variable increases. The +=
string operator concatenates the characters extracted from the original string to the right of any characters already in the reversed string.c + r
concatenates the character extracted from the original string to the left of the characters already added to the reversed string. The new string created by the concatenation operation replaces the contents of (i.e., is stored in) the reversed string, r.Comparing the C-string and string class solutions for the palindrome-number problem, including the three different versions of the reverse function, suggests three elaborating questions that we should ask ourselves:
+=
, which concatenates the new character to the right of the reversed string. The for-range loop uses separate operators: +
and =
, and c+r
concatenates the new character to the left of the reversed string. Can you figure out why there is a difference?