Suppose we want to write characters to a file (output.txt, say). As always, we must declare a file pointer (out, say) and associate it with the file using
FILE * out = fopen("output.txt", "w");
If ch is a char variable, we can write the value of ch to the file with fprintf(out, "%c", ch);
C also provides the function putc (put a character) to do the same job. To write the value of ch to the file associated with out, we must write:
putc(ch, out);
Note that the file pointer is the second argument to putc.
6.10.1 Echo Input, Number Lines
Let us expand the example on the previous page to read data from a file and write back the same data (echo the data) to the screen with the lines numbered starting from 1.
The program would read the data from the file and write it to the screen, thus:
1. First line of data 2. Second line of data etc.
This problem is a bit more difficult than those we have met so far. When faced with such a problem, it is best to tackle it a bit at a time, solving easier versions of the problem and working your way up to solving the complete problem.
For this problem, we can first write a program that simply echoes the input without numbering the lines. When we get this right, we can tackle the job of numbering the lines.
An outline of the algorithm for this first version is the following:
read a character, ch
while ch is not the end-of-file character print ch
read a character, ch endwhile
This will maintain the line structure of the data file since, for instance, when \n is read from the file, it is immediately printed to the screen, forcing the current line to end.
Program P6.10 implements the above algorithm for reading the data from a file and printing an exact copy on the screen.
Program P6.10
#include <stdio.h>
int main() { char ch;
FILE *in = fopen("input.txt", "r");
while ((ch = getc(in)) != EOF) putchar(ch);
fclose(in);
}
Now that we can echo the input, we need only figure out how to print the line numbers.
A simplistic approach is based on the following outline:
set lineNo to 1 print lineNo
read a character, ch
while ch is not the end-of-file character print ch
if ch is \n
add 1 to lineNo print lineNo endif
read a character, ch endwhile
We have simply added the statements that deal with the line numbers to the algorithm above.
We can easily add the code that deals with the line numbers to Program P6.10 to get Program P6.11. Note that when we print the line number, we do not terminate the line with \n since the data must be written on the same line as the line number.
Program P6.11
//This program prints the data from a file numbering the lines
#include <stdio.h>
int main() { char ch;
FILE *in = fopen("input.txt", "r");
int lineNo = 1;
printf("%2d. ", lineNo);
while ((ch = getc(in)) != EOF) { putchar(ch);
if (ch == '\n') { lineNo++;
printf("%2d. ", lineNo);
} }
fclose(in);
}
Assume the input file contains the following:
There was a little girl Who had a little curl
Right in the middle of her forehead Program P6.11 will print this:
1. There was a little girl 2. Who had a little curl
3. Right in the middle of her forehead 4.
Almost, but not quite, correct! The little glitch is that we print an extra line number at the end.
To see why, look at the if statement. When \n of the third data line is read, 1 would be added to lineNo, making it 4, which is printed by the next statement. This printing of an extra line number also holds if the input file is empty, since line number 1 would be printed in this case, but there is no such line.
To get around this problem, we must delay printing the line number until we are sure that there is at least one character on the line. We will use an int variable writeLineNo, initially set to 1. If we have a character to print and writeLineNo is 1, the line number is printed and writeLineNo is set to 0. When writeLineNo is 0, all that happens is that the character just read is printed.
When \n is printed to end a line of output, writeLineNo is set to 1. If it turns out that there is a character to print on the next line, the line number will be printed first since writeLineNo is 1.
If there are no more characters to print, nothing further is printed; in particular, the line number is not printed.
Program P6.12 contains all the details. When run, it will number the lines without printing an extra line number.
Program P6.12
//This program prints the data from a file numbering the lines
#include <stdio.h>
int main() { char ch;
FILE *in = fopen("input.txt", "r");
int lineNo = 0, writeLineNo = 1;
while ((ch = getc(in)) != EOF) { if (writeLineNo) {
printf("%2d. ", ++lineNo);
writeLineNo = 0;
}
putchar(ch);
if (ch == '\n') writeLineNo = 1;
}
fclose(in);
}
We wrote the if condition as follows:
if (writeLineNo)...
If writeLineNo is 1 the condition evaluates to 1 and is, therefore, true; if it is 0, the condition is false. We could also have written the condition as
if (writeLineNo == 1)...
In the statement
printf("%d. ", ++lineNo);
the expression ++lineNo means that lineNo is incremented first before being printed. By comparison, if we had used lineNo++, then lineNo would be printed first and then incremented.
Exercise: Modify Program P6.12 to send the output to a file, linecopy.txt.
Exercise: Write a program to copy the contents of a file, input.txt, to a file, copy.txt.
Hint: you just need to make minor changes to Program P6.10.