Palindrome class help in C++ [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Hi i am trying to write a palindrome class but am getting the wrong results.
I need to create a Palindrome class and return whether the phrase is a Palindrome.
Here is my code.
Palindrome.h:
#ifndef PALINDROME_H
#define PALINDROME_H
#include <iostream>
#include<cstring>
using namespace std;
class Palindrome{
private:
char str[1024];
char s1[1024];
char s2[1024];
int a;
int b;
public:
Palindrome(char s2[1024], int a, int b)
{
s2[1024] = { 0 };
a = 0;
b = 0;
}
void removeNonLetters(char str[]);
void lowerCase(char s1[]);
bool isPalindrome(char s2[], int a, int b);
}; // End of class definition
#endif
Palindrome.cpp:
#include "Palindrome.h"
void Palindrome::removeNonLetters(char str[])
{
char s1[1024] = { 0 };
int j = 0;
int l1 = strlen(str);
for (int i = 0; i < l1; i++)
{
if (str[i] <= '9' && str[i] >= '0')
{
s1[j++] = str[i];
}
else if ((str[i] >= 'A' && str[i] <= 'Z')
|| (str[i]) >= 'a' && str[i] <= 'z')
{
s1[j++] = str[i];
}
}
cout << s1 << endl;
}
void Palindrome::lowerCase(char s1[])
{
char s2[1024] = { 0 };
int l2 = strlen(s1);
int g = 0;
for (int i = 0; i < l2; i++)
{
if (s1[i] >= 'a' && s1[i] <= 'z')
{
s2[g++] = s1[i];
}
else if (s1[i] >= 'A' && s1[i] <= 'Z')
{
s2[g++] = s1[i] + 32;
}
}
cout << s2 << endl;
}
bool Palindrome::isPalindrome(char s2[], int a, int b)
{
if (a >= b)
return true;
cout << "Yes" << endl;
if (s2[a] != s2[b])
return false;
else
return isPalindrome(s2, a + 1, b - 1);
cout << "No" << endl;
}
Main.cpp:
#include "Palindrome.h"
int main()
{
char str[1024] = { 0 };
char s1[1024] = { 0 };
char s2[1024] = { 0 };
cout << "input a string:" << endl;
cin.getline(str, sizeof(str));
Palindrome removeNonLetters(char str[]);
Palindrome lowerCase(char s1[]);
int length = strlen(s2);
Palindrome isPalindrome(s2, 0, length - 1);
return 0;
}

You teacher may not like this, but this is how we do it in the real world.
First things first, reach for the standard library:
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
A function to strip non-alpha characters from a string:
std::string strip(std::string s)
{
s.erase(std::remove_if(std::begin(s),
std::end(s),
[](auto c) { return !std::isalpha(c); }),
std::end(s));
return s;
}
A function to transform a string to lower case:
std::string to_lower(std::string s)
{
std::transform(std::begin(s),
std::end(s),
std::begin(s),
[](auto c) { return std::tolower(c); });
return s;
}
A function to check that a string is the same in reverse as it is forwards:
bool is_palindrome(const std::string& s)
{
return std::equal(std::begin(s), std::end(s),
std::rbegin(s), std::rend(s));
}
Putting it all together in a test:
int main()
{
auto word = std::string("a!b B <>A");
if (is_palindrome(to_lower(strip(word)))) {
std::cout << "palindrome" << std::endl;
}
else {
std::cout << "not palindrome" << std::endl;
}
return 0;
}
Complete listing:
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
std::string strip(std::string s)
{
s.erase(std::remove_if(std::begin(s),
std::end(s),
[](auto c) { return !std::isalpha(c); }),
std::end(s));
return s;
}
std::string to_lower(std::string s)
{
std::transform(std::begin(s),
std::end(s),
std::begin(s),
[](auto c) { return std::tolower(c); });
return s;
}
bool is_palindrome(const std::string& s)
{
return std::equal(std::begin(s), std::end(s),
std::rbegin(s), std::rend(s));
}
int main()
{
auto word = std::string("a!b B <>A");
if (is_palindrome(to_lower(strip(word)))) {
std::cout << "palindrome" << std::endl;
}
else {
std::cout << "not palindrome" << std::endl;
}
return 0;
}

There are many things wrong with your code. I hope these pointers help:
You should be using std library.
Why does the constructor for the class take any parameters? Nothign uses them
Why are there any member variables? Nothing uses them.
Why are the functions in a class at all? They're just functions - they should be in a functions library or similar.
The functions just write to cout so are useless.
Your main function doesn't even seem to call the functions correctly.
I tried this:
char str[1024] = { 0 };
cout << "input a string:" << endl;
cin.getline(str, sizeof(str));
int length = strlen(str);
Palindrome a(str,0, length);
a.removeNonLetters(str);
a.lowerCase(str);
a.isPalindrome(str, 0, length - 1);
cin.getline(str, sizeof(str));
return 0;
I don't get the exception but get the following output:
input a string:
EVIL rats on no star **** live
EVILratsonnostarlive
evilratsonnostarlive
Yes
However this works too:
input a string
hello
hello
hello
Yes
So the first two functions seem to work (if removing spaces was also intentional) but the third does not.

Related

String function optimisation?

I'm new to C++ and i just wrote a function to tell me if certain characters in a string repeat or not:
bool repeats(string s)
{
int len = s.size(), c = 0;
for(int i = 0; i < len; i++){
for(int k = 0; k < len; k++){
if(i != k && s[i] == s[k]){
c++;
}
}
}
return c;
}
...but i can't help but think it's a bit congested for what it's supposed to do. Is there any way i could write such a function in less lines?
Is there any way i could write such a function in less lines?
With std, you might do:
bool repeats(const std::string& s)
{
return std::/*unordered_*/set<char>{s.begin(), s.end()}.size() != s.size();
}
#include <algorithm>
bool repeats(std::string s){
for (auto c : s){
if(std::count(s.begin(), s.end(), c) - 1)
return true;
}
return false;
}
Assuming you are not looking for repeated substrings :
#include <iostream>
#include <string>
#include <set>
std::set<char> ignore_characters{ ' ', '\n' };
bool has_repeated_characters(const std::string& input)
{
// std::set<char> is a collection of unique characters
std::set<char> seen_characters{};
// loop over all characters in the input string
for (const auto& c : input)
{
// skip characters to ignore, like spaces
if (ignore_characters.find(c) == ignore_characters.end())
{
// check if the set contains the character, in C++20 : seen_characters.contains(c)
// and maybe you need to do something with "std::tolower()" here too
if (seen_characters.find(c) != seen_characters.end())
{
return true;
}
// add the character to the set, we've now seen it
seen_characters.insert(c);
}
}
return false;
}
void show_has_repeated_characters(const std::string& input)
{
std::cout << "'" << input << "' ";
if (has_repeated_characters(input))
{
std::cout << "has repeated characters\n";
}
else
{
std::cout << "doesn't have repeated characters\n";
}
}
int main()
{
show_has_repeated_characters("Hello world");
show_has_repeated_characters("The fast boy");
return 0;
}
std::string str;
... fill your string here...
int counts[256]={0};
for(auto s:str)
counts[(unsigned char)s]++;
for(int i=0;i<256;i++)
if(counts[i]>1) return true;
return false;
6 lines instead of 9
O(n+256) instead of O(n^2)
This is your new compact function :
#include <iostream>
#include <algorithm>
using namespace std;
int occurrences(string s, char c) {
return count(s.begin(), s.end(), c); }
int main() {
//occurrences count how many times char is repetated.
//any number other than 0 is considered true.
occurrences("Hello World!",'x')?cout<<"repeats!":cout<<"no repeats!";
//It is equal write
//
// if(occurrences("Hello World!",'x'))
// cout<<"repeats!";
// else
// cout<<"no repeats!";
//So to count the occurrences
//
// int count = occurrences("Hello World!",'x');
}

How to make sure that two strings only have certain alphabets in c++

Aim is to make sure that the user entered input for string 1 and string 2 contains only characters A,T,G or C in any order. If either string contains another other character then error should be displayed. Example:
Input contains error
Error in String #1: aacgttcOgMa
Error in String #2: ggataccaSat
This is my attempt at LCS.cpp file code:
#include "LCS.h"
#include <string>
using namespace std;
bool validate(string strX, string strY)
{
string x = strX;
string y = strY;
char searchItem = 'A';
char searchItem = 'C';
char searchItem = 'G';
char searchItem = 'T';
int numOfChar = 0;
int m = strX.length();
int n = strY.length();
for (int i = 0; i < m; i++)
{
if (x[i] == searchItem)
{
numOfChar++;
}
for (int i = 0; i < n; i++)
{
if (y[i] == searchItem)
{
numOfChar++;
}
}
}
This is my LCS.h file code:
#pragma once
#ifndef LCS_H
#define LCS_H
#include <string>
using namespace std;
bool validate(string strX, string strY);
#endif
And my driver file "Driver6.cpp" has this code:
#include "LCS.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
string strX, strY;
cout << "String #1: ";
cin >> strX;
cout << "String #2: ";
cin >> strY;
//validate the input two strings
if (validate(strX, strY) == false)
{
return 0;
}
int m = strX.length();
int n = strY.length();
}
Didn't really want to do this but it seems like the best bet rather than going round the houses in the comments:
#include <string>
#include <iostream>
bool validate( const std::string & s ) {
for ( auto c : s ) {
if ( c != 'A' && c != 'T' && c != 'C' && c != 'G' ) {
return false;
}
}
return true;
}
int main() {
std::string s1 = "ATGCCCG";
std::string s2 = "ATGfooCCCG";
if ( validate( s1 ) ) {
std::cout << "s1 is valid\n";
}
else {
std::cout << "s1 is not valid\n";
}
if ( validate( s2 ) ) {
std::cout << "s2 is valid\n";
}
else {
std::cout << "s2 is not valid\n";
}
}
Another technique:
bool validate(const std::string& s)
{
const static std::string valid_letters("ATCGatcg");
for (auto c: s)
{
std::string::size_type position = valid_letters.find_first_of(c);
if (position == std::string::npos)
{
return false;
}
}
return true;
}
The above code searches a container of valid letters.

How to insert an integer with leading zeros into a std::string?

In a C++14 program, I am given a string like
std::string s = "MyFile####.mp4";
and an integer 0 to a few hundred. (It'll never be a thousand or more, but four digits just in case.) I want to replace the "####" with the integer value, with leading zeros as needed to match the number of '#' characters. What is the slick C++11/14 way to modify s or produce a new string like that?
Normally I would use char* strings and snprintf(), strchr() to find the "#", but figure I should get with modern times and use std::string more often, but know only the simplest uses of it.
What is the slick C++11/14 way to modify s or produce a new string like that?
I don't know if it's slick enough but I propose the use of std::transform(), a lambda function and reverse iterators.
Something like
#include <string>
#include <iostream>
#include <algorithm>
int main ()
{
std::string str { "MyFile####.mp4" };
int num { 742 };
std::transform(str.rbegin(), str.rend(), str.rbegin(),
[&](auto ch)
{
if ( '#' == ch )
{
ch = "0123456789"[num % 10]; // or '0' + num % 10;
num /= 10;
}
return ch;
} // end of lambda function passed in as a parameter
); // end of std::transform()
std::cout << str << std::endl; // print MyFile0742.mp4
}
I would use regex since you're using C++14:
#include <iostream>
#include <regex>
#include <string>
#include <iterator>
int main()
{
std::string text = "Myfile####.mp4";
std::regex re("####");
int num = 252;
//convert int to string and add appropriate number of 0's
std::string nu = std::to_string(num);
while(nu.length() < 4) {
nu = "0" + nu;
}
//let regex_replace do it's work
std::regex_replace(std::ostreambuf_iterator<char>(std::cout),
text.begin(), text.end(), re, nu);
std::cout << std::endl;
return 0;
}
WHy not use std::stringstream and than convert it to string.
std::string inputNumber (std::string s, int n) {
std::stringstream sstream;
bool numberIsSet = false;
for (int i = 0; i < s; ++i) {
if (s[i] == '#' && numberIsSet == true)
continue;
else if (s[i] == '#' && numberIsSet == false) {
sstream << setfill('0') << setw(5) << n;
numberIsSet = true;
} else
sstream << s[i];
}
return sstream.str();
}
I would probably use something like this
#include <iostream>
using namespace std;
int main()
{
int SomeNumber = 42;
std:string num = std::to_string(SomeNumber);
string padding = "";
while(padding.length()+num.length()<4){
padding += "0";
}
string result = "MyFile"+padding+num+".mp4";
cout << result << endl;
return 0;
}
Mine got out of control while I was playing with it, heh.
Pass it patterns on its command line, like:
./cpp-string-fill file########.jpg '####' test###this### and#this
#include <string>
#include <iostream>
#include <sstream>
std::string fill_pattern(std::string p, int num) {
size_t start_i, end_i;
for(
start_i = p.find_first_of('#'), end_i = start_i;
end_i < p.length() && p[end_i] == '#';
++end_i
) {
// Nothing special here.
}
if(end_i <= p.length()) {
std::ostringstream os;
os << num;
const std::string &ns = os.str();
size_t n_i = ns.length();
while(end_i > start_i && n_i > 0) {
end_i--;
n_i--;
p[end_i] = ns[n_i];
}
while(end_i > start_i) {
end_i--;
p[end_i] = '0';
}
}
return p;
}
int main(int argc, char *argv[]) {
if(argc<2) {
exit(1);
}
for(int i = 1; i < argc; i++) {
std::cout << fill_pattern(argv[i], 1283) << std::endl;
}
return 0;
}
I would probably do something like this:
using namespace std;
#include <iostream>
#include <string>
int main()
{
int SomeNumber = 42;
string num = std::to_string(SomeNumber);
string guide = "myfile####.mp3";
int start = static_cast<int>(guide.find_first_of("#"));
int end = static_cast<int>(guide.find_last_of("#"));
int used = 1;
int place = end;
char padding = '0';
while(place >= start){
if(used>num.length()){
guide.begin()[place]=padding;
}else{
guide.begin()[place]=num[num.length()-used];
}
place--;
used++;
}
cout << guide << endl;
return 0;
}

Taking Each Individual Word From a String in C++

I am writing a method in C++ which will take a string of 2 or more words and output each individual word of the string separated by a second or so, using the sleep() method. I am trying to do this using a for loop and substrings. I am unsure also of the regexs which should be used, and how they should be used, to achieve the desired output.
I have reviewed this and this and find my question differs since I am trying to do this in a loop, and not store the individual substrings.
Input:
"This is an example"
Desired output:
"This " (pause) "is " (pause) "an " (pause) "example."
Use std::stringstream, no regular expressions required:
#include <iostream>
#include <sstream>
using namespace std;
int main() {
stringstream ss("This is a test");
string s;
while (ss >> s) {
cout << s << endl;
}
return 0;
}
Also, see How do I tokenize a string in C++?
Here are a pair of implementations that don't involve creating any extraneous buffers.
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/copy.hpp> //for boost::copy
#include <chrono>
#include <iostream>
#include <string>
#include <experimental/string_view> //in clang or gcc; or use boost::string_ref in boost 1.53 or later; or use boost::iterator_range<char*> in earlier version of boost
#include <thread>
void method_one(std::experimental::string_view sv)
{
for(auto b = sv.begin(), e = sv.end(), space = std::find(b, e, ' ')
; b < e
; b = space + 1, space = std::find(space + 1, e, ' '))
{
std::copy(b, space, std::ostreambuf_iterator<char>(std::cout));
std::cout << " (pause) "; //note that this will spit out an extra pause the last time through
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
void method_two(std::experimental::string_view sv)
{
boost::copy(
sv | boost::adaptors::filtered([](const char c) -> bool
{
if(c == ' ')
{
std::cout << " (pause) "; //note that this spits out exactly one pause per space character
std::this_thread::sleep_for(std::chrono::seconds(1));
return false;
}
return true;
})
, std::ostreambuf_iterator<char>(std::cout)
);
}
int main() {
const std::string s{"This is a string"};
method_one(s);
std::cout << std::endl;
method_two(s);
std::cout << std::endl;
return 0;
}
Live on coliru, if you're into that.
you can implement your own method:
//StrParse.h
#pragma once
#include <iostream>
static counter = 0;
char* strPar(char* pTxt, char c)
{
int lenAll = strlen(pTxt);
bool strBeg = false;
int nWords = 0;
for(int i(0); i < lenAll; i++)
{
while(pTxt[i] != c)
{
strBeg = true;
i++;
}
if(strBeg)
{
nWords++;
strBeg = false;
}
}
int* pLens = new int[nWords];
int j = 0;
int len = 0;
for(i = 0; i < lenAll; i++)
{
while(pTxt[i] != c)
{
strBeg = true;
i++;
len++;
}
if(strBeg)
{
pLens[j] = len;
j++;
strBeg = false;
len = 0;
}
}
char** pStr = new char*[nWords + 1];
for(i = 0; i < nWords; i++)
pStr[i] = new char[pLens[i] + 1];
int k = 0, l = 0;
for(i = 0; i < lenAll; i++)
{
while(pTxt[i] != c)
{
strBeg = true;
pStr[k][l] = pTxt[i];
l++;
i++;
}
if(strBeg)
{
pStr[k][l] = '\0';
k++;
l = 0;
strBeg = false;
}
}
counter++;
if(counter <= nWords)
return pStr[counter - 1];
else
return NULL;
}
//main.cpp
#include "StrParse.h"
void main()
{
char* pTxt = " -CPlusPlus -programming -is -a - superb thing ";
char* pStr1 = NULL;
int i = 1;
char sep;
std::cout << "Separator: ";
sep = std::cin.get();
std::cin.sync();
while(pStr1 = strPar(pTxt, sep))
{
std::cout << "String " << i << ": " << pStr1 << std::endl;
delete pStr1;
i++;
}
std::cout << std::endl;
}

C++ Palindrome program

I find myself oddly perplexed on this homework assignment. The idea is to create a Palindrome program, using a specific header the professor wants us to use, but for some reason, when I run it, right after I enter the phrase the program crashes on me.
Here is the program
#include <iostream>
#include <ctime>
#include "STACK.h"
using namespace std;
int main(void)
{
// Declare variables
time_t a;
STACK<char, 80> s;
STACK<char, 80> LR;
STACK<char, 80> RL;
char c;
char c1;
char c2;
// Displays the current time and date
time(&a);
cout << "Today is " << ctime(&a) << endl;
// Prompts the user to enter the string
cout << "Enter a phrase: ";
while(cin.get(c) && (c != '\n'))
{
if(isalpha(c))
{
c = toupper(c);
LR.PushStack(c);
s.PushStack(c);
}
}
// Copies s into RL in reverse order
while(!(s.EmptyStack() ) )
{
c = s.PopStack();
RL.PushStack(c);
}
// Checks for Palindrome
while(!(LR.EmptyStack() ) )
{
c1 = LR.PopStack();
c2 = RL.PopStack();
if( c1 != c2)
{
break;
}
}
// Displays the result
if(LR.EmptyStack() )
{
cout << "Palindrome";
}
else
{
cout << "Not a Palindrome";
}
return 0;
}
And here is the header (I am not allowed to change this)
#ifndef STACK_H
#define STACK_H
template <class T, int n>
class STACK
{ private: T a[n];
int counter;
public:
void MakeStack() { counter = 0; }
bool FullStack()
{ return (counter == n) ? true : false ; }
bool EmptyStack()
{ return (counter == 0) ? true : false ; }
void PushStack(T x)
{ a[counter] = x; counter++; }
T PopStack()
{ counter--; return a[counter]; }
};
#endif
You are not calling MakeStack, which will set STACK initial size (0).