(sequential-io)=
# Sequential IO with `stdin` & `stdout`

## Opening a file

```c
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 write & read functions.

We should close the file after we are finished processing the file. Closing guarantees that the data we write to the file are indeed written to the file. If we don't close the file, then the OS will close it after the program ends.

Opening a file is not the same as having the sole access to the file. On Linux on MacOS, other programs can still read & write; on Windows, other programs can read but not write. This is the default behavior and can be changed.

## Writing & reading strings

```c
int fputs(char *s, FILE *stream);
char *fgets(char *s, int size_of_s, FILE *stream);

// With formatting
int fprintf(FILE *stream, char *format);
int fscanf(FILE *stream, char *format);

// stdout
int puts(char *s);
```
- `f` stands for file.
- `puts`  adds a newline. If you don't want it, use `printf` or `fputs`.
- `fgets` requires `size` and `stdout` explicitly.
- the sister of `puts`, `char *gets(char *s)`{l=c} 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 could lead to buffer overflow.

:::{card} 🤔 Question to ponder
Why does `fgets` require `size` but `fputs` does not?
:::

## Opening modes

:::{list-table}
:header-rows: 1
:width: 50%
* - mode
  - meaning
  - mode+
  - meaning
* - `r`
  - read
  - `r+`
  - read + write
* - `w`
  - write
  - `w+`
  - write + read
* - `a`
  - append
  - `a+`
  - append + read
:::

:::{card} ⚡ Live programming
Example below
:::

:::{literalinclude} ../code/writing-and-reading-a-file.c
:language: c
:::
:::{literalinclude} ../code/writing-and-reading-a-file.txt
:language: text 
:::

::::{activity} Processing temperature data
:label: processing-temperature-data
`temperatures.txt` contains several temperature measurements:

:::{literalinclude} ../code/temperatures.txt
:language: text
:::

Write a single program that do the following actions. For each point, open and close the file separately.
1. Reads five lines from `temperatures.txt` file and prints them to the console.
1. Creates a new file `temperatures-today.txt` and writes three temperature measurements.
1. Appends a new measurement to `temperatures-today.txt`.
1. Creates an empty file `measurements-done.txt`
1. Reads five lines from `temperatures.txt` and writes the temperatures which are greater than 19 to `temperatures-filtered-some.txt`. Use a for loop that reads five times.

   For conversion between string and integer you can use 
  - `fgets` + `strtol` 
  - or `fscanf` + `fprintf` for integer conversion.

1. Same to the last specification, but:

   1. read all lines using `while(line = fgets(...))`.
   1. output to `temperatures-filtered-all.txt`.

   What does `fgets` return if we arrive at the end of the file? Refer to the documentation.
::::
<!--
TODO I have to introduce what fgets returns more gracefully
-->


## Appendix

### Character-oriented functions

```c
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.,:

```c
int putchar(int c) {
  lcd_write(c);  
  lcd_move_cursor();
  return c;
}
```

Then you can use `puts` or `printf` to display whole strings.

<!--
It is also possible to define a stream like `stdout`, e.g., `lcdout`.
-->

:::{card} 🥡 Takeaway
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`

```c
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:

- <https://stackoverflow.com/questions/14008907/fputc-vs-putc-in-c>
- <https://stackoverflow.com/questions/20106401/why-fputc-when-putc>