WHILE is more flexible. FOR is more concise in those instances in which it applies.
FOR is great for loops which have a counter of some kind, like
for (int n=0; n<max; ++n)
You can accomplish the same thing with a WHILE, of course, as others have pointed out, but now the initialization, test, and increment are broken across three lines. Possibly three widely-separated lines if the body of the loop is large. This makes it harder for the reader to see what you're doing. After all, while "++n" is a very common third piece of the FOR, it's certainly not the only possibility. I've written many loops where I write "n+=increment" or some more complex expression.
FOR can also work nicely with things other than a counter, of course. Like
for (int n=getFirstElementFromList(); listHasMoreElements(); n=getNextElementFromList())
Etc.
But FOR breaks down when the "next time through the loop" logic gets more complicated. Consider:
initializeList();
while (listHasMoreElements())
{
n=getCurrentElement();
int status=processElement(n);
if (status>0)
{
skipElements(status);
advanceElementPointer();
}
else
{
n=-status;
findElement(n);
}
}
That is, if the process of advancing may be different depending on conditions encountered while processing, a FOR statement is impractical. Yes, sometimes you could make it work with a complicated enough expressions, use of the ternary ?: operator, etc, but that usually makes the code less readable rather than more readable.
In practice, most of my loops are either stepping through an array or structure of some kind, in which case I use a FOR loop; or are reading a file or a result set from a database, in which case I use a WHILE loop ("while (!eof())" or something of that sort).