Searching substrings - c++

I am a programming student. I have been asked to write a program that searches for a substring of another string, but I am not suppose to use the find() function that is provided in the string class. The code I have written thus far works, but it uses the find() function. How can I change this to not use the find function and still give me the location of the substring? Here is my code:
#include <iostream>
#include <string>
using namespace std;
int f_r(string, string);
int main()
{
string s;
string t;
cout << "\nEnter the string to be searched: ";
getline(cin,s);
cout << "Now enter the string you want to search for: ";
cin >> t;
if (f_r(s,t) == 0)
{
cout << "\n Substring could not be found.";
}
else
{
cout << "\nThe index of substring is = " << f_r(s,t) << endl;
}
system("PAUSE");
return 0;
}
int f_r(string str, string c)
{
int pos = 0;
pos = str.find(c, pos);
if (pos > str.length())
{
return 0;
}
else
{
pos++;
return pos - 1;
}
}

You need to search for matches within the string ONE character at a time, i.e. seeing the strings as if they were arrays of characters (since you're apparently working in C/C++ that is quite convenient since string and char[] are synonymous).
You will likely need to maintain indexes or pointers into the current location in both strings..
This will be the naive / initial approach, and when you get that working rather well, assuming you are a bit curious, you'll start wondering if there are more efficient ways of doing so, for example by skipping some characters in some cases, or by using general statistics about text in the underlying languages.

This art may help:
|_|_|_|_|_|_|_|_|_|_|_|
^ ^
i i+j
|
|_|_|_|_|
^
j

int search(char *a,char *b)
{
int i=0,j=0,k=0,m,n,pos;
m=strlen(a);
n=strlen(b);
while(1)
{
while((a[i]==b[j]) && b[j]!=0)
{
i++;
j++;
}
if (j==n)
{
pos=i-j;
return(pos);
}
else
{
i=i-j+1;
j=0;
}
}}
I have this code with me. I hope it will help you.
Note:- its an old code

Related

Finding a Pair of character in a string [duplicate]

This question already has answers here:
Counting the number of occurrences of a string within a string
(5 answers)
Closed 2 years ago.
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;
cin >> t;
while(t--){
int count = 0;
vector<string> v;
string resp;
cin >> resp;
v.push_back(resp);
for(int i = 0; i < v.size(); i++){
if(find(v.begin(), v.end(), "xy") != v.end()){
count++;
}
cout << count << endl;
}
return 0;
}
I want to find the character "xy" in the string for multiple test cases.
For input xy, my count value outputs correctly as 1.
But for the input xyxxy instead of 2 it gives the value as 0
It is only finding the value once but i want to check the count of xy in whole string
I tried to use the substring function as well but it failed to work
I don't get the idea of while loop but that worked for me.
#include <iostream>
#include <vector>
int main()
{
std::string str;
std::cin >> str;
int count = 0;
for (int i(0); i < str.size()-1; ++i)
{
if ((str[i] == 'x') && (str[i + 1] == 'y'))
{
++count;
}
}
std::cout << count;
}
You're looking for "xy" within a vector of strings, which in your example, has a single element, "xyxxy". Since "xy" is not equal to "xyxxy", you're not finding any matches.
But even if you tried to std::find "xy" within "xyxxy" itself - that would fail too, since std::find looks for a single element within a range (or rather, iterator pair).
Instead, you can use the string::find() method, as described here; or, as the case may be, std::string_view::find():
#include <string>
#include <vector>
#include <iostream>
#include <string_view>
int main() {
const std::string needle{"xy"};
std::string haystack;
std::cin >> haystack;
std::size_t count{0};
std::string_view remainder{haystack};
while(true) {
auto first_pos = remainder.find(needle);
if (first_pos == std::string_view::npos) { break; }
count++;
remainder = remainder.substr(first_pos+needle.length());
}
std::cout << "Found " << count << " occurrences of \"" << needle << "\"\n";
}
Note: This does not account for overlapping occurrences. If you want those, you could either always increase the starting position by just 1; or make your solution more complex by employing something Boyer-Moore or Knuth-Morris-Pratt search (see String search algorithms), and resuming it at the correct state after each occurrence found.

Trouble with strings and arrays

My goal is to make a program that inputs a phone number and outputs it in a standard format. It skips over any non-number characters, will output if there are not enough digits, and will also skip over any digits after the first ten digits. My raptor worked without a hitch, but it's been difficult to translate it to C++.
I am using Microsoft Visual Studio.
The problem is it is not running. If I put in anything more then one number in, I receive a fail error.
I am having some difficulty running this code.
Any and all help and advice would be greatly appreciated.
#include <iostream>
#include <string>
using namespace std;
void format(char outArray[], string inNumber)
{
outArray[0] = '(';
outArray[4] = ')';
outArray[5] = ' ';
outArray[9] = '-';
outArray[1] = inNumber[0];
outArray[2] = inNumber[1];
outArray[3] = inNumber[2];
outArray[6] = inNumber[3];
outArray[7] = inNumber[4];
outArray[8] = inNumber[5];
outArray[10] = inNumber[6];
outArray[11] = inNumber[7];
outArray[12] = inNumber[8];
outArray[13] = inNumber[9];
}
int main()
{
string phone, inNumber;
cout << "Please enter a phone number: ";
cin >> phone;
int index = 0;
int num = 0;
char outArray[14];
for (index; phone[index] >= '0' && phone[index] <= '9'; index++)
{
inNumber[num] = phone[index];
num++;
}
if (inNumber.size() > 10)
{
format(outArray, inNumber);
cout << "The properly formatted number is: ";
cout << outArray;
}
else {
cout << "Input must contain at least 10 digits." << endl;
}
system("pause");
return 0;
}
A few things to note:
Use std::string instead array of char array.
You do not need to check charters using a for loop unless you are not sure about the input(phone). However, if that's the case, use std::getline() to get the input and parse as follows using a range-based for loop.
You can use std::isdigit to check the character is a digit.
My goal is to make a program that inputs a phone number and outputs it
in a standard format. It skips over any non-number characters, will
output if there are not enough digits, and will also skip over any
digits after the first ten digits.
That means the number should have a minimum length of 10. Then the
if statement should be if (inNumber.size() >= 10)
Need a pass by ref call in the function format(), since you want to change the content of outArray. Additionally, inNumber could be a
const ref, since we do not change this string.
Updated code: (See a sample code online)
#include <iostream>
#include <string>
#include <cstddef> // std::isdigit, std::size_t
void format(std::string& outArray, const std::string& inNumber) /* noexcept */
{
for (std::size_t index = 0; index < 10; ++index)
{
if (index == 0) outArray += '(';
else if (index == 3) outArray += ") ";
else if (index == 6) outArray += '-';
outArray += inNumber[index];
}
}
int main()
{
std::string phone;
std::cout << "Please enter a phone number: ";
std::getline(std::cin, phone);
std::string inNumber;
for (char letter : phone)
if (std::isdigit(static_cast<unsigned char>(letter))) // check the letter == digits
inNumber += letter;
if (inNumber.size() >= 10)
{
std::string outArray;
format(outArray, inNumber);
std::cout << "The properly formatted number is: ";
std::cout << outArray;
}
else {
std::cout << "Input must contain at least 10 digits." << std::endl;
}
return 0;
}
inNumber[num] = phone[index]; //undefined behavior.
You cannot subscript inNumber now, since its capacity is 0, thus it can not store or access any element here.
You may need to use string's constructor whose parameter has a size_t type or string::reserve or string::resize.
And I'm happy to see cppreference get more complete now, learn to use it: http://en.cppreference.com/w/cpp/string/basic_string
BTW, this function won't do anything you want to:
void format(char outArray[], string inNumber)
maybe you'd like to have an signature like this?
void format(char outArray[], string& inNumber)

Anagram generator for C++ (not using STL)

I am trying to create an anagram solver just using a very basic, procedural approach. I am finding out that I probably should have done this using classes, but now it is too late and my assignment is about due. Any suggestions on how to figure this out would be great!
Basically, this is what the algorithm should do:
Get all words in the dictionary; store them in a container
Get a word from the user; quit if appropriate
Get all permutations of the word that the user entered
Strip the word the user entered from the permutations
Strip all words in the permutation collection that aren't also in the dictionary I collected in part 1
Now for the last step, I must make sure that I don't display duplicate anagrams (i.e. anagrams which contain the same letter, such as "loop"). I cannot seem to get this check to work, which is noted below with under the TODO comment block.
Any suggestions would be awesome!!
#include <iostream>
#include <fstream>
#include <string>
//
// Change size below to accomodate more anagrams and dictionary words
//
#define MAX_ANGM_SIZE 4096
#define MAX_WORD_SIZE 1048576
using namespace std;
//
// Determines whether anagram is valid or not; will not display word
// which user entered or words not contained in dictionary
//
bool isValidAnagram(string word, string userWord,
string dictionary[], unsigned int listIdx)
{
for(unsigned int idx = 0; idx < listIdx; ++idx)
{
if(word == userWord)
return false;
else if (word == dictionary[idx])
return true;
}
return false;
}
//
// Determines whether user's word is contained in the dictionary
// or not
//
bool isValidWord(string word, string dictionary[],
unsigned int listIdx)
{
for(unsigned int idx = 0; idx < listIdx; ++idx)
{
if(word == dictionary[idx])
return true;
}
return false;
}
//
// TODO:This function should test for duplicate anagrams and return
// true if duplicates are found.
//
bool isRepeated(string anagrams[], unsigned int anaIdx)
{
for(unsigned int idx = anaIdx; idx != 0; --idx)
{
if(anagrams[idx] == anagrams[anaIdx])
return true;
else
return false;
}
return false;
}
//
// Only display elements in array which aren't blank and don't
// display duplicate anagrams; notify user if no anagrams
// were found.
//
void displayAnagrams(string anagrams[], unsigned int next)
{
int flag = 0;
for (unsigned int idx = 0; idx < next; ++idx)
{
if((anagrams[idx] != "") || (!(isRepeated(anagrams, idx))))
{
if(idx == 1)
cout << " Anagrams: ";
if(idx > 0)
flag = 1;
cout << anagrams[idx] << " ";
}
else
continue;
}
if(flag == 0)
cout << " no anagrams found" << endl;
}
static void swap(char &c1, char &c2)
{
char temp = c1;
c1 = c2;
c2 = temp;
}
//
// Pass in word to be altered, the userWord for comparison, the array to store
// anagrams, the dictionary for comparison, the count for the number of anagrams
// and the count for number of dictionary words
//
static void permute(string word, string userWord, int k, string anagrams[],
string dictionary[], unsigned int &next, unsigned int listIdx)
{
if(k == word.length()-1)
{
if(isValidAnagram(word, userWord, dictionary, listIdx))
anagrams[next] = word;
++next;
}
else
{
for(int idx = k; idx < word.length(); ++idx)
{
swap(word[k], word[idx]);
permute(word, userWord, k+1, anagrams, dictionary, next, listIdx);
}
}
}
//
// Create container to store anagrams, validate user's word in dictionary, get all
// of the anagrams, then display all valid anagrams
//
void getAnagrams(string word, string dictionary[], unsigned int listIdx)
{
string anagrams[MAX_ANGM_SIZE];
unsigned int next = 0;
if(isValidWord(word, dictionary, listIdx))
{
permute(word, word, 0, anagrams, dictionary, next, listIdx);
}
else
{
cerr << " \"" << word << "\"" << " is not a valid word" << endl;
return;
}
displayAnagrams(anagrams, next);
}
//
// Read in dictionary file, store contents of file in a list, prompt
// the user to type in words to generate anagrams
//
int main()
{
string file;
string word;
string quit = "quit";
string dictionary[MAX_WORD_SIZE];
unsigned int idx = 0;
cout << "Enter a dictionary file: ";
cin >> file;
cout << "Reading file \"" << file << "\"" << endl;
cout << endl;
ifstream inFile(file.c_str());
if(!(inFile.is_open()))
{
cerr << "Can't open file \"" << file << "\""
<< endl;
exit(EXIT_FAILURE);
}
while(!inFile.eof())
{
inFile >> dictionary[idx];
++idx;
}
inFile.close();
while(true)
{
cout << "Enter a word: ";
cin >> word;
if(word == quit) break;
getAnagrams(word, dictionary, idx);
cout << endl;
}
return 0;
}
You may want to rethink your step (3). If the user enters a 12-letter word you have 479,001,600 permutations of it which will probably be impractical to assemble all at once (and if that's not, then a 16-letter word will be...).
Instead, try thinking about how you could store the words and look up potential anagrams in a way that doesn't require you to do that.
Edit: I get that ability to solve largeish words may not be your biggest concern at this point, but it might actually make your fourth and fifth steps easier if you do them by assembling the set of valid words rather than starting with all possibilities and removing all the ones that don't match. 'Removing' an item from an array is a bit awkward since you have to shuffle all the following items up to fill in the gap (this is exactly the kind of thing that STL manages for you).
Better algorithm : don't store your word, but store a tupple containing (your word, sorted letters). Moreover, you sort that big storage by the second key (hint, you could use a sqlite database to do the work for you and use an index (can't be unique!))
E.g. to store
"Florent", "Abraham","Zoe"
you would store in memory
("aaabhmr", "abraham"),("eflnort","florent"),("eoz","zoe")
When you got your word from your user, you just use same "sorting letter inside word" algorithm.
Then you look for that pattern in your storage, and you find all anagrams very quickly (log(size of dictionary)) as it's sorted. Of course, original words are the second elements of your tuple.
You can do that using classes, standard structures, a database, up to you to choose the easiest implementation (and the one fitting your requirements)

Using vectors to bleep some predefined strings

So i'm currently doing the exercices in my programming book "Programming: Principles and practice using c++" from Bjarne Stroustrup and i'm curently stuck at one exercice. Basically, the exercice is to write a program that bleeps out words it doesn't like. The way it works is that the user inputs a string and the program repeats the word. If the word the user enters is part of the dislike vector, the word is replaced by "Bleep". (I don't know if I explained this right, but it shouldn't be to complicated to understand).
This is my version of the program:
int main()
{
string dislike = "Potato";
string words = " ";
cout << "Please enter some words: " << endl;
while(cin>>words)
{
if(words==dislike)
{
cout << "Bleep!" << endl;
}
else
{
cout << words << endl;
}
}
system("pause");
return 0;
}
As you can see, this version isn't using vectors (and it should, because the exercice is right after the explanation of vectors in the chapter). So my question is, how can I implement a vector with many "dislike" words in it like this:
vector<string>dislike;
dislike.push_back("Potatoes");
dislike.push_back("Peanuts");
dislike.push_back("Coconut");
and make it so it works like my other version without vectors (repeats words, but bleeps the dislike words). I can't seem to understand how to navigate in a vector so that it only bleeps the "dislike" words.
If someone could give me a hand and explain to me how it works (please do not just give me the answer) it would be very appreciated.
Thank you for your time and help, learning c++ alone isn't always simple, and I thank this website for making my learning curve a bit easier.
bobicool
Ok, let me explain a simple approach to it. There are more elegant ones, but for now it's important that you get a feeling of how std::vector can be accessed and how to compose control structures correctly.
Step 1 - looping through all elements of a vector
You can use iterators to go through all elements of a vector.
for(vector<string>::const_iterator it = dislike.begin(); it != dislike.end(); ++it) {
// now *it gives access to the current element (here: current dislike word)
if (*it == words) {
// ... yeah, we found out the current word is on the list!
}
}
You get an iterator to the first element in a vector by calling begin(), then keep incrementing (++it) it until you reached the end of the vector. I use const_iterator here because I'm not going to modify any elements, if you need to, use iterator.
with a std::vector, indexing via [index] is also possible (but not recommended, usually):
for(size_t i = 0;i < dislike.size(); ++i) {
// dislike[i] is the current element
if (dislike[i] == words) {
// huuuuray! another BEEEP candidate
}
}
Step 2 - break the loop early
As soon as you know what for sure that we have a dislike word, you don't need to search the vector further.
for(vector<string>::const_iterator it = dislike.begin(); it != dislike.end(); ++it) {
if (*it == words) {
// we found a positive match, so beep and get out of here
cout << "Bleep!" << endl;
break;
}
}
Step 3 - make a note if we handled a word already
bool is_beep = false;
for(vector<string>::const_iterator it = dislike.begin(); it != dislike.end(); ++it) {
if (*it == words) {
// we found a positive match, so beep and get out of here
cout << "Bleep!" << endl;
is_beep = true;
break;
}
}
// this is not a dislike word if is_beep is false, so print it as usual
if (!is_beep) {
cout << words << endl;
}
Step 4 - putting it all together
int main()
{
vector<string>dislike;
dislike.push_back("Potatoes");
dislike.push_back("Peanuts");
dislike.push_back("Coconut");
string words = " ";
cout << "Please enter some words: " << endl;
while(cin>>words)
{
bool is_beep = false;
for(vector<string>::const_iterator it = dislike.begin(); it != dislike.end(); ++it) {
if (*it == words) {
// we found a positive match, so beep and get out of here
cout << "Bleep!" << endl;
is_beep = true;
break;
}
}
// this is not a dislike word if is_beep is false, so print it as usual
if (!is_beep) {
cout << words << endl;
}
}
system("pause");
return 0;
}
Check out std::find for a more idiomatic solution - it basically saves you the inner loop. You can also get rid of that bool in the last code sample if you re-structure a bit. I'll leave that as an exercise to you (hint: keep the iterator alive and check out its value after terminating the loop).
int main()
{
vector<string> dislike;
dislike.push_back("Potatoes");
dislike.push_back("Peanuts");
dislike.push_back("Coconut");
string words;
cout << "Please enter some words: " << endl;
while(cin >> words)
{
if(find(dislike.begin(), dislike.end(), words) != dislike.end())
{
cout << "Bleep!" << endl;
}
else
{
cout << words << endl;
}
}
system("pause");
return 0;
}
For std::find add #include <algorithm> to your source.
use std::find(your_vector.begin(), your_vector.end(), words)
int main()
{
vector<string>dislike;
dislike.push_back("Potatoes");
dislike.push_back("Peanuts");
dislike.push_back("Coconut");
string words = " ";
cout << "Please enter some words: " << endl;
while(cin>>words)
{
if(std::find(dislike.begin(), dislike.end(), words) != dislike.end())
{
cout << "Bleep!" << endl;
}
else
{
cout << words << endl;
}
}
system("pause");
return 0;
}
Here is my solution to that particular question in the book when i was reading it. :) hope it's self-explanatory.
/*THE QUESTION GOES LIKE;
Write a program that “bleeps” out words that you don’t like; that is, you read in words
using cin and print them again on cout. If a word is among a few you have defined, you
write out BLEEP instead of that word. Start with one “disliked word” such as string
disliked = “Broccoli”;
When that works, add a few more.*/
#include "std_lib_facilities.h" // this is a standard library header that came with
the book
int main () {
vector<string> dislike = {"Dislike", "Alike", "Hello", "Water"}; /* defining a vector
for the disliked words. */
vector<string> words; //initializing vector for the read words.
cout << "Please enter some words\n"; //prompt user to enter some words.
for( string word; cin >> word;) //this current word typed is read in.
words.push_back(word); // word read in are pushed into the vector "words".
sort(words); /* function for the standard library for sorting data...this makes the data from the vector "words" appears in alphabetical order. */
for (int i=0; i<words.size(); ++i){ /*this acts as an iterator. and goes through all the element of the vector "words". */
if(i==0 || words[i-1]!=words[i]){ /*this prevents the words from repeating....just an option incase the user enters same kinda words twice or more. */
if(words[i]!=dislike[0] && words[i]!=dislike[1] && words[i]!=dislike[2] && words[i]!=dislike[3]) /*This test checks whether the words typed match any of the elements of the vector "dislike".if they don't match; */
cout << words[i]<< '\n'; //prints out the words.
else
cout << "BlEEP!\n"; //if they match....print out "BlEEP!".
}
}
}
I am learning C++. This Program has been changed some.
Write a program that "bleeps" out bad words that you don't like; that is,
you read in words using cin and print them again on cout. If a word is among a few you have defined, you write out BLEEP and or have it to BLEEP(Sound) instead of that word. Start with one "bad word" such as -- string badword = "arse"; When that works, add a few more or write a whole program based on all the bad words that you do not want printed out.
while (cin >> words)
{
if(find(badwords.begin(), badwords.end(),words) !=badwords.end())
{
cout << " " << endl; // You can put Bleep in or leave it out (Blank) if blank
// it will leave a blank in the phrase when it prints
Beep(523,500); // This is to Bleep (Sound) when a bad word is found
cin.get();
}
else
{
cout << words << endl;
}
}
Since someone gave the answer I have Changed the program some. That is for you to learn.
This runs on Visual Studio Express 2012
I have solved this problem using the ideas that have already been learned in the previous chapters, not going beyond what you understand.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<string> disliked;
//adding disliked words to the vector
disliked.push_back("dog");
disliked.push_back("cat");
disliked.push_back("goat");
disliked.push_back("cow");
disliked.push_back("sheep");
disliked.push_back("pig");
string words=""; //this variable will store the input from the user.
while(cin>>words)
{//test every entered word to see if it's equal to any word listed in disliked words.
if(words==disliked[0] ||//or
words==disliked[1] ||//or
words==disliked[2] ||//or
words==disliked[3] ||//or
words==disliked[4] ||//or
words==disliked[5]){
cout<<"Bleeps";}
else{
cout<<words;}
}
return 0;
//Not that I have not gone beyond what has been covered in the previous chapters.
//I know their are beautiful solutions to this problem.
//Keep learning you will know everything.
}
This question was asked a long, long time ago so the author is probably professional at this point lol, but here is simpler yet working solution for anybody who is looking for the same answer. I am learning from the beginning through Bjarne book so im not yet "affected" with higher knowledge to confuse you with but with solutions that are good enough to work based on how far we are in the book. :)
// program that bleeps out words we dont like
vector <string> words;
vector <string> bwords = {"this", "that", "then"}; //bleeped words
string sword; // temporary word
cout << "Enter few words: ";
for (string tword; cin >> tword;) // read in words
words.push_back(tword);
//check if they match beeped words
cout << "\n\nWords:\n";
for (int i = 0; i < words.size(); i++) //take word[i] from the vector
{
sword = words[i]; // temporary variable is now word[i]
for (int j = 0; j < bwords.size(); j++) // take beeped word[j] from saved words
{
if (words[i] == bwords[j]) // is word[i] same as bleeped word[j]
sword = "BLEEP"; // if word[i] is same then replace sword with BEEP
}
cout << sword << "\n"; // now we checked first word and if it matches with any of the bleeped words then it will cout bleep, otherwise it will cout first word.
}
Now in this example you can add many new bleeped words and you wont need to change the code.
This is not the best solution in "real life" programming, but at this point in the book we learned for, if, vector(not a lot of it), cout, cin.. etc so anything else just looks confusing..until this point we dont know yet about using :: , begin, true/fals, cin.get or anything like that.
//Josef.L
//2019/7/11
int main(void){
vector <string> inpute;
for(string pat; cin >>pat;){
inpute.push_back(pat);
}
for(int i=0; i < inpute.size(); i++){
if("work"== inpute[i]){
cout<<"bleep! "<<endl;}
else if("life" == inpute[i]){
cout<<"bleep! "<<endl;
}
else if("broccoli" == inpute[i]){
cout<<"bleep! "<<endl;
}
else if("homework" == inpute[i]){
cout<<"bleep! "<<endl;
}
else{
cout <<inpute[i]<<endl;
}
}
return 0;}
//However, the entire source code is too long and boring, so there should be an improvement.
That's my solution, where you can add as many words as you want without changing the code.
#include "std_lib_facilities.h"
int main()
{
vector<string> dislike;
dislike.push_back("Potatoes");
dislike.push_back("Peanuts");
dislike.push_back("Coconut");
vector<string> words;
for (string temp_word; cin >> temp_word; )
{
for (int i = 0; i < dislike.size(); ++i)
{
if (temp_word == dislike[i])
{
words.push_back("BLEEP");
break;
}
else if (i == dislike.size() - 1 && temp_word != dislike[dislike.size() - 1])
{
words.push_back(temp_word);
break;
}
}
}
for (string temp_word : words)
{
cout << temp_word << ' ';
}
keep_window_open();
}
“Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains.” ― Steve Jobs
#include "std_lib_facilities.h"
int main()
{
vector<string>disliked;
disliked.push_back("Apple");
disliked.push_back("OliveOil");
disliked.push_back("Strawberry");
disliked.push_back("Lemon");
cout<<"Please type some words:"<<"\n";
string words=" ";
while(cin>>words)
{
if (words==disliked[0] | words==disliked[1]|
words==disliked[2] | words==disliked[3])
{cout<<"BLEEP"<<"\n";}
else{cout<<words<<"\n";}
}
keep_window_open();
}

Palindrome program isn't comparing properly

I'm currently learning about vectors and trying to make a palindrome program using them. This is a simple program and so far, I'm trying to make it identify "I am what am I." as a palindrome properly. This is my program so far:
#include <vector>
#include <string>
#include <iostream>
using namespace std;
vector <string> sentVec;
void getSent(string sent);
void readBackwards(string sent);
int main()
{
string sent;
getSent(sent);
readBackwards(sent);
return 0;
}
void getSent(string sent)
{
cout << "Enter your sentence:" << endl;
getline (cin,sent);
string currentWord, currentLetter;
for (int i = 0; i < sent.length(); i++)
{
currentLetter = sent[i];
if (currentLetter == " ") // inserts word
{
currentWord += sent[i];
sentVec.push_back(currentWord);
currentWord = "";
}
else if (currentLetter == ".") // inserts period
{
sentVec.push_back(currentWord);
currentWord = sent[i];
sentVec.push_back(currentWord);
}
else
{
currentWord += sent[i];
}
}
}
void readBackwards(string sent)
{
string sentForwards, sentBackwards;
// create sentence forwards and backwards without the period.
for (int i = 0; i < sentVec.size() - 1; i++)
{
sentForwards += sentVec[i];
}
for (int j = sentVec.size() - 2; j >= 0; j--)
{
sentBackwards += sentVec[j];
if (j == sentVec.size() - 2)
{
sentBackwards += " ";
}
}
cout << "Sentence forwards is: " << sentForwards << endl;
cout << "Sentence backwards is: " << sentBackwards << endl;
if (sentForwards == sentBackwards)
{
cout << "This sentence reads the same backwards as forwards." << endl;
}
else
{
cout << "This sentence does not read the same backwards as forwards." << endl;
}
}
When I run this program, it prints:
Enter your sentence:
I am what am I.
Sentence forwards is: I am what am I
Sentence backwards is: I am what am I
This sentence does not read the same backwards as forwards.
Why does this not trigger the if loop when comparing the two sentences?
Because sentBackwards isn't the same as sentForwards, because sentBackwards has a trailing whitespace at the end, and thus they aren't the same.
I am unsure how your program detects palindromes, but here is a simple iterative method:
#include <string>
bool isPalindrome(std::string in) {
for (int i = 0; i < in.size() / 2; i++) {
if (in[i] != in[in.size() - 1 - i]) {
return false;
}
}
return true;
}
It returns true if the string passed as an argument is a palindrome
You should not only learn about vector, but also the STL algorithm functions such as std::reverse.
As the other answer given pointed out, one vector has a trailing whitespace. You could have avoided all of that by simply taking the original vector, copying it to another vector, and calling std::reverse. There is no need to write a loop:
void readBackwards()
{
// copy the vector
std::vector<std::string> sentBackwards = sentVec;
// reverse it
std::reverse(sentBackwards.begin(), sentBackwards.end());
// see if they're equal
if (sentVec == sentBackwards)
cout << "This sentence reads the same backwards as forwards." << endl;
else
cout << "This sentence does not read the same backwards as forwards." << endl;
}
This works, since std::vector has an overloaded operator == that compares the items in each of the two vectors and returns true if all items are the same.
In addition to this, reading into a vector can be accomplished much more easily than what you attempted.
#include <sstream>
#include <algorithm>
//...
void getSent(string sent)
{
// remove the periods(s)
auto iter = std::remove_if(sent.begin(), sent.end(), [] (char ch) { return ch == '.';});
sent.erase(iter, sent.end());
// copy the data to a vector
std::istringstream iss(sent);
string currentword;
while ( iss >> currentword)
sentVec.push_back(currentword);
}
Note that we use the std::istringstream to serve as the space delimited parser, alleviating the need to write a loop looking for the space. Also, the std::remove_if algorithm is used to remove any period characters from the string before we start to store the individual strings into a vector.
So basically, the only loop in this whole setup is the while to read from the stream into the vector. Everything else is accomplished by using the algorithm functions, and taking advantage of the various member functions of std::vector (like the overloaded ==)