having a difficulty with making a palindrome program c++ [duplicate] - c++

This question already has answers here:
std::cin input with spaces?
(8 answers)
Closed 7 years ago.
Hi this is my code for the palindrome program:
void palindrome()
{
string input;
bool checkInput, palindrome;
palindrome = true;
do
{
checkInput = false;
cout << "Enter a word, phrase or sentence :\n";
getline(cin, input);
for (unsigned int i = 0; i < input.size(); i++)
{
if (input[i] < 65 || input[i] > 90 && input[i] < 97 || input[i] > 122)
{
checkInput = true;
}
}
} while (checkInput);
for (unsigned int i = 0, j = input.size() - 1; i < input.size(); i++, j--)
{
if (input[i] != input[j] && input[i] + 32 != input[j] && input[i] - 32 != input[j])
{
palindrome = false;
break;
}
}
if (palindrome)
{
cout << "\n\nTo consider only letters and digits:\n";
cout << input << "\nYes, it is palindrome!\n";
cout << "\t\t Press <Enter> key back to menu";
fflush(stdin);
cin.get();
}
else
{
cout << "\n\nTo consider only letters and digits:\n";
cout << input << "\nNOPE, it's not palindrome\n";
cout << "\t\t Press <Enter> key back to menu";
fflush(stdin);
cin.get();
}
}
and when my input is racecar it reads and says it is a palindrome, but when my input is race car (with a space) it doesn't read and it says its not a palindrome.
My intend is to ignore all the spaces. Any help will be much appreciated!
Thanks in advance!
**editted
so i switched my cin >> input to getline(cin, input) and it doesnt let me input my words or phrases

Maybe it will work if you first remove all whitespaces after reading the Input?
#include <algorithm>
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
Whitespaces are not in die ASCII values you are checking, so the whileloop ends at the first whitespace.

The Problem
The palindrome is a word that is spelled backwards and forwards the same. Therefore, you can be sure that, going from the outside in, the letters need to be the same until you're examining the same letter (the total number of letters are odd) or the letter-searching things/examiners/markers (let's call them iterators) criss-cross.
How do you examine pair of letters from outside to inside? By using an index loop from the first to last position in tandem with a last-to-first index loop.
How You Do it (The Implementation)
Let's pretend we have two variables to act as the iterators, i and j. i will move forward while j will move backward. They will start at opposite ends:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
//This is where our word will be.
std::string str;
//Get input
std::cout << "Input your word, please!" << std::endl;
std::getline(std::cin, str);
//Let's use std::erase to take away our whitespaces from the
//C++11 library <algorithm>
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
//Initialize i and j, our iterators
//I use auto because the iterator type is long. It's a reason why auto was invented.
auto i = str.begin();
auto j = str.end() - 1;
//You see, str.end() is actually the END, and not the last letter.
//That's why it has a -1.
bool is_palindrome = true;
while (i < j) //While the two haven't crossed yet
{
//This std::cout shows you what i and j are at each repeat
std::cout << "i = " << *i << " ||| j = " << *j << std::endl;
//If the two characters marked by the two iterators are not equal
if (*i != *j)
{
is_palindrome = false;
break;
}
else
{
//Let's continue.
++i;
--j;
}
}
//If the loop gets to this point successfully, it's a palindrome.
if (is_palindrome)
std::cout << str << " is a palindrome!" << std::endl;
else
std::cout << str << " is not a palindrome." << std::endl;
return 0;
}
Hopefully this will help you. Remember to compile with -std=c++11 for C++11 features!

See if this works.
for (unsigned int i = 0, j == input.size() - 1; i < input.size();)
{
//Ignore spaces
if (input[i] == ' ')
{
++i; continue;
}
if (input[j] == ' ')
{
--j;continue;
}
//Automatic palindrome analysis
if (input[i] != input[j])
{
palindrome = false;
break;
}
++i;--j;
}

Related

Trying to find the number of words without counting the spaces

