First, compile with warnings turned all the way up:
Code:
$ gcc -Wall -ggdb3 -pedantic -std=c99 -O0 -o foo foo.c -lm -lpthread -lrt
foo.c: In function ‘main’:
foo.c:23:21: warning: implicit declaration of function ‘isdigit’ [-Wimplicit-function-declaration]
foo.c:27:17: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
foo.c:7:9: warning: unused variable ‘number_of_digits’ [-Wunused-variable]
Second, read this link: FAQ > Why it's bad to use feof() to control a loop - Cprogramming.com. You'll read the last thing twice (i.e. read the last char twice since you're using fgetc. this error with fgets would repeat the last line). You should use the return value of your read functions to control the loop.
Third, you need to #include <ctype.h> if you want to use isdigit().
Fourth, C is not python. Indentation will not make code part of an if or loop, or anything else. Use curly braces if you want to include several statements in a sub-block. Note, the below code shows correct syntax, but the logic here is still broken.
Code:
if(isdigit(num)) {
number_of_digits_per_line++;
linescount++;
printf("%d %d\n", linescount, number_of_digits_per_line);
}
Fifth, pay attention to operator precedence. The following line sets a to the result of the boolean == comparison. Once again, the below demonstrates the syntax you want, but has incorrect logic.
Code:
a = fgetc(inputFile) == '\n'
// is equivalent to
a = (fgetc(inputFile) == '\n')
// but you really want
(a = fgetc(inputFile)) == '\n')
Sixth, check the documentation for functions you use. fgetc returns an int, so it can return all possible char values, plus status values like EOF. a should be declared an int, if you want it to contain the return value from fgetc.
Seventh, you need to think carefully about what you are doing. Work out the problem, with paper and pencil, in your native language. If you can't solve the problem yourself, you can't program a computer to do it for you. You must understand the problem and solution before you begin coding. Some questions to consider:
- When should you increase number_of_digits_per_line?
- What should you do to number_of_digits_per_line when you start a new line?
- When should you increase linescount?
- When should you print linescount and number_of_digits_per_line?
- What should the program do if a line contains no digits? Should it print <line number> 0, or should it skip output for that line?
Lastly, implement the code. Work in small chunks, around 5 lines at a time. Compile, at maximum error/warning levels, and fix all errors. Then test your code and make sure it does exactly what it's supposed to do. Don't move onto the next section until you're completely done and error-free with the current section. The "chunks" I would have broken this program into are:
- Code to open and close the file. Test that it correctly handles errors with fopen. Hint, I would use perror() to print an error, it tells you why the function failed, which is very helpful when debugging.
- Read the file line-by-line, and count lines. Each time you read a line, print the line count and the actual line, to make sure you read the right number of lines and read whole line (no more, no less) correctly. This would catch your while (!feof) error with the double-last-line.
- Go through each char in the line you read, counting the digits. Each time you find a digit, print the current digit count for that line, the digit you found, and possible the position in the line you found it at, to help you verify your code is working correctly.
- Remove any debugging output, and add the actual output the program expects (i.e. list of lines with digit counts for that line).
My personal preference would be to use fgets to read a whole line at a time into a buffer, then loop through the buffer counting digits. It saves you from having to worry about the logic to detect a '\n', it's built into fgets.