Sequential IO with stdin & stdout#
Opening a file#
FILE *fopen(char *path, char* mode);
int fclose(FILE *stream);
When we open a file, then we get a stream or a FILE *. We use the stream with the following functions.
Writing & reading strings#
int fputs(char *s, FILE *stream);
char *fgets(char *s, int size, FILE *stream);
// With formatting
int fprintf(FILE *stream, char *format);
int fscanf(FILE *stream, char *format);
// stdout
int puts(char *s);
fstands for file.putsAdds a newline. If you don't want it, useprintforfputs.fgetsrequiressizeandstdoutexplicitly.the sister of
puts,char *gets(char *s)used to exist, but is deprecated now due to security. It is impossible to know in advance how many characters we will read, so it can lead to buffer overflow.
Why does fgets require size but fputs does not?
Opening modes#
mode |
meaning |
mode+ |
meaning |
|---|---|---|---|
|
read |
|
read + write |
|
write |
|
write + read |
|
append |
|
append + read |
Example below
#include <stdio.h>
#define LINE_MAX 80
void write_to_a_file() {
FILE *fp = fopen("file.txt", "w");
// open file with only write permissions
fputs("First string", fp);
fputs("Second string", fp);
fputs("\nNew line", fp);
fclose(fp);
}
void read_from_a_file() {
FILE *fp = fopen("file.txt", "r");
// only read permissions
char line[LINE_MAX];
fgets(line, LINE_MAX, fp);
puts(line);
fgets(line, LINE_MAX, fp);
puts(line);
}
int main() {
write_to_a_file();
read_from_a_file();
}
First stringSecond string
New line
Activity 59 (Processing temperature data)
temperatures.txt contains several temperature measurements:
20
21
18
18
19
20
20
Write a single program that do the following actions. For each point, open and close the file separately.
Reads five lines from
temperatures.txtfile and prints them to the console.Creates a new file
temperatures-today.txtand writes three temperature measurements.Appends a new measurement to
temperatures.txt.Creates an empty file
measurements-done.txtReads five lines from
temperatures.txtand writes the temperatures which are greater than 19 totemperatures-filtered.txt. Use a for loop that reads five times.You can use
fgets+strtolorfscanffor integer conversion.Similar to last, but read all lines using
while(line = fgets(...)).What does
fgetsreturn if we arrive at the end of the file? Refer to the documentation.
Appendix#
Character-oriented functions#
int fputc(int c, FILE *stream);
int fgetc(FILE *stream);
// stdout & stdin
int putchar(int c);
int getchar(void);
String-oriented functions use character-oriented functions. This is useful for implementing input-output (IO) for special hardware. Let's assume you are programming a microcontroller and want to use an LCD to display data. You can implement putchar to write a character to the LCD's display memory and maybe to move the cursor afterwards, e.g.,:
int putchar(int c) {
lcd_write(c);
lcd_move_cursor();
return c;
}
Then you can use puts or printf to display whole strings.
String-oriented functions are built on top of the character-oriented functions.
If you provide, i.e., implement a character-oriented function like putc, you can determine what string functions do.
putc && getc#
int putc(int c, FILE *stream);
int getc(FILE *stream);
These are input-output-wise functionally equivalent to fputc and fgetc. I don't mention these functions, because these functions are in the standard for performance. They are allowed to be implemented as macros.
More info: