A minimal C utility to read a single line at a time from a file descriptor. This project is a classic 42 assignment focused on robust buffered I/O, static storage, and edge-case handling.
- Repository: https://github.com/otmansabir/get_next_line
- Language: C
get_next_line(int fd)
reads from fd
and returns the next line, including the newline character if one is encountered before EOF. It maintains internal state between calls to continue from where it left off, making it suitable for iterating through a file (or stdin) line by line.
The bonus version adds support for handling multiple file descriptors at once.
- get_next_line.c — Core implementation
- get_next_line.h — Public header and API
- get_next_line_utils.c — String/util helpers for the core
- get_next_line_bonus.c — Bonus implementation (multi-FD)
- get_next_line_bonus.h — Bonus header
- get_next_line_utils_bonus.c — Helpers used by the bonus build
char *get_next_line(int fd);
- Parameters
fd
: A valid file descriptor (e.g., fromopen
,STDIN_FILENO
, or a socket).
- Returns
- A heap-allocated C string containing the next line (including the trailing
\n
when present). NULL
on EOF with no remaining data or on error.
- A heap-allocated C string containing the next line (including the trailing
Caller is responsible for free
ing the returned pointer when non-NULL.
This project typically relies on a compile-time macro BUFFER_SIZE
to control read chunk size.
- Define it at compile time:
-D BUFFER_SIZE=42
(example)
- Choosing a reasonable value (e.g., 32, 42, 1024) balances syscall frequency and memory usage.
If BUFFER_SIZE
is not provided, the implementation may use a default value defined in the header/source.
No build system is required; compile directly with your compiler.
-
Regular (single-FD) version:
cc -Wall -Wextra -Werror -D BUFFER_SIZE=42 \ -c get_next_line.c get_next_line_utils.c
Link the resulting objects with your program:
cc -Wall -Wextra -Werror -D BUFFER_SIZE=42 \ your_main.c get_next_line.o get_next_line_utils.o -o your_program
-
Bonus (multi-FD) version:
cc -Wall -Wextra -Werror -D BUFFER_SIZE=42 \ -c get_next_line_bonus.c get_next_line_utils_bonus.c cc -Wall -Wextra -Werror -D BUFFER_SIZE=42 \ your_main.c get_next_line_bonus.o get_next_line_utils_bonus.o -o your_program
Adjust flags and compiler as needed for your environment.
Read all lines from a file:
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include "get_next_line.h"
int main(void)
{
int fd = open("input.txt", O_RDONLY);
char *line;
if (fd < 0)
return 1;
while ((line = get_next_line(fd)) != NULL)
{
printf("%s", line);
free(line);
}
close(fd);
return 0;
}
Read from stdin:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "get_next_line.h"
int main(void)
{
char *line;
while ((line = get_next_line(STDIN_FILENO)) != NULL)
{
// process line...
free(line);
}
return 0;
}
- Includes the newline character
\n
in the returned string when a line break is encountered. - On EOF:
- If there is leftover buffered data without a trailing newline, returns that final chunk.
- Subsequent calls return
NULL
.
- Returns
NULL
on error (e.g., invalidfd
, read failure, memory allocation failure). - The function uses internal static storage to keep unread fragments between calls.
- Supports reading from multiple file descriptors in parallel (e.g., interleaving calls to
get_next_line(fd1)
andget_next_line(fd2)
). - Keeps independent internal buffers per
fd
.
Use get_next_line_bonus.c/.h
and corresponding utils for this behavior.
- Always
free
the returned pointer when non-NULL. - Guard against infinite loops by breaking on
NULL
. - Consider wrapping calls in a helper that ensures cleanup on errors.
- Choose a
BUFFER_SIZE
appropriate to your workload and platform.
- Standard C on Unix-like systems.
- Uses
read(2)
; ensure the descriptor is readable and opened appropriately.
- otmansabir — https://github.com/otmansabir
No license file is present in this repository at the time of writing.