In addition to format-driven printf/fprintf and scanf/fscanf, C provides stream functions that transfer individual characters or complete lines. stdin and stdout are also FILE * streams, so console and file operations share one stream model.
getchar and putchar
getchar() is equivalent to calling fgetc on stdin, while putchar(ch) writes one character to stdout. Both use int so every unsigned char value and the special EOF value can be represented.
#include <stdio.h>
int main(void) {
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
putchar(ch);
}
putchar('\n');
return 0;
}fgetc and fputc
fgetc(fp) reads the next byte from a specified stream and returns the promoted character value or EOF. fputc(ch, fp) writes one character to a specified stream and returns EOF on failure.
The examples use file-io-sample.txt. Create it in the program's working directory by copying this text:
Leaflet file I/O sample
The second line is ready to read.#include <stdio.h>
int main(void) {
FILE *source = fopen("file-io-sample.txt", "r");
FILE *target = fopen("first-character.txt", "w");
if (source == NULL || target == NULL) {
if (source != NULL) {
fclose(source);
}
if (target != NULL) {
fclose(target);
}
return 1;
}
int ch = fgetc(source);
if (ch != EOF) {
if (fputc(ch, target) == EOF) {
fclose(source);
fclose(target);
return 1;
}
}
fclose(source);
fclose(target);
return 0;
}gets and puts
gets cannot know the destination capacity, can overwrite memory, and was removed from C11. The next snippet only documents how legacy code called it; do not compile or use it. puts remains valid and appends a newline after the string.
/* Historical example — never use this pattern.
char text[16];
gets(text);
puts(text);
*/For a fixed output line, puts can be used on its own:
#include <stdio.h>
int main(void) {
puts("File processing complete.");
return 0;
}fgets and fputs
fgets(buffer, size, stream) reads at most size−1 characters and writes \0. It keeps the newline when that character fits. fputs(text, stream) writes a string but does not add a newline automatically.
#include <stdio.h>
int main(void) {
char line[80];
fputs("Enter a line: ", stdout);
if (fgets(line, sizeof line, stdin) == NULL) {
return 1;
}
fputs("You entered: ", stdout);
fputs(line, stdout);
return 0;
}When a read returns EOF or NULL, the cause can be normal end-of-file or an error. Use feof and ferror after the read when the distinction matters.
KNOWLEDGE QUIZ
KNOWLEDGE QUIZ
KNOWLEDGE QUIZ
KNOWLEDGE QUIZ
Safely read and label one line
Declare an 80-byte array and read one line from stdin with fgets. On success, use fputs to output received: and then the original line; return 1 on failure. Do not use gets, scanf, or printf.
- Prepare a fixed-capacity character array and call fgets.
- Do not use the buffer when reading fails.
- Write the label and line with fputs and check both results.
Copy a text file character by character
Copy the text shown in this lesson to create file-io-sample.txt, open it for reading, and create character-copy.txt for writing. Copy with fgetc/fputc, check write failure and ferror on the source, then close both files.
- Open both files in read/write modes and validate the returned streams.
- Store fgetc in an int and loop until EOF.
- Check fputc and fclose and close every stream that was opened.