Below is a palindrome function and a helper function that implements a reverse operation. For some reason, even though the types appear to be the same, the if comparision statement never evaluates to true. Both variables s and comp seem to be strings, and I even tried calling stoi() on both to turn them into ints but comp for some reason throws an error:
terminate called after throwing an instance of 'std::invalid_argument'
what(): stoi
Aborted (core dumped)
I'm not sure what the problem is.
bool palindrome (int n)
{
string s = to_string(n);
cout << s << endl;
string comp = rev(s);
cout << comp << endl;
if (s == comp)
{
cout << s << " " << comp << endl;
return 1;
}
return 0;
}
string rev (string &s)
{
string return_string("");
for (string::iterator it = s.end(); it != (s.begin() - 1); it--)
{
return_string += *it;
}
return return_string;
}
Your rev function has two errors. First, it computes (s.begin() - 1). Second, on its first iteration it dereferences s.end(). Both are undefined behavior.
You'll have fewer problems using reverse iterators:
string rev( const string& s )
{
string return_string;
for ( auto it = s.rbegin(); it != s.rend(); ++it )
{
return_string += *it;
}
return return_string;
}
for (string::iterator it = s.end(); it != (s.begin() - 1); it--) is certainly wrong. In the first iteration, you'll be dereferencing s.end(), and then one before s.begin() . This is undefined behavior (even s.begin() - 1 is).
Use reverse iterators:
for(auto it = s.rbegin(); it != s.rend(); ++it)
for (string::iterator it = s.end(); it != (s.begin() - 1); it--)
{
return_string += *it;
}
end() points one beyond the end of the container, so when you dereference it you are accessing memory you don't own.
Also, trying to access more memory you don't own by decrementing begin() to an address before the start of your container.
Try using a reverse iterator, reverse end and reverse begin, like so:
string rev(const string &s)
{
string return_string("");
for (string::const_reverse_iterator rit = s.rbegin(); rit != s.rend(); ++rit)
{
return_string += *rit;
}
return (return_string);
}
Related
void rev(string& str)
{
for (auto i = str.end() -1; i != str.begin() -1; i--)
cout << *i;
cout << '\n';
}
The code above works on my system however str.begin() -1 invokes undefined behaviour as per the standard. So what is the idiomatic way of reverse traversal using iterator's but not reverse_iterator's?
This works
for (auto i = str.end(); i != str.begin(); )
{
--i;
...
}
Segmentation fault is throw in the below code.
Counting total no of duplicate char As examples
input:
helloWorld
output:
l = 3
o = 2
steps
Loop input string
search for each char
count on found
del the counted char
Below is my code
#include<iostream>
#include<string>
#include<bits/stdc++.h>
#include <algorithm>
int main()
{
std::string str;
std::cin>>str;
int cout = 0;
std::string::iterator it1,it2;
for(it1 = str.begin() ; it1!=str.end(); ++it1)
{
for(it2 = str.begin() ; it2!=str.end(); ++it2)
{
if(*it1==*it2)
{
++cout;
continue ;
}
}
if(cout >1)
{
std::cout<<*it1<<"="<<cout<<"\n";
if(!str.empty() && str.find(*it1))
str.erase(std::remove(str.begin(), str.end(), *it1), str.end()); // remove char once count done
}
cout=0;
}
}
Your iterators it1 and it2 are being invalidated when you adjust the string str.
Don't do it like that. Use indexes into the std::string (of std::size_t types) instead.
(I'd solve this using an container foo say of int of size CHAR_MAX - CHAR_MIN + 1, initialised to zero, which is such that foo[i] is the number of times character i occurs. This can be populated in O(N), and the output stage is particularly trivial: see Can the Duplicate Characters in a string be Identified and Quantified in O(n)?)
Use c++'s built in functionality. By using sort and adjacent_find to do this in O(n log n) time:
sort(begin(str), end(str));
for(auto start = adjacent_find(cbegin(str), cend(str)), finish = upper_bound(start, cend(str), *start); start != cend(str); start = adjacent_find(finish, cend(str)), finish = upper_bound(start, cend(str), *start)) {
cout << *start << " = " << distance(start, finish) << endl;
}
Live Example
I'm working on a project in my data stucts book and for some reason even though it's nearly verbatim from what's written I'm still getting a runtime error that I can't identify.
Here is my code:
int main()
{
cout << "Enter an expression, to check if its balanced.\n";
string exp;
while (getline(cin, exp) && (exp != ""))
{
cout << exp;
if(is_balanced(exp))
{
cout << " is balanced.";
}
else
{
cout << " is not balanced.";
}
cout << "Enter another expression: \n";
}
return 0;
}
bool is_balanced(const string& expression) // pass reference to the input expression
{
//create stack to hold parantheses
stack<char> s;
bool balanced = true; //to hold return value
string::const_iterator iter;
expression.begin(); // sets a read-only iterator at the beginning of the expression
while (balanced && (iter != expression.end())) //while 'balanced' and not at end of expression cont. looping
{
char nx_ch = *iter;
if (is_open(nx_ch))
{
s.push(nx_ch);
}
else if (is_closed(nx_ch))
{
if (s.empty())
{
balanced = false;
}
else
{
char tp_ch = s.top(); // if the stack isn't closed set the char as tp for comparisson
s.pop(); // remove top char
balanced = OPEN.find(tp_ch) == CLOSE.find(nx_ch);
}
}
++iter;
}
if(!s.empty())
{
balanced = false;
return balanced && s.empty();
}
else
{
return balanced && s.empty();
}
}
The error occurs at this line: if(is_balanced(exp))
In the main and reads:
Debug Assertion Failed! ... Expression: string iterators incompatible
Everything I've read about the error says it happens when you compare to iterators, but that doesn't make sense if I can't even get it through the constructor. Any help to better understand this would be wonderful. Thanks in advance.
string::const_iterator iter; does not initialise the iterator.
Then you are reading its value in iter != expression.end().
The behaviour on doing that is undefined.
Did you mean string::const_iterator iter = expression.begin();?
This isn't how you set a variable:
string::const_iterator iter;
expression.begin(); // sets a read-only iterator at the beginning of the expression
This is how you set a variable:
string::const_iterator iter = expression.begin(); // sets a read-only iterator at the beginning of the expression
So here's the line of my code to which I'm referring:
x.insert("a", "hello");
I'm trying to insert the string "hello" after each "a" in a string. Is it possible to do this with the insert function?
is it not possible to do this with the insert function?
That's right, you can't do this with a single call to insert() since std::string does not have an insert() function with these semantics.
Following this comment, here is how you can do this in a (non-infinite) loop:
void insert_after_each(std::string& s, const std::string& target, const std::string& to_insert)
{
for (std::string::size_type i = s.find(target);
i != std::string::npos;
i = s.find(target, i + target.size() + to_insert.size()))
{
s.insert(i + target.size(), to_insert);
}
}
This inserts the text after (what I call) the target string and skips past the target text ("a") and the inserted text ("hello") in each iteration.
Sample usage:
std::string s = "A cat sat on a mat";
insert_after_each(s, "a", "hello");
assert(s == "A cahellot sahellot on ahello mahellot");
What you want to do is find the position of a by using std::string::find then call std::string::insert to insert string to the right position. For example:
C++11
auto pos = x.find("a");
x.insert(pos, "app");
C++03:
std::string b(x);
int n = 0;
for(std::string::iterator iter = x.begin(); iter!=x.end(); ++iter)
{
if ((*iter) == 'a')
{
int pos = rep.size()* n + distance(x.begin(), iter);
cout << distance(x.begin(), iter) << " " << rep.size() << endl;
b.insert(pos,"app");
n++;
}
}
Now string b is what you are after.
int i;
vector<string> names;
string s = "penny";
names.push_back(s);
i = find(names.begin(), names.end(), s);
cout << i;
I'm trying to find index of an element in vector. It's ok with iterators, but I want it as int. How can I do it?
You can use std::distance for this.
i = std::distance( names.begin(), std::find( names.begin(), names.end(), s ) );
You will probably want to check that your index isn't out of bounds, though.
if( i == names.size() )
// index out of bounds!
It's probably clearer to do this with the iterator before using std::distance, though.
std::vector<std::string>::iterator it = std::find( names.begin(), names.end(), s );
if( it == names.end() )
// not found - abort!
// otherwise...
i = std::distance( names.begin(), it );
std::vector<string>::iterator it = std::find(names.begin(), names.end(), s);
if (it != names.end()) {
std::cout << std::distance(names.begin(), it);
} else {
// ... not found
}
try
i = (find( names.begin(), names.end(), s ) - names.begin());
Edit:
Although you should consider using vector::size_type instead of an int.
Assumptions that I am making about your code:
using std::vector;
using std::cout;
using std::string;
If my assumptions are correct, then you can find the distance between the beginning of the vector and the iterator (essentially the index into the vector at which you can find such element):
using std::distance;
Like so...
vector<string>::iterator i = find(names.begin(), names.end(), s);
if (i != names.end())
{
cout << "Index " << std::distance(names.begin(), i);
}
else
{
cout << s << "not found";
}
You can just dereference your iterator
int i = *name;