This is really a rather subjective topic. In my view, there's nothing fundamentally wrong with three nested while loops, but you are reaching the limit of acceptability. Were you to add one or two more levels of nesting then you would, in my view, cross the boundary of what is reasonable to expect a reader to comprehend. The human brain can only handle so much complexity at any one point in time.
Some people would argue, counter to my opinion, that there should be no more than one level of nesting in a function, and that functions should not contain more than around 10 lines of code. The counter argument is that such a policy can result in more fragmented, disjoint code. My rule of thumb is that if you cannot think of a good function name for a chunk of code, then perhaps that chunk of code is not really meant to stand alone as a function.
Looking at ways in which you could break this function up, there are a couple of obvious options.
- Extract the body of the outermost
while
into a separate function. That extracted function would process a single line. It would be easy to name and clear to read.
- Extract the
while
loop that skips whitespace into a separate function. That again would be easy to name and would make your code easier to read. You would remove the whitespace comment because the name of the extracted function would render it needless. That's probably worth doing.
If you applied these ideas then your code might look a little like this:
char* skipWhitespace(char* str)
{
while (isspace(*str))
str++;
return str;
}
void parseLine(char *lineStr)
{
charPtr = strtok(lineStr, DELIMITERS);
while (charPtr != NULL)
{
charPtr = skipWhitespace(charPtr);
puts(charPtr);
charPtr = strtok(NULL, DELIMITERS);
}
}
......
while (fgets(lineStr, MAXLINELENGTH, fp) != NULL)
parseLine(lineStr);
Note that the refactoring and naming of extracted methods makes the comments a little superfluous and I removed them. Another good rule of thumb is that if you need to comment code too much, then perhaps it is not yet well-factored.
Ultimately, there really are not hard and fast rules, and it comes down to judgement and personal preference. In my view, the code in the question is very clear and readable, but the refactored version is just a little clearer, in my view.
Disclaimer: I make no comment regarding the correctness or otherwise of the code. I simply ignored that aspect.