Can C fgets persuade a * not * string from a file?

In particular, the sample code here works fine, but only when the line is saved in a file.

Sometimes I need this to process the generated string (stored in a string variable), but I had problems convincing that the third parameter fgets works with string variables, because it is a pointer to a FILE structure .

Or maybe there is a functional equivalent to fgets that can be used in strings?

Any suggestions? Thanks!

+7
c string file fgets
source share
7 answers

In the spirit of hacking quick answers, here is the "sgets" I just wrote. It tries to emulate fgets, but with string input.

Edit The bug Monte pointed out (thanks) has been fixed. Madly gaining utility, believing that at least 15 other people with the same idea are desperate to do the same, do not lead to a well-tested code. Poorly. The original version included a newline on a subsequent call.

char *sgets( char * str, int num, char **input ) { char *next = *input; int numread = 0; while ( numread + 1 < num && *next ) { int isnewline = ( *next == '\n' ); *str++ = *next++; numread++; // newline terminates the line but is included if ( isnewline ) break; } if ( numread == 0 ) return NULL; // "eof" // must have hit the null terminator or end of line *str = '\0'; // null terminate this tring // set up input for next call *input = next; return str; } int main( int argc, char* argv[] ) { // quick and dirty test char *str = "abc\ndefghitjklksd\na\n12345\n12345\n123456\nabc\n\n"; char buf[5]; while ( sgets( buf, sizeof( buf ), &str )) printf( "'%s'\n", buf ); } 
+9
source share

The C standard library does not provide this functionality.

But AT & T's safe / fast I / O library allows memory streams to be included, and it also provides a wrapper code to use the FILE API with their extensions. The last update was from February 2005, so either they finally worked out all the mistakes, or they can no longer afford to support it now when Luke Wilson is on the payroll : - (

The package can be downloaded here .

+4
source share

sscanf should do this. Of course, the semantics are different.

+3
source share

If the string is already in memory, you can tokenize in new lines (either with strtok , if you are fine with changing the string, and if you do not need to worry about reconnecting or manually using strchr and copying to a separate buffer).

You would not get a platform-specific newline conversion, which usually gives you the stdio functions, so you need extra care if your lines in memory use, say, CRLF line terminators.

+2
source share

Use a pipe and then open the channel with fdopen to get FILE * , then read this.

 #include <stdio.h> int main (int argc, char *argv[]) { int pipes[2]; FILE *write; FILE *read; char buffer[1000]; pipe (pipes); read = fdopen (pipes[0], "r"); write = fdopen (pipes[1], "w"); fputs ("My\nlong\nstring\nin\nmany\nlines\n", write); fclose (write); while (fgets (buffer, sizeof(buffer), read) != NULL) { printf ("Found a line: %s", buffer); } fclose (read); return 0; } 
+2
source share

All you have to do is do a linear search of the strings in the string. Here is a small program to get you started writing your own streaming stream class.

 #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct StringStream StringStream; struct StringStream { const char *data; const char *position; }; StringStream * stringstream_new(const char *data) { StringStream *self = malloc(sizeof (StringStream)); self->data = self->position = data; return self; } void stringstream_delete(StringStream *self) { free(self); } char * stringstream_gets(char *s, int n, StringStream *self) { const char * eol; int i, len; if (NULL == self->position || '\0' == *self->position) return NULL; eol = strchr(self->position, '\n'); if (eol) { len = eol - self->position + 1; len = len <= n ? len : n - 1; for (i = 0; i < len; ++i) s[i] = *self->position++; } else { for (i = 0; *self->position && i < n; ++i) s[i] = *self->position++; if ('\0' == *self->position) self->position = NULL; else ++self->position; } s[i] = '\0'; return s; } int main(int argc, char * argv[]) { static const int LEN = 100; static const char TEST_STRING[] = "line 0\n" "line 1\n" "line 2\n" "line 3\n" "line 4\n" "line 5\n" "line 6\n" "line 7\n" "line 8\n" "line 9\n"; StringStream *stream; char buf[LEN]; stream = stringstream_new(TEST_STRING); while (stringstream_gets(buf, LEN, stream)) printf("gets: %s\n", buf); stringstream_delete(stream); return 0; } 
+1
source share

i modified source code of fgets function:

 size_t my_fgets( inBuf , n , outBuf ) unsigned char *inBuf; size_t n; unsigned char *outBuf; { size_t len = 0; unsigned char *s; unsigned char *p, *t; if (n <= 0) /* sanity check */ return (-1); p = inBuf; s = outBuf; n--; /* leave space for NUL */ while (n != 0) { len = n; t = memchr((void *)p, '\n', strlen(p)); //printf ("'p' found at position %d.\n", t -p + 1); if (t != NULL) { len = ++t -p; (void)memcpy((void *)s, (void *)p, len); s[len] = 0; return len; } (void)memcpy((void *)s, (void *)p, len); s += len; n -= len; } *s = 0; return len; } 

and main function:

 int main(void) { char *inBuf = "this \n" "is \n" "test \n"; char outBuf[1024]; my_fgets(inBuf,strlen(inBuf),outBuf); printf("outBuf:%s \n",outBuf); return 0; } 

and conclusion:

 outBuf:this 
0
source share

All Articles