I am trying to find the number of words in from the input by user but i am asked not to find it through counting the spaces since the user can input a single letter and a bunch of spaces and it will count it as number of words
I have tried it with counting the number of spaces but i can not think of another way to count the number of words
char Array[100];
{
//variable declaration
int words = 0;
// input
cout << "Enter string: ";
cin.getline(Array, 100);
// Number of words
for (int i = 0; i < strlen(Array); i++)
{
if (Array[i] == ' ')
words++;
}
cout << "Number of words in the string are: " << words + 1;
cout << endl;
}
I want to find the number of words with another method rather than counting it through the number of spaces.Any help is appreciated.I am a beginner so could you not use something complicated to solve the problem like a getloc.
You just have to count the number of times the space character is followed immediately by a non-space character.
int firstNonSpace = 0;
while (Array[firstNonSpace] == ' ') //to skip spaces at the beginning of input
{
firstNonSpace++;
}
for (int i = firstNonSpace; i < strlen(Array) - 1; i++)
{
if (Array[i] == ' ' && Array[i+1] != ' ')
words++;
}
if(words || firstNonSpace == 0)
words++; //do not increment if the input is empty or only spaces.
cout << "Number of words in the string are: " << words;
See Live Demo
Note that you will have to handle the case when the input exceeds the bounds of the array so as not to run into undefined behavior.
The easiest way is to let the standard library parse the words for you, eg:
#include <iostream>
#include <string>
#include <sstream>
int main () {
//variable declarations
std::string line, word;
int words = 0;
// input
std::cout << "Enter string: ";
std::getline(std::cin, line);
// Number of words
std::istringstream iss(line);
while (iss >> word) {
++words;
}
std::cout << "Number of words in the string are: " << words << std::endl;
return 0;
}
If you don't want to use std::string (ie, to avoid memory allocations), you could do this instead:
#include <iostream>
#include <algorithm>
#include <cctype>
int main() {
//variable declarations
char Array[100];
int words = 0;
// input
std::cout << "Enter string: ";
std::cin.getline(Array, 100);
// Number of words
char *ptr = Array;
char *end = ptr + std::cin.gcount();
while (ptr != end) {
ptr = std::find_if(ptr, end, [](char c){ return !std::isspace(static_cast<unsigned char>(c)); });
if (ptr == end) break;
ptr = std::find_if(ptr+1, end, [](char c){ return std::isspace(static_cast<unsigned char>(c)); });
++words;
}
std::cout << "Number of words in the string are: " << words << std::endl;
return 0;
}
Or, if you want to completely avoid standard library algorithms:
#include <iostream>
int main() {
//variable declarations
char Array[100];
int words = 0;
// input
std::cout << "Enter string: ";
std::cin.getline(Array, 100);
// Number of words
char *ptr = Array;
char *end = ptr + std::cin.gcount();
while (ptr != end) {
while ((*ptr <= ' ')) && (ptr != end)) ++ptr;
if (ptr == end) break;
++ptr;
while ((ptr != end) && (*ptr > ' ')) ++ptr;
++words;
}
std::cout << "Number of words in the string are: " << words << std::endl;
return 0;
}
You could then wrap the parsing into a helper function to clean up the counting loop:
#include <iostream>
//#include <algorithm>
//#include <cctype>
bool findNextWord(char* &begin, char *end) {
/*
begin = std::find_if(begin, end, [](char c){ return !std::isspace(static_cast<unsigned char>(c)); });
if (begin == end) return false;
begin = std::find_if(begin+1, end, [](char c){ return std::isspace(static_cast<unsigned char>(c)); });
return true;
*/
while ((begin != end) && (*begin <= ' ')) ++begin;
if (begin == end) return false;
++begin;
while ((begin != end) && (*begin > ' ')) ++begin;
return true;
}
int main() {
//variable declarations
char Array[100];
int words = 0;
// input
std::cout << "Enter string: ";
std::cin.getline(Array, 100);
// Number of words
char *ptr = Array;
char *end = ptr + std::cin.gcount();
while (findNextWord(ptr, end)) {
++words;
}
std::cout << "Number of words in the string are: " << words << std::endl;
return 0;
}
Just do the following change and bob's your uncle :)
if(array[i] == ' ') {
continue;
}
words++;
while(array[i] != ' ') {
i++;
}
I was looking online and found them all very confusing this is simple and works
string state;//variable for statement the user may enter
int i; //variable for the for loop
int wordtally; // variable for word count
//this checks if its a space or not and then if it is a space it loops untill it
//reaches a character then after reaching a character loops until it hits a space anmd
//when that happens the counter goes up making it so every time a blank amount of spaces
//then a word it increases word count
for ( i=0 ; i < state.length() ; i++ )
{
if(state[i]==' '){
do {
i++;
}while(state[i]==' ');
}
else if(state[i]>=' '){
do {
i++;
}
while(state[i]>' ');
wordtally++ ;
}
}

Pig latin conversion using Cstrings

