I'm not really fond of this exercise, because the use of a stack here is not only artificial but also unintuitive.
As @Mike Borland said, the idea is probably to avoid explicit counting by popping the stack filled with as while you iterate over the rest of the string. Something along the lines:
#include <stack>
#include <string>
bool is_ab_balanced(const std::string& str) {
auto it = str.begin();
std::stack<char> as;
while (*it == 'a') as.push(*it++);
while (!as.empty()) {
if (it == str.end() || *it != 'b') return false;
as.pop(); ++it;
}
return it == str.end();
}
By the way, you'll notice that:
it always is better to use standardized containers unless you need customized behavior: std::stack is certainly better optimized and tested than linkedStackType<>
you shouldn't take a string by value as an argument, unless you intend to modify it while keeping the original string unchanged. Here, there's no modification, so use a const reference instead.
you should get rid of unused variables (see a and b in your second version). Those superfluous variables probably are a by-product of bad habits: declaring variables too far ahead of their use, and not enabling all warnings when you compile your code.
iterators are a better way to iterate over a range: it's more idiomatic, it's necessary to leverage the power of the STL, and it also avoids that extra size variable.
A few more key-strokes are better than using namespace std, which is is a bad idea
But, as I said, a good exercise should look more like real life. In real life, you use a stack only if it is the best way to go. So how would you check if a string belongs to the language if you could choose without restriction?
My take on that would be:
#include <string>
#include <algorithm>
using Iterator = std::string::iterator;
bool is_balanced(Iterator first, Iterator last) {
auto middle = std::next(first, std::distance(first, last) / 2);
return std::equal(first, middle, middle, last, [](auto a, auto b) {
return a == 'a' && b == 'b';
});
}