Palindrome evaluator in C++ I started learning C++ a few days ago, and this is my first full program. It takes in words until an end-of-file character prompt is given, and then outputs which of those words are palindromes and the longest palindrome of those words.

I want to know if my evaluation for whether each string is a palindrome is acceptable given the little knowledge I have about C++ thus far, and by acceptable I mean like not costly or just not agreeable for good C++ code. I was unsure if it would be better to access characters by position in each string with like a "double iterator" to check if they were the same while the iterators converged, or if just making a reversed string and checking is a better approach like I did.

Also, just if my general program structure looks okay - I'm rather unsure if my desire to have void functions to clean up my main function is really a good thing to do or otherwise.

#include &lt;iostream&gt;
#include &lt;list&gt;
#include &lt;iomanip&gt;

using std::cin;         using std::cout;        using std::string;
using std::istream;     using std::list;        using std::endl;
using std::setw;

istream&amp; read(istream&amp; is, list&lt;string&gt;&amp; word_list)
{
    word_list.clear();
    string word;
    while(is &gt;&gt; word)
        word_list.push_back(word);

    is.clear();
    return is;
}

void evaluate(list&lt;string&gt;&amp; words, string&amp; longest)
{
    longest.clear();
    typedef string::size_type str_sz;

    list&lt;string&gt;::iterator it = words.begin();
    while (it != words.end())
    {
        if (*it == string(it-&gt;rbegin(), it-&gt;rend()))
        {
            longest = max(longest, *it);
            ++it;
        }
        else
        {
            it = words.erase(it);
        }
    }
}

void output(const list&lt;string&gt;&amp; palindrs, const string&amp; longest)
{
    if (palindrs.empty())
        cout &lt;&lt; "No palindromes were given :(" &lt;&lt; endl;
    else{
        cout &lt;&lt; "The palindrome(s) given are: " &lt;&lt; '\n' &lt;&lt; endl;
        for (list&lt;string&gt;::const_iterator it = palindrs.begin(); 
            it != palindrs.end(); ++it)
            cout &lt;&lt; setw(5) &lt;&lt; "- \"" &lt;&lt; *it &lt;&lt; "\"" &lt;&lt; endl;

        cout &lt;&lt; '\n' &lt;&lt; "And the longest palindrome is \"" &lt;&lt;
             longest &lt;&lt; "\"!";
    }
}

int main()
{
    list&lt;string&gt; words;

    cout &lt;&lt; "Please enter some words." &lt;&lt; endl;
    read(cin, words);

    string longest;
    evaluate(words, longest);

    output(words, longest);

    return 0;
}
Your code looks so good, it is quite impressive of you were learning c++ few days ago. i'm sure you will get a decent code-review but here my humble attempt.

It always preferred to pass the std::string by const reference if you don't  modify it. also, std::vector is preferred over std::list. here link for more details 

In your read function. It redirects all input into this container until EOF is received. However, the used container might need to reallocate memory too often, or you will end with a std::bad_alloc exception when your system gets out of memory. In order to solve these problems, you could reserve a fixed amount N of elements and process these amount of elements. here an alternative example to your read function by using std::copy_n and std::istream_iterator like so,

words.reserve(N);
std::copy_n(std::istream_iterator&lt;std::string&gt;(std::cin),
    N,
    std::back_inserter(words));


In your evaluate function, it is fine but not efficient doe to the call of std::string constructor in every iteration along with deleting un-palindrome elements. it is better to create another container for palindrome elements and check the main container elements if it has palindrome element. possible implementation:

std::vector&lt;std::string&gt; palindromes;
for (const auto&amp; word : words)
{
    if(is_palindrome(word))
        palindromes.emplace_back(word);
}


The is_palindrome function, we test the given string for whither it is palindrome or not, like so:

bool is_palindrome(const std::string&amp; str)
{
    if (str.empty())
        return false;

    using str_sz = std::string::size_type;
    for (str_sz i = 0, j = str.length() -1; i &lt; j ; ++i, --j)
    {
        if (str[i] != str[j])
            return false;
    }
    return true;
}


thanks to @screwnut for suggesting to std::copy_if instead of for-range while the for-loop is bit clear and simple. but std::copy_if will allow us to use lambda instead of calling is_palindrome function, that might be helpful if you simply write it like this:

std::copy_if(words.begin(), words.end(), 
             std::back_inserter(palindromes), 
             [](const std::string&amp; str)
             {return std::equal(str.begin(), str.begin() + str.size() / 2, str.rbegin());});


Lastly, for longest string, you may take advantage of STL by using std::max_element which is return iterator.

std::max_element(palindromes.begin(), palindromes.end(),
    [](const std::string&amp; lhs, const std::string&amp; rhs)
{
    return lhs.size() &lt; rhs.size();
});


put all to gather:

#include &lt;iostream&gt;
#include &lt;vector&gt;
#include &lt;algorithm&gt;
#include &lt;iterator&gt;

int main()
{
    const std::size_t TotalWords = 3;
    std::vector&lt;std::string&gt; words;
    words.reserve(TotalWords);

    std::cout &lt;&lt; "Please enter some words." &lt;&lt; std::endl;
    std::istream_iterator&lt;std::string&gt; in(std::cin);
    std::copy_n(in, TotalWords, std::back_inserter(words));

    std::vector&lt;std::string&gt; palindromes;

    auto comp = [](const std::string&amp; str)
    {
        return std::equal(str.begin(), str.begin() + str.size() / 2, str.rbegin());
    };

    std::copy_if(words.begin(), words.end(), std::back_inserter(palindromes), comp);

    if (palindromes.empty())
    {
        std::cout &lt;&lt; "No palindromes were given" &lt;&lt; std::endl;
    }
    else
    {
        auto longest = std::max_element(palindromes.begin(), palindromes.end(),
            [](const std::string&amp; lhs, const std::string&amp; rhs)
        {
            return lhs.size() &lt; rhs.size();
        });
        std::ostream_iterator&lt;std::string&gt; out(std::cout, "\n ");
        std::cout &lt;&lt; "Palindromes: \n ";
        std::copy(palindromes.begin(), palindromes.end(), out);
        std::cout &lt;&lt; "\rLongest: " &lt;&lt; *longest &lt;&lt; std::endl;
    }
}