#include <stdlib.h> #include <stdio.h> #include <ERRNO.H> #include <assert.H> #define MIN_LINE_ALLOCATION 64 int getstr(char **lineptr, size_t *n, FILE *stream, char terminator, int offset) { int ret; if (!lineptr || !n || !stream) { errno = EINVAL; return -1; } if (!*lineptr) { *n = MIN_LINE_ALLOCATION; *lineptr = (char*) malloc(sizeof(char) * (*n)); if (!*lineptr) { errno = ENOMEM; return -1; } } int nchars_avail = *n - offset; char *read_pos = *lineptr + offset; for (;;) { int save_errno; int c = getc(stream); save_errno = errno; assert((*lineptr + *n) == (read_pos + nchars_avail)); if (nchars_avail < 2) { if (*n > MIN_LINE_ALLOCATION) { *n *= 2; } else { *n += MIN_LINE_ALLOCATION; } nchars_avail = *n + *lineptr - read_pos; *lineptr = (char*)realloc(*lineptr, sizeof(char) * (*n)); if (!*lineptr) { errno = ENOMEM; return -1; } read_pos = *n - nchars_avail + *lineptr; assert((*lineptr + *n) == (read_pos + nchars_avail)); } if (ferror(stream)) { errno = save_errno; return -1; } if (c == EOF) { if (read_pos == *lineptr) { return -1; } else { break; } } *read_pos++ = c; nchars_avail--; if (c == terminator) { break; } } *read_pos = '\0'; ret = read_pos - (*lineptr + offset); return ret; } int getline(char **lineptr, size_t *n, FILE *stream) { return getstr(lineptr, n, stream, '\n', 0); } int wgetstr(wchar_t **lineptr, size_t *n, FILE *stream, wchar_t terminator, int offset) { int ret; if (!lineptr || !n || !stream) { errno = EINVAL; return -1; } if (!*lineptr) { *n = MIN_LINE_ALLOCATION; *lineptr = (wchar_t*)malloc(sizeof(wchar_t) * (*n)); if (!*lineptr) { errno = ENOMEM; return -1; } } int nchars_avail = *n - offset; wchar_t* read_pos = *lineptr + offset; for (;;) { int save_errno; register wint_t c = fgetwc(stream); save_errno = errno; assert((*lineptr + *n) == (read_pos + nchars_avail)); if (nchars_avail < 2) { if (*n > MIN_LINE_ALLOCATION) { *n *= 2; } else { *n += MIN_LINE_ALLOCATION; } nchars_avail = *n + *lineptr - read_pos; *lineptr = (wchar_t*) realloc(*lineptr, sizeof(wchar_t) * (*n)); if (!*lineptr) { errno = ENOMEM; return -1; } read_pos = *n - nchars_avail + *lineptr; assert((*lineptr + *n) == (read_pos + nchars_avail)); } if (ferror(stream)) { errno = save_errno; return -1; } if (c == WEOF) { if (read_pos == *lineptr) { return -1; } else { break; } } *read_pos++ = c; nchars_avail--; if (c == terminator) { break; } } *read_pos = L'\0'; ret = read_pos - (*lineptr + offset); return ret; } int wgetline(wchar_t **lineptr, size_t *n, FILE *stream) { return wgetstr(lineptr, n, stream, L'\n', 0); }
sample
FILE *hFile = fopen("input.txt", "r, ccs=UTF-8"); if (hFile) { wchar_t *lineptr = 0; size_t n = 0; while (wgetline(&lineptr, &n, hFile) != -1) { wprintf(L"%s", lineptr); } free(lineptr); fclose(hFile); }
int getstrstr(char **lineptr, size_t *n, const char** stream, char terminator, int offset) { int ret; if (!lineptr || !n || !(*stream)) { return -1; } if (!*lineptr) { *n = MIN_LINE_ALLOCATION; *lineptr = (char*)malloc(sizeof(char) * (*n)); if (!*lineptr) { return -1; } } int nchars_avail = *n - offset; char *read_pos = *lineptr + offset; for (;;) { int save_errno; int c = *(*stream); (*stream)++; assert((*lineptr + *n) == (read_pos + nchars_avail)); if (nchars_avail < 2) { if (*n > MIN_LINE_ALLOCATION) { *n *= 2; } else { *n += MIN_LINE_ALLOCATION; } nchars_avail = *n + *lineptr - read_pos; *lineptr = (char*)realloc(*lineptr, sizeof(char) * (*n)); if (!*lineptr) { return -1; } read_pos = *n - nchars_avail + *lineptr; assert((*lineptr + *n) == (read_pos + nchars_avail)); } if (c == 0) { if (read_pos == *lineptr) { return -1; } else { break; } } *read_pos++ = c; nchars_avail--; if (c == terminator) { break; } } *read_pos = '\0'; ret = read_pos - (*lineptr + offset); return ret; }
sample
char *slineptr = 0; size_t n = 0; const char *p = "a , b, c"; while (getstrstr(&slineptr, &n, &p, ',', 0) != -1) { printf("'%s'", slineptr); } free(slineptr);
reading a line from console
int getstr(char* lineptr, size_t n, FILE* stream, char terminator, int offset) { int ret; int nchars_avail = n - offset; char* read_pos = lineptr + offset; for (;;) { int save_errno; int c = getc(stream); save_errno = errno; assert((lineptr + n) == (read_pos + nchars_avail)); if (nchars_avail < 2) { return EACCES; } if (ferror(stream)) { errno = save_errno; return -1; } if (c == EOF) { if (read_pos == lineptr) { return -1; } else { break; } } if (c == terminator) { break; } *read_pos++ = c; nchars_avail--; } *read_pos = '\0'; ret = read_pos - (*lineptr + offset); return ret; } int main() { char str[100]; getstr(str, 100, stdin, '\n', 0); printf("%s", str); }