The program takes in a word given by the user and translates that to pig latin. I've gotten everything to work almost perfectly, but have run into two bugs. The first of which is when translating words that begin with consonants say "count", the output is "ounttcay" instead of "ountcay". The second bug is that when for three letter words like "egg" or "not" the output is "egg_\377ay" or "ottn\377ay". Is there a simple way to remove that duplicate character and get rid of those numbers?
Note - Unfortunately it has to be done using a Cstring
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
int convertToPigLatin(char arr[50]);
bool isVowel(char ch);
int main() {
char userInput[50];
char answer = ' ';
do {
cout << "Enter a word to convert it to pig latin" << endl;
cin.getline(userInput, 50); //get user input
cout << "Your entered word is " << userInput << endl;
convertToPigLatin(userInput); //translate user's input into piglatin
cout << "Would you like to convert another word?" << endl;
cin >> answer;
cin.ignore(); //clear past user input
cin.clear();
} while (answer == 'Y' || answer == 'y');
return 0;
}
bool isVowel (char ch) {
switch (tolower(ch)) { //if the first character of the given input is a vowel
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return true;
default:
return false;
}
}
int convertToPigLatin(char arr[50]) {
char newArr[50];
// string conjunctions[6] = {"and","but","for","nor","yet","the"}; //list of conjunctions not to be converted
size_t arrLength = strlen(arr); //holds length of input
for (int i = 0; i < arrLength; i++) { //make sure all characters in input are lower case for easier processing
newArr[i] = tolower(arr[i]);
}
char lastChar = newArr[0]; //save the first character in case it needs to be appended
if (atoi(arr) || arr[0] == '\0') { //if the input contains a number or begins with a null character print an error
cout << "Cannot translate inputs that contain numbers" << endl;
return -1;
} else if (arrLength <= 2) { // if the input is 2 or less characters
cout << newArr << endl; //print the input as is
cout << "Boring! Try somthing more than 2 characters long" << endl;
return 0;
} else if ((strstr(newArr, "and") && arrLength == 3) || (arrLength == 3 && strstr(newArr, "but")) || (arrLength == 3 && strstr(newArr, "for")) || (arrLength == 3 && strstr(newArr, "nor")) || (arrLength == 3 && strstr(newArr, "yet")) || (arrLength == 3 && strstr(newArr, "the"))) { //if the input is more than 2 characters long
cout << newArr << endl; //print the input as is
cout << "No conjucntions try again!" << endl;
return 0;
} else { //if the given input is three characters and is not a conjunction, being translation
if (isVowel(arr[0])) { //check if input's first character is a vowel
cout << "Your word in piglatin is "<< strcat(newArr, "ay") << endl; //print that string with 'ay' at the end (i.e. egg'ay')
return 0;
} else { //else if the given input starts with a consonant
for (int r = 1; r < arrLength; r++) {
newArr[r-1] = newArr[r];
newArr[arrLength] = lastChar;
}
cout << "Your word in piglatin is " << strcat(newArr, "ay") << endl;
return 0;
}
}
return 0;
}
You're not terminating newArr, and the last index of the input string is arrLength - 1.
int convertToPigLatin(char arr[50]) {
// Make sure newArr is properly terminated.
char newArr[50] = {0};
// [...]
} else { //else if the given input starts with a consonant
for (int r = 1; r < arrLength; r++) {
newArr[r-1] = newArr[r];
}
// Do this outside the loop.
newArr[arrLength-1] = lastChar;
// No need for strcat here.
cout << "Your word in piglatin is " << newArr << "ay" << endl;
}
}
return 0;
}
You need to add the '\0' at the end of newArr because strlen does not count it so you are not copying it. strcat replaces '\0' witn 'ay\0' but you have no '\0'.
for (int r = 1; r < arrLength; r++) {
newArr[r-1] = newArr[r];
newArr[arrLength] = lastChar;
}
newArr[arrLength+1] = '\0';
cout << "Your word in piglatin is " << strcat(newArr, "ay") << endl;

How to count unique words in string and output line where they occur? C++

