This is an interesting problem, and a good interview question.
Count the number of comments in Code file
Lets define the comments :
1) Single line comments start with //
2) Multi line comments start with /* and end with */
What are the different possible comments in the code ?
// at the start of the line,
some code here and then // some code
“C://somepath” this is not a comment !! (Our code should be able to ignore this)
‘//’ Even this is not a comment we should ignore (//) here.
/* some line */
/* /**/*/
/*
//
//
*/
These are some of the possible combinations that form comments in source code.
Now we can solve this using traditional approach of checking first character and second character and deciding based on that, but i dont like it,
it will involve lot of if’s and hard to keep track of all the conditions. Also the code will not be readable.
How about creating a state machine like the following :
So we start with initial state “Normal Content” if we get a / there then we go to state -> Single Line Comment start , here if we get another /
we go to state -> single line comment end. Similarly for the rest conditions.
And here is the code for above state machine :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
public enum ParserState { NormalContent, SingleQuote, DoubleQuote, MultipleCommentStart, MultipleCommentEnd, SingleLineCommentEnd, SingleLineCommentStart, StartObserved } private async Task<int> CommentCounter(string fileName) { var file = await KnownFolders.PicturesLibrary.GetFileAsync("codefile.txt"); IList<string> fileContent = await FileIO.ReadLinesAsync(file); ParserState currentState = ParserState.NormalContent; int singleLineComments = 0; int multiLineComments = 0; foreach (string line in fileContent) { for (int i = 0; i < line.Length; i++) { switch (currentState) { case ParserState.NormalContent: switch (line[i]) { case '/': currentState = ParserState.SingleLineCommentStart; break; case '\'': currentState = ParserState.SingleQuote; break; case '\"': currentState = ParserState.DoubleQuote; break; default: break; } break; case ParserState.SingleLineCommentStart: switch (line[i]) { case '/': currentState = ParserState.SingleLineCommentEnd; break; case '*': currentState = ParserState.MultipleCommentStart; break; default: currentState = ParserState.NormalContent; break; } break; case ParserState.MultipleCommentStart: switch (line[i]) { case '*': currentState = ParserState.StartObserved; break; default: break; } break; case ParserState.StartObserved: switch (line[i]) { case '/': currentState = ParserState.MultipleCommentEnd; break; case '*': currentState = ParserState.StartObserved; break; default: currentState = ParserState.MultipleCommentStart; break; } break; case ParserState.DoubleQuote: switch (line[i]) { case '\"': currentState = ParserState.NormalContent; break; default: break; } break; case ParserState.SingleQuote: switch (line[i]) { case '\'': currentState = ParserState.NormalContent; break; default: break; } break; } switch (currentState) { case ParserState.SingleLineCommentEnd: singleLineComments++; break; case ParserState.MultipleCommentEnd: multiLineComments++; break; } if (currentState == ParserState.SingleLineCommentEnd || currentState == ParserState.MultipleCommentEnd) { currentState = ParserState.NormalContent; break; } } } return multiLineComments + singleLineComments; } |
Leave a comment if you like the post 🙂