Avoid arbitrary limits
The definition of max (and especially as a #define rather than as a C++ constant) is worrying. Especially as the checking simply prints a diagnostic and then ignores the action that was requested.
Simple refactorings
if (test) return true; else return false; is the same as return test;. So we can write
bool Stack::isStackEmpty()
{
return top == -1;
}
Similarly, testing ==true is redundant:
if (isStackEmpty())
A more involved refactoring
void Stack::removeAdjacentDuplicate(std::string str)
{
int len = str.length();
for (int i = 0; i < len; i++)
{
if (isStackEmpty() == true)
{
push(str[i]);
}
else if (str[i] == stk[top])
{
int discard = pop();
}
else
{
push(str[i]);
}
}
}
Here, we're iterating over the elements of str, so we can use for (char c: str), which is clearer and less error-prone than using indexes.
The first and last branch are the same, so we can change the condition to bring them together:
void Stack::removeAdjacentDuplicate(const std::string& str)
{
for (auto c: str) {
if (isStackEmpty() || c != stk[top]) {
push(c);
} else {
(void)pop();
}
}
}
Think like standard algorithms
We have standard algorithms - one similar to our needs is std::unique(). This makes a single pass over its input, and returns an iterator to the new end position.
If we make a function with a similar interface, we can use the 'erase/remove' idiom to replace characters in a string:
#include <string>
std::string repeatedly_remove_duplicates(std::string s)
{
s.erase(repeatedly_remove_duplicates(s.begin(), s.end()), s.end());
return s;
}
How do we implement repeatedly_remove_duplicates()? I would assume a single pass called remove_duplicates(), and call it until the returned end doesn't change:
template <typename Iter>
Iter repeatedly_remove_duplicates(Iter begin, Iter end)
{
Iter new_end;
while ((new_end = remove_duplicates(begin, end)) != end) {
end = new_end;
}
return end;
}
(I've made this a template, so it can work with any container. The also allows us to make repeatedly_remove_duplicates() a template to work with any string type, including std::wstring, for instance).
Now, we need an implementation of remove_duplicates. We can do this in-place:
template <typename Iter>
Iter remove_duplicates(Iter begin, Iter end)
{
auto dest = begin;
if (begin == end) { return dest; }
auto prev = begin;
bool is_duplicate = false;
while (++begin != end) {
if (*begin == *prev) {
is_duplicate = true;
} else {
if (!is_duplicate) {
*dest++ = *prev;
}
is_duplicate = false;
prev = begin;
}
}
if (!is_duplicate) {
*dest++ = *prev;
}
return dest;
}
There are other ways to do this; we might use std::adjacent_find(), for example:
#include <algorithm>
#include <functional>
template <typename Iter>
Iter remove_duplicates(Iter begin, Iter end)
{
using namespace std::placeholders;
using not_equal_to = std::not_equal_to<typename Iter::value_type>;
auto dest = begin;
do {
Iter pair = std::adjacent_find(begin, end);
if (dest != begin) {
std::copy(begin, pair, dest);
dest += std::distance(begin, pair);
} else {
dest = pair;
}
} while (begin != end);
return dest;
}
Putting it all together
#include <algorithm>
#include <functional>
template <typename Iter>
Iter remove_duplicates(Iter begin, Iter end)
{
using namespace std::placeholders;
using not_equal_to = std::not_equal_to<typename Iter::value_type>;
auto dest = begin;
do {
Iter pair = std::adjacent_find(begin, end);
if (dest != begin) {
std::copy(begin, pair, dest);
dest += std::distance(begin, pair);
} else {
dest = pair;
}
#ifdef REMOVE_PAIR_ONLY
begin = pair;
if (pair != end) {
begin += 2;
}
#else
begin = std::adjacent_find(pair, end, not_equal_to());
if (begin != end) {
++begin;
}
#endif
} while (begin != end);
return dest;
}
template <typename Iter>
Iter repeatedly_remove_duplicates(Iter begin, Iter end)
{
Iter new_end;
while ((new_end = remove_duplicates(begin, end)) != end) {
end = new_end;
}
return end;
}
#include <string>
std::string repeatedly_remove_duplicates(std::string s)
{
s.erase(repeatedly_remove_duplicates(s.begin(), s.end()), s.end());
return s;
}
#include <iostream>
int main(int argc, char **argv)
{
for (auto i = 1; i < argc; ++i) {
std::cout << argv[i] << " ⇒ "
<< repeatedly_remove_duplicates(argv[i])
<< std::endl;
}
}
steeel? Your code appears to only remove adjacent pairs, but the example inputs don't give a clear requirement. \$\endgroup\$gazetteer,addressees,keenness\$\endgroup\$