Line numbers.
This commit is contained in:
parent
a3147500b5
commit
96433cf5b4
38
src/main.c
38
src/main.c
|
@ -1,5 +1,10 @@
|
|||
#include <stdlib.h> /* EXIT_ strtol */
|
||||
#include <stdio.h> /* FILE fopen fclose fread */
|
||||
/** This is a test for `min_array.h`: takes an arbitrary stream, (Cntl-d stops
|
||||
in most implementations of interactive terminal,) and greedily extracts
|
||||
integers in the style of `strtol` until it gets to the end-of-file or a
|
||||
null-terminator. */
|
||||
|
||||
#include <stdlib.h> /* size_t EXIT_ strtol */
|
||||
#include <stdio.h> /* FILE fopen fclose fread [f]printf ferror perror */
|
||||
#include <errno.h> /* errno */
|
||||
#include <ctype.h> /* isdigit */
|
||||
#include <limits.h> /* LONG_ INT_ _MIN _MAX */
|
||||
|
@ -9,10 +14,10 @@
|
|||
MIN_ARRAY(char, char)
|
||||
MIN_ARRAY(num, int)
|
||||
|
||||
/** Concatenates the contents of `fp` after the file pointer to `string`. The
|
||||
file pointer is modified. Zeros are preserved, as well as appending a
|
||||
null-terminator. @return Success, otherwise `string` may have read a partial
|
||||
read and may not be terminated. @throws[fread, malloc] */
|
||||
/** Concatenates the contents after the file pointer of `fp` to `string`. Zeros
|
||||
are preserved, as well as appending a null-terminator. @return Success,
|
||||
otherwise `string` may have read a partial read and may not be terminated.
|
||||
@throws[fread, malloc] */
|
||||
static int cat_fp_to_str(FILE *const fp, struct char_array *const string) {
|
||||
const size_t granularity = 1024;
|
||||
size_t nread;
|
||||
|
@ -27,6 +32,7 @@ static int cat_fp_to_str(FILE *const fp, struct char_array *const string) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
/** Stores the entire stream and then stores the extracted `int` numbers. */
|
||||
int main(void) {
|
||||
int success = EXIT_FAILURE;
|
||||
struct char_array str = MIN_ARRAY_IDLE;
|
||||
|
@ -34,28 +40,30 @@ int main(void) {
|
|||
int *num;
|
||||
long big_num;
|
||||
char *a, *anum = 0;
|
||||
size_t i;
|
||||
size_t i, line = 1 /* Unix: delimited by '\n'. */;
|
||||
errno = 0; /* In case we are running it as part of another editor. */
|
||||
if(!cat_fp_to_str(stdin, &str)) goto catch;
|
||||
/*printf("<<<%s>>>\n", str.data);*/
|
||||
/* The first sentinel '\0' it stops, even though it could have more data,
|
||||
and we could conceivably use the length to continue; it's simple. */
|
||||
for(a = str.data; a = strpbrk(a, "-0123456789"); ) {
|
||||
/* It would be conceivable use the length to continue past the first
|
||||
sentinel '\0', but not that complex. */
|
||||
fprintf(stderr, "Read:\n<<<%s>>>\n", str.data);
|
||||
for(a = str.data; a = strpbrk(a, "-0123456789\n"); ) {
|
||||
if(*a == '\n') { line++; a++; continue; }
|
||||
if(*a == '-') { anum = a++; continue; }
|
||||
if(!(num = num_array_new(&nums))) goto catch;
|
||||
if(!anum || anum != a - 1) anum = a; /* Wasn't negative. */
|
||||
big_num = strtol(anum, &a, 0);
|
||||
if((!big_num || big_num == LONG_MIN || big_num == LONG_MAX) && errno)
|
||||
goto catch; /* Long conversion failed. */
|
||||
goto catch; /* Long conversion failed, (not all platforms.) */
|
||||
if(big_num < INT_MIN || big_num > INT_MAX)
|
||||
{ errno = ERANGE; goto catch; }
|
||||
*num = (int)big_num; /* Safe now. */
|
||||
*num = (int)big_num;
|
||||
}
|
||||
for(i = 0; i < nums.size; i++) printf("Extracted %d.\n", nums.data[i]);
|
||||
fprintf(stderr, "Extracted:\n");
|
||||
for(i = 0; i < nums.size; i++) printf("%d\n", nums.data[i]);
|
||||
success = EXIT_SUCCESS;
|
||||
goto finally;
|
||||
catch:
|
||||
perror("stdin");
|
||||
fprintf(stderr, "Line %lu ", line), perror("stdin");
|
||||
finally:
|
||||
char_array_(&str);
|
||||
num_array_(&nums);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/** X-macro for a minimal dynamic array. `MIN_ARRAY(name, type)`, where `name`
|
||||
/** X-macro for a minimal dynamic array: `MIN_ARRAY(name, type)`, where `name`
|
||||
is an identifier prefix that satisfies `C` naming conventions when mangled and
|
||||
`type` is defined tag-type associated therewith. When expanding the array,
|
||||
resizing may be necessary and incurs amortised cost; any pointers to this
|
||||
|
@ -72,7 +72,7 @@ static type *name##_array_new(struct name##_array *const a) { \
|
|||
type *const data = name##_array_buffer(a, 1); \
|
||||
return data ? name##_array_emplace(a, 1), data : 0; \
|
||||
} \
|
||||
/* They don't have to all be used, (destructor is important.) */ \
|
||||
/* It's perfectly valid that these functions are not used. */ \
|
||||
static void name##_unused_coda(void); static void name##_unused(void) { \
|
||||
name##_array(0); name##_array_new(0); name##_unused_coda(); } \
|
||||
static void name##_unused_coda(void) { name##_unused(); }
|
||||
|
|
Loading…
Reference in New Issue