So I'm working on this homework assignment and I'm really having trouble. I'm supposed to count the number of words more than two characters(have to contain one letter), unique words, and the number of times each unique word appears in the Programming Execution Environment. I'm also supposed to get input to search for in the PEE and output the number of times it appears and the line where it appears. I have some of it working, but I'm really struggling with counting how many times each word appears. I know my code is really bad right now, but that's why I'm here. I'm really struggling with these string functions for some reason. Any help is really appreciated!
#include <iostream>
#include <cstring>
#include <string>
#include <cctype>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
//PEE string
string envstr("");
bool checkChar(unsigned c)
{
return (ispunct(c) || isspace(c) || isblank(c) || isdigit(c) || c == '\n');
}
void searchWord(unsigned c, size_t length)
{
multiset<string> words;
vector<string> vwrds; //this was something i was trying out
string tempword;
while (!checkChar(envstr[c]) && c < length)
{
tempword = tempword + envstr[c]; //problem here
c++;
}
tempword = tempword + " ";
vwrds.push_back(tempword);
words.insert(tempword); //this is just a bunch of random letters
tempword.clear();
//for (multiset<string>::const_iterator i(words.begin()), end(words.end()); i != end; i++)
//cout << *i;
}
bool checkIfWord(char c)
{
bool valid = false;
int i;
for (i = c; i > c - 2; i--)
{
if (!checkChar(envstr[i]))
valid = true;
}
if (valid)
searchWord(i, envstr.length());
return valid;
}
int main()
{
//this code given by my instructor
extern char **environ; // needed to access your execution environment
int k = 0;
size_t wordCount = 0;
while (environ[k] != NULL)
{
cout << environ[k] << endl;
string str(environ[k]);
envstr = envstr + str;
k++;
}
//iterator to count words
wordCount = count_if(envstr.begin(), envstr.end(), checkIfWord);
cout << "\nThe PEE contains " << wordCount << " words. \n";
//transform environment string to lowercase
transform(envstr.begin(), envstr.end(), envstr.begin(), tolower);
string input;
do
{
cout << "Enter your search item: \n";
cin >> input;
//string can only be forty characters
if (input.length() > 40 || input == "\n")
{
cout << "That search query is too long. \n";
continue;
}
//change the search string to lowercase, like the envstr
transform(input.begin(), input.end(), input.begin(), tolower);
int j = 0;
int searchCount = 0;
vector<size_t> positions;
size_t pos = envstr.find(input, 0);
//search for that string
while (pos != string::npos)
{
positions.push_back(pos);
pos = envstr.find(input, pos + 1);
searchCount++;
}
cout << "\nThat phrase occurs a total of " << searchCount << " times.\n";
cout << "It occurs in the following lines: \n";
//output where that string occurs
for (vector<size_t>::iterator it = positions.begin(); it != positions.end(); ++it)
{
for (int i = *it; i < envstr.length() - 1 && checkChar(envstr[i]); i++)
{
cout << envstr[i];
}
cout << endl;
}
positions.clear();
} while (input != "END");
cin.get();
return 0;
}
First, your function checkChar() returns false when the parameter is a char, so if you want to print where that string occurs, it should be:
for (int i = *it; (i < envstr.length() - 1) && !checkChar(envstr[i]); i++)
{
cout << envstr[i];
}
Second, the code for counting words makes no sense and there is a potential out-of-bounds here: if (!checkChar(envstr[i])), I would suggest you to split the string using delimter '\', then do something.

C++ - Replacing "_" with a character

