I am working on some homework and wanted to know if there is such as thing as too many nested while loops. Is there downsides to nesting several while loops? If so how would one refactor the code snippet I have below?
Below is code to read a file one line at a time, parse the fields delimited by some defined delimiters, and remove leading white space before printing to console.
// Read the file one line at a time
while (fgets(lineStr, MAXLINELENGTH, fp) != NULL)
{
charPtr = strtok(lineStr, DELIMITERS);
// Loop until line is parsed
while (charPtr != NULL)
{
// Skip past leading whitespace
while (isspace(*charPtr))
charPtr++;
puts(charPtr);
charPtr = strtok(NULL, DELIMITERS);
}
}
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.
while
into a separate function. That extracted function would process a single line. It would be easy to name and clear to read.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.
The only real downside is readability, for which there aren't really any hard and fast rules about... although more than 3 nests will usually irritate anyone else you're working with. As another poster said, sometimes its better to break the nest by moving the loop to another function, but what you have here is perfectly readable to me - and thats the only real metric out there; pure subjective opinion :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With