PDA

View Full Version : Another c++ ? for stu



Orphious
11-05-01, 02:47 PM
I was wondering what is the easiest way to read in a string of character and check to see if they are a palindrome? Thanks stu

Stu
11-05-01, 09:32 PM
Well, the easiest way I can think of is using the STL algorithm library--particularly the reverse() function template. It reverses the elements in a container--and a string is a kind of container. You pass it two parameters the position of the first element and the position of the last element (in the case of a string; reverse(myString.begin() myString.end()); ). Here's how I would do it (less getting the user input):




#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>

class Palindrome {

public:

Palindrome(){}; // Does nothing

bool isPalindrome(string s) const {

size_t pos; // Position holder
string r; // This is a holder for the
// reverse of the input string

// Get rid of any leading spaces...
while(s[0] == ' ')
s.erase(0, 1);

// Get rid of any trailing spaces or new lines...
while( (s[s.size() - 1] == ' ') || (s[s.size() - 1] == '\n') )
s.erase(s.size() - 1, 1);

// Get rid of any punctuation...
while( (pos = s.find_first_of("`~!@#$%^&*()-_=+{}|[]\\:;\"\'<>,.?/\t\r\n")) != string::npos)
s.erase(pos, 1);

// Get rid of any double spaces...
while( (pos = s.find(" ")) != string::npos)
s.erase(pos, 1);

// Convert to uppercase (ignoring single spaces)...
while( (pos = s.find_first_of("abcdefghijklmnopqrstuvwxyz")) != string::npos)
s[pos] = toupper(s[pos]);

// Make sure it's not an empty string...
if(s.empty()){

// For demo, print message and bail...
cout << "Error: Empty String Entered!\n" << ends;
exit(0);

} // End if

// Copy the input string to a temp string...
r = s;

// Reverse the temp string...
reverse(r.begin(), r.end());

return (0 == s.compare(r));

} // End isPalindrome(string &)

bool isPalindrome(char * c) const {

string t; // Temp value for conversion

// Convert to string...
t = static_cast<string>(c);

// Pass to other method...
return this->isPalindrome(t);

} // End isPalindrome(char *)

}; // End class Palindrome


int main(int argc, char *argv[]){

Palindrome palindrome; // Class to evaluate
string s("otto"); // This is the input string

cout << s.c_str();

if(palindrome.isPalindrome(s))
cout << " is a ";
else
cout << " is not a ";

cout << "palindrome.\n" << ends;


} // End main()

Orphious
11-06-01, 03:25 PM
Let me ask you what this part means
int main(int argc, char *argv[])//the part in the parenthesis.
{
}
because I have seen it this way as well
int main()
{
return 0;
}
Whats the difference? Is one way better

Last question, what would be a good way to get input from the user and stick it in a stack, such as
cout << "Enter a string of characters\n";
could you read in the characters one at a time and stick them in a stack until you read a whitespace or something? I'm sure this isn't the best way, but the manual wants us to get exposure to stacks. Did that make any sense? Thanks again stu, you rock!

Stu
11-06-01, 06:51 PM
I'm used to having my programs take command-line options. So, I automatically write them that way. Basically, 'int argc' is the argument count of the parameters passed in, and 'char *argv[]' or 'char **argv' is an array of the arguments as character strings. argv[0] is the program name. Here's a simple example:




#include <iostream>

int main (int argc, char *argv[]){

for(unsigned int i = 0; i < argc; i++){

cout << "Argument "
<< i
<< " is "
<< argv[i]
<< '\n'
<< ends;

} // End for

} // End main()



If you run it like this (assuming the program name is myProgram):

myProgram this is an example

The output would be:

Argument 0 is myProgram
Argument 1 is this
Argument 2 is is
Argument 3 is an
Argument 4 is example

There is no real performance loss or gain using one or the other.

On to the stack thing. They probably want you to use a stack to reverse the string (even though the reverse() function template is probably a better way to go). I wouldn't go to the trouble of reading one character at a time. Just cin to a string and loop through it. Example:




#include <iostream>
#include <string>
#include <stack>

int main(int argc, char *argv[]){

string buf; // Input buffer
stack<char> chars; // Stack to store inputted chars

// Prompt and read...
cout << "Enter stuff: " << ends;
cin >> buf;

// Build stack...
for(unsigned int i = 0; i < buf.size(); i++)
chars.push(buf[i]);

// Print stack (show that it worked)...
while(!chars.empty()){

cout << chars.top() << endl;
chars.pop();

} // End for

} // End main()



Hope that helps...

Orphious
11-06-01, 08:50 PM
Man, your just a fountain of knowledge :D. Thanks again stu!!!!!

goofy78270
06-20-05, 08:25 PM
I have looked over your code and it looks great. How would you impliment this code as a stack or queue instead of a string?

Stu
07-06-05, 02:40 PM
Well, the Standard Template Library stacks and queues aren't containers--they are container adapters. Which in the most basic of terms means that they are a wrapper around a container (they both default to using a deque internally--but you can use vectors or lists just the same) and provide a simplistic LIFO/FIFO interface. However, in doing this they limit accessability--there are no iterators. So, the algorithms library reverse() approach to reversing the contents wouldn't work. But, they both have the operator==() member function--you can "return (r == s)". Therefore, the program remains virtually the same except you manually reverse the stack or queue. So, for stacks you'd replace reverse() with:




stack<char> temp(s);
stack<char> r;

while(!temp.empty()){
r.push(temp.top());
temp.pop();
}

return (r == s);



And for queues:




queue<char> temp(s);
queue<char> r;

while(!temp.empty()){
r.push(temp.front());
temp.pop();
}

return (r == s);