This is really a pretty subjective topic. In my opinion, there is nothing fundamentally wrong in the three nested loops, but you reach the limit of acceptability. If you added one or two levels of nesting, you would, in my opinion, cross the border of what is reasonable to expect from the reader. The human brain can only cope with such complexity at one point in time.
Some people will argue with my opinion that a function should have no more than one level of nesting, and that functions should not contain more than 10 lines of code. The argument of the counter is that such a policy can lead to more fragmented, disjoint code. My rule of thumb is that if you cannot come up with a good function name for a piece of code, then perhaps this piece of code is not really designed to work on its own.
Looking at the ways in which you could break this function down, there are some obvious options.
- Extract the body of the external
while
into a separate function. This extracted function would process one line. It would be easy to call and readable. - Extract a
while
that skips the space into a separate function. This would again be easy to name and make code easier to read. You would remove the whitespace comment because the name of the extracted function would make it unnecessary. It is probably worth it.
If you applied these ideas, your code might look something 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 refactoring and naming the extracted methods makes comments a little redundant, and I deleted them. Another good rule of thumb: if you need to comment too much on the code, it may not be well known.
Ultimately, there are really no hard and fast rules, and it comes down to judgment and personal preferences. In my opinion, the code in the question is very clear and readable, but, in my opinion, the refactoring version is a little understandable.
Disclaimer: I do not comment on the correctness or code. I just ignored this aspect.