Using C++, I'm trying to make a hangman game to become better at using C++ and programming in general. Anyways, the issue I'm facing is that I'm not sure how to replace the dashes within a string with the letter the user has guessed.
I think my problem is with the fact the word chosen is randomly chosen from an array and I'm not sure how to go about finding the positions within the randomly chosen string which consists of the guessed character.
I have commented out the area that's causing the issue.
#include <iostream>
#include <array>
#include <string>
#include <stdlib.h>
#include <time.h>
#include <cstddef>
#include <algorithm>
using namespace std;
int main()
{
string words[3] = {"stack", "visual", "windows"};
string guess;
cout << "Welcome to hangman.\n";
cout << "\n";
srand(time(NULL));
int RandIndex = rand() % 3;
string selected = words[RandIndex];
for (int i = 1; i <= selected.size(); i++) {
cout << "_ ";
}
cout << "\n";
cout << "\nType in a letter: ";
cin >> guess;
cout << "\n";
if (selected.find(guess) != string::npos) {
/*for (int i = 1; i <= selected.size(); i++) {
if (selected.find(guess) != string::npos) {
cout << "_ ";
} else {
cout << guess << " ";
}
}*/
} else {
cout << "\nNay!\n";
cout << "\n";
}
cout << "\n";
cout << "\n";
system("PAUSE");
return 0;
}
I was thinking about using the replace() function but the problem I face here is that I'm not replacing the string within selected variable but sort of iterating through the word itself, if that made any sense whatsoever?
Use a second string, that is initialized with the underscores. If the find function doesn't return string::npos it returns the position in the string, and this is the same position you should change in the string with the underscores as well.
You actually need to use a second string to store the "guessed" string; this is because you need to keep track of all the guessed letters and display them.
something like :
string s ="test";
string t=""; //empty string
for(int i=0;i<s.size();i++)
t.append("_"); //initialize the guess string
cout<<t<<'\n';
char c;
cin >> c;
int pos = s.find(c); //get the first occurrence of the entered char
while(pos!=-1) //look for all occurrences and replaced them in the guess string
{
t.replace(pos,1,1,c);
pos = s.find(c, pos+1);
}
I think you need to maintain some extra state while looping - to keep track of which letters have / haven't been guessed.
You could add a new string current_state which is initially set to the same length as the word but all underscores. Then, when the player guesses a letter, you find all instances of that letter in the original word, and replace the underscore with the letter guessed, at all the positions found but in current_state.
First i would initialize a new string to show the hidden word:
string stringToDisplay = string( selected.length(), '_');
Then For each letter given by the user i would loop like this:
(assuming guess is letter)
size_t searchInitPos = 0;
size_t found = selected.find(guess, searchInitPos));
if (found == string::npos)
{
cout << "\nNay!\n";
cout << "\n";
}
while( found != string::npos)
{
stringToDisplay[found] = guess;
searchInitPos = found+1;
found = selected.find(guess, searchInitPos));
}
cout << stringToDisplay;
Hope this will help
I think it should be that:
string words[3] = {"stack", "visual", "windows"};
char guess;
string display;
cout << "Welcome to hangman.\n";
cout << "\n";
srand(time(NULL));
int RandIndex = rand() % 3;
string selected = words[RandIndex];
for (int i = 0; i < selected.size(); i++) {
display.insert(0, "_ ");
}
cout << display;
while(display.find("_ ") != string::npos) {
cout << "\n";
cout << "\nType in a letter: ";
cin >> guess;
cout << "\n";
bool flag = false;
for (int i = 0; i < selected.size(); i++) {
if (selected[i] == guess) {
display.replace(i*2, 1, 1, guess);
flag = true;
}
}
if (!flag) {
cout << "\nNay!\n";
cout << "\n";
} else {
cout << display;
}
}

How to remove punctuation characters from a char array?

My program prompts a user for a phrase to check if its a palindrome, then it's supposed to print out the phrase without capitalization or special characters like " ' , ? etc. My problem is erasing those characters. I've gotten my program to ignore them I'm asking how should I erase them? I made a comment where I think the statement should go. Example output should be: "Madam I'm Adam" to "madamimadam"
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
//Variables and arrays
int const index = 80;
char Phrase[index];
char NewPhrase[index];
int i, j, k, l;
bool test = true;
//Prompt user for the phrase/word
cout << "Please enter a sentence to be tested as a palindrome: ";
cin.getline(Phrase, 80);
//Make everything lowercase, delete spaces, and copy that to a new array 'NewPhrase'
for(k = 0, l = 0; k <= strlen(Phrase); k++)
{
if(Phrase[k] != ' ')
{
NewPhrase[l] = tolower(Phrase[k]);
l++;
}
}
//cout << "The Phrase without punctuation/extra characters: " << newPhrase[l];
int length = strlen(NewPhrase); //Get the length of the phrase
for(i = 0, j = length-1; i < j; i++, j--)
{
if(test) //Test to see if the phrase is a palindrome
{
if(NewPhrase[i] == NewPhrase[j])
{;}
else
{
test = false;
}
}
else
break;
}
if(test)
{
cout << endl << "Phrase/Word is a Palindrome." << endl << endl;
cout << "The Palindrome is: " << NewPhrase << endl << endl;
}
else
cout << endl << "Phrase/Word is not a Palindrome." << endl << endl;
system("Pause");
return 0;
}
Modify this line:
if(Phrase[k] != ' ')
To be:
if((phrase[k] != ' ') && (ispunct(phrase[k]) == false))
This means that we check for spaces and punctuation at the same time.
Also, consider rewriting this:
if(NewPhrase[i] == NewPhrase[j])
{;}
else
{
test = false;
}
As this:
if(NewPhrase[i] != NewPhrase[j])
test = false;
Here's suggestion:
Use an std::string
Use std::ispunct to determine whether a character in the string is a punctuation mark
Use the erase-remove idiom to remove punctuation
That is one line of code (plus one extra line for a convenience lambda):
std::string phrase = .....;
auto isPunct = [](char c) { return std::ispunct(static_cast<unsigned char>(c)); }
phrase.erase(std::remove_if(phrase.begin(), phrase.end(), isPunct),
phrase.end());
Next, for turning into lower case, from my answer to this recent question, another one-liner:
std::transform(phrase.begin(), phrase.end(), phrase.begin(),
[](char c)
{ return std::tolower(static_cast<unsigned char>(c));});