Comparing two string iterators always comes out true C++ - c++

So, here's a bit of an odd question that I'm really just having trouble with. I have a list of strings and I'm trying to see if two of them match. So, I have one iterate through and get each string, and another that checks if it has a match. However, it always says that the two are true - even when the first doesn't have a match in the list.
for(iterator = tagList.begin(); iterator != tagList.end(); ++iterator)
{
string theWord = *iterator;
string currentWord = *iterator;
if(currentWord[0] == '<' && currentWord[1] != '/')
{
bool matchFound = false;
list<string>::const_iterator it2;
for(it2 = (++iterator); it2 != tagList.end(); ++it2)
{
string temp = *it2;
if(currentWord.compare(temp) && temp != "")
{
fixedString += theWord + ' ';
matchFound = true;
cout << "A match was found... Current string: "
<< fixedString << endl;
cout << "\tthe matched word was " << *it2 << endl;
break;
}
}
if(!matchFound)
{
currentWord = *iterator;
currentWord = currentWord.substr(1, currentWord.size() - 2);
fixedString += currentWord;
cout << "No match was found... Current string: " << fixedString
<< endl;
}
}
}
Any ideas on why it's always true?

Your problem is with currentWord.compare(temp). string::compare() has a return type of int that will be 0 if they are equal (which evaluates to false) and a positive or negative numerical value if they are different (which evaluates to true).
You want:
if((currentWord.compare(temp) == 0) && temp != "") {
...
You can read about string::compare() here:
http://www.cplusplus.com/reference/string/string/compare/

Related

c++ reading user inputted char one by one symbol

So I have been searching, but couldn't exactly find a solution for the thing I want to do. Basically User input's a char like "asdasdasd" and I need to go thru each symbol to check if it's 'a', and need to stop the loop after it has reached the end of char. I got this far and it works, it output's the char symbols one by one, but in this case I can't stop the loop, I tried adding another char at the end and make it something specific like "." and use that to stop the loop but then I need to use char o[] which brakes the symbol by symbol thing going on there. Need help.. any input would be appreciated.
#include <iostream>
using namespace std;
int main(){
char o;
cout<<"input: "; cin>>o;
while(o!= '\0'){
cout<<o<<"\n";
cin >> o;
}
return 0;
}
When I understand your question correct you will input a string like "ahobansodfb" and search in there after a specific char? If yes, this is a little example:
#include <iostream>
using namespace std;
int main() {
string input;
char search;
int findPos = 0, countOfSearchedChars = 0;
cout << "input searched char: ";
cin >> search;
cout << "input string: ";
cin >> input;
while((findPos = input.find_first_of(search, findPos)) != string::npos){
cout << "Find searched char on pos: " << findPos << endl;
++findPos;
++countOfSearchedChars;
}
if(countOfSearchedChars == 0)
cout << "Char: " << search << " not found in: " << input << endl;
else
cout << "Char: " << search << " found: " << countOfSearchedChars << " time/s in string: " << input << endl;
}
Explanation for: while((findPos = input.find_first_of(search, findPos)) != string::npos)
input.find_first_of(search, findPos) find the first place where the searched char lies. When the char doesn't found it returns string::npos (18446744073709551615)
So we loop so long the return value is not string::npos: != string::npos
Edit to answer comment question:
Possibilities to iterate through a string:
std::string str = "aabaaba";
for(char& c : str) {
if(c == 'a'){
//it's a
} else if(c == 'b') {
//it's b
}
}
std::string str = "abaaba;
for(std::string::iterator it = str.begin(); it != str.end(); ++it) {
if(*it == 'a'){
//it's a
} else if(*it == 'b') {
//it's b
}
}
For every character in string
THANKS for all the answers!, you were big help, this code will do for me, going to go research what it does x.x
std::string str = "abaaba;
for(std::string::iterator it = str.begin(); it != str.end(); ++it) {
if(*it == 'a'){
//it's a
} else if(*it == 'b') {
//it's b
}
}

C++ Multiple delimiters with more than one char

In c++, I'm having trouble coding multiple delimiters with single char delimiters and string delimiters (e.g. "<=" as a delimiter as opposed to '='). The code below works with single char delimiters (I've set the delimiters as space, comma, dot, plus and equal) and separates the words in string line nicely. However, I don't know how to add string delimiters to this code.
std::string delimiters = " ,.+=";//I want "<=" added as a single delimiter
std::string line = "this+is,a.string=testing one";
std::size_t prev = 0, pos;
while ((pos = line.find_first_of(delimiters, prev)) != std::string::npos)
{
if (pos > prev)
{
cout << line.substr(prev, pos-prev) << endl;
prev = pos + 1;
}
}
if (prev < line.length()){
cout << line.substr(prev, std::string::npos) << endl;
}
Here is one way you could do it by erasing the delimiters you find from the line_copy string, having a special if statement for the special delimiter. Full example here:
auto pos = find_first_of(begin(line_copy), end(line_copy), begin(delimiters),
end(delimiters));
while (pos != line_copy.end()) {
if (pos != line_copy.end()) {
if (*pos == '<' && *(pos + 1) == '=') {
cout << "delimiter: \'";
cout << string(pos, pos + 2) << "\'" << endl;
// remove the delimiters from copy string
line_copy.erase(pos, pos + 2);
}
else {
cout << "delimiter: \'" << *pos << "\'" << endl;
// remove the delimiters from copy string
line_copy.erase(pos, pos + 1);
}
}
cout << endl;
pos = find_first_of(begin(line_copy), end(line_copy), begin(delimiters),
end(delimiters));
}
I would change the line
rev = pos + 1
in the following way:
if (pos > prev)
{
cout << line.substr(prev, pos-prev) << endl;
prev = line.find_first_not_of(delimiters, pos))
}
So once you hit a delimiter then you move to the fiurst char not being a delimiter.
Do a two character search one by one.
Search for "<" first and if found search for an immediate "=" if found, do substr otherwise continue searching.

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

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;
}

using str::find and find_first_of and last_of

Im not sure if I used find_first of and last_of correctly, but what I want to do is that I need to print error when it finds _ on the beginning or at the end of my code, plus when it finds two or more _ next to each other, like this lol___, lol__lol, _lol_, _lol, lol_, and one more rule, _ cannot be in front of capital letter, like this lol_Lol
here is my code
std::string::size_type n;
std::string::size_type n2;
std::string::size_type n3;
std::string const ss = slovo;
n = ss.find('_');
n2 = ss.find_first_of('_');
n3 = ss.find_last_of('_');
if (n2 == std::string::npos && n3 == std::string::npos) {
cout << "chyba" << endl;
}else if(n == std::string::npos){
string s = transform(slovo);
cout << s << endl;
}else{
string s = untransform(slovo);
cout << s << endl;
}
EDIT>
if ( !ss.empty() && ss.front() == '_' && ss.back() == '_' )
{
cout << "Chyba" << endl;
} else {
if ( ss.length() > 3 && ss.find( '__', 1, ss.length() - 2 ) != std::string::npos )
{
if (n == std::string::npos){
string s = transform(slovo);
cout << s << endl;
}else{
string s = untransform(slovo);
cout << s << endl;
}
}else{
cout << "chyba" << endl;
}
}
EDIT2:
cin >> slovo;
}
std::string::size_type n;
std::string const ss = slovo;
n = ss.find('_');
// kontrola podtrznika
if ( ss.empty() && ss[0] == '_' && ss[ss.length() - 1] == '_' )
{
cout << "chyba" << endl;
}
if ( ss.length() > 3 && ss.find( "__", 1, ss.length() - 2 ) != std::string::npos )
{
cout << "chyba" << endl;
}
if (n == std::string::npos)
{
string s = transform(slovo);
cout << s << endl;
}else{
string s = untransform(slovo);
cout << s << endl;
}
if those functions return npos it means the character couldn't be found in the string. So if one of them returns that, all 3 of them will.
So this code outputs 'chyba' it there's no _ in the string or calls untransform otherwise. From your description, that's not what you intend.
You really need to scan through the string for all those conditions. And if you want to check the first and last characters of the string, use ss[0] and ss[ss.length() - 1] (taking appropriate care you don't have a string of length 0 or 1).
It is obvious that the two function calls will give you the same result
n = ss.find('_');
n2 = ss.find_first_of('_');
In this context they are equivalent.
If I have understood you correctly you need to determine whether the first and the last characters in a string are underscores and whether the string contains two adjacent undescores within itself.
To determine the first case it is simple to write
if ( !ss.empty() && ss.front() == '_' && ss.back() == '_' )
{
//...
}
To find at least two adjacent underscores excluding the first and the last characters you can write
if ( ss.length() > 3 && ss.find( "__", 1, ss.length() - 2 ) != std::string::npos )
{
//...
}

Why this while loop executes twice before asking for name

I have a function which validates a user's first and last name. However, the while loop executes twice, and I can't find out why.... any help
string getName()
{
string name = "";
bool stop = false;
string::iterator it;
while(!stop)//name validation loop
{
cout << "enter name: ";
getline(cin, name);
for(it = name.begin(); it < name.end(); it++)
{
if(tolower(*it) > 'z' || tolower(*it) < 'a' && tolower(*it) != ' ')
{
cout << "Error, only letters! \n";
break;
}
if(it == name.end()-1) { stop = true; }
}
cout << "here\n";
}
return name;
}
It may happen if there is still some newspace character in cin buffer. std::ws extracts white spaces like newline character, space, tabulator from stream before right text. Try that:
string getName()
{
string name = "";
bool stop = false;
string::iterator it;
while(!stop)//name validation loop
{
cout << "enter name: ";
std::cin >> std::ws; // <--- drop whitespaces
getline(cin, name);
for(it = name.begin(); it < name.end(); it++)
{
if(tolower(*it) > 'z' || tolower(*it) < 'a' && tolower(*it) != ' ')
{
cout << "Error, only letters! \n";
break;
}
if(it == name.end()-1) { stop = true; }
}
cout << "here\n";
}
return name;
}
There are a few problems with your loop and this is how I'd rewrite it, keeping it as similar to your implementation as possible:
string getName()
{
bool stop;
string name;
string::iterator it;
do {
stop = true;
cout << "enter name: ";
getline(cin, name);
for(it = name.begin(); it < name.end(); it++)
{
if( (tolower(*it) > 'z' || tolower(*it) < 'a') && tolower(*it) != ' ' )
{
cout << "Error, only letters! \n";
stop = false;
break;
}
}
cout << "here\n";
} while (!stop);
return name;
}
With what you had here:
if(tolower(*it) > 'z' || tolower(*it) < 'a' && tolower(*it) != ' ')
Due to && having higher precedence, it equates to:
if(tolower(*it) > 'z' ||(tolower(*it) < 'a' && tolower(*it) != ' '))
which is not what you want.
EDIT: since ' ' (space) is < 'a' your code won't actually cause problems, but I'm not sure you did it like that on purpose.
I also don't like this: if(it == name.end()-1) { stop = true; }, and a do...while loop is better suited.
EDIT: You might also want to add a check for empty input (all whitespace), since that would seem an invalid name.
EDIT(again): Loki's right, you must have junk on the input stream before calling getName. You can use Mścisław's solution or cin.ignore().