From e8d66db238ec3814b90cc225fafbba5c8cbcf025 Mon Sep 17 00:00:00 2001 From: Intel A80486DX2-66 Date: Sun, 10 Mar 2024 14:39:10 +0300 Subject: [PATCH] freadln.*: implement reading lines from arbitrary file --- c-programming/io/freadln.c | 38 ++++++++++++++++++++++++++++++++------ c-programming/io/freadln.h | 3 ++- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/c-programming/io/freadln.c b/c-programming/io/freadln.c index 3d5a30c..5e54bf4 100644 --- a/c-programming/io/freadln.c +++ b/c-programming/io/freadln.c @@ -10,13 +10,12 @@ * TODO: Figure out potential problems * TODO: Add 'flushing' of STDIN (while there are characters, read them) before * the input reading loop to avoid input queues - * TODO: Add the feature of reading from arbitrary file, then extract a macro: - * `#define finreadln(output, length_out) freadln(stdin, output, length_out)` + * FIXME: Handle EOF in a special way to indicate EOF */ #include "freadln.h" -int freadln(char** output, size_t* length_out) { +int freadln(FILE* f, char** output, size_t* length_out) { /* * The length of STDIN line is counted without any terminating characters. * @@ -24,7 +23,7 @@ int freadln(char** output, size_t* length_out) { * freadln_OK: no errors, the length of STDIN line has been stored in * `length_out` * freadln_ERROR: an error occurred (see errno) - * >= 0: length of stdin line + * >= 0: length of read line */ if (output == NULL) @@ -41,7 +40,7 @@ int freadln(char** output, size_t* length_out) { return freadln_ERROR; int character; - while ((character = fgetc(stdin)) != EOF + while ((character = fgetc(f)) != EOF /* stop on a newline character: */ && character != '\n') { (*output)[length] = (char) character; @@ -71,13 +70,40 @@ int freadln(char** output, size_t* length_out) { #ifdef TEST int main(void) { + // stdin test printf("Type something> "); char* line; - if (freadln(&line, NULL) != freadln_OK) { + if (finreadln(&line, NULL) != freadln_OK) { perror("freadln"); exit(EXIT_FAILURE); } printf("Input string: '%s'\n", line); + + // file test +#define TEST_FILE "freadln_test.txt" + FILE* f = fopen(TEST_FILE, "w"); + if (f == NULL) { + perror("fopen"); + exit(EXIT_FAILURE); + } + fprintf(f, "Hello, world!\nAnother line\n\n"); + FILE* new_f = freopen(TEST_FILE, "r", f); + if (new_f == NULL) { + perror("freopen"); + exit(EXIT_FAILURE); + } + f = new_f; + for (int i = 0; i < 5; i++) { + size_t line_length; + if (freadln(f, &line, &line_length) != freadln_OK) { + perror("freadln"); + exit(EXIT_FAILURE); + } + printf("File, line #%d: '%s' (%zu characters)\n", i + 1, line, + line_length); + } + fclose(f); + return 0; } #endif diff --git a/c-programming/io/freadln.h b/c-programming/io/freadln.h index 4476518..912a9ab 100644 --- a/c-programming/io/freadln.h +++ b/c-programming/io/freadln.h @@ -26,6 +26,7 @@ enum freadln_status { return freadln_OK; \ } while (0) -int freadln(char** output, size_t* length_out); +int freadln(FILE* f, char** output, size_t* length_out); +#define finreadln(output, length_out) freadln(stdin, output, length_out) #endif /* _FREADLN_H */