equivalent of fgets on a buffer?
Asked Answered
L

5

6

I was originally parsing a file line by line using fgets().

Now I changed things so that I already have my entire file in a buffer. I still like to read that buffer line by line for parsing purposes. Is there something designed for this, or do I need to make a loop that inspects for 0x0A chars at this point?

Lessee answered 17/9, 2011 at 15:44 Comment(5)
if you're using C++, have a look at istringstream which allows you to 'read from a string in memory'.Cheapskate
You've tagged this c and c++ ... which is it? And how is your buffer defined?Synectics
Decide whether you want to write C code or C++ code. Then come back and ask how to do that. I'm not gonna waste my time on writing a C++ solution for you when you might dismiss it as "not C enough".Trinitroglycerin
I am using C++ but I prefer to use the C functions like fopen when it is straightforward to implement using them.Lessee
If you writing a lexer why not write it in flex, it's blazingly fast and gets it right every time. It will give you both C and C++ outputs and you can write callbacks once you receive a token to your heart's content for either.Pushup
H
7

memchr (with a little bit of your own wrapper code, ending with memcpy) is the exact equivalent - like fgets it takes a maximum length it will process (should be the min of the remaining input buffer size and the size of your output buffer) and scans until it hits the desired character (which will be '\n') or runs out of input/output space.

Note that for data already in a buffer in memory, though, you might want to skip the step of copying to a separate output buffer, unless you need to null-terminate the output without modifying the input. Many beginner C programmers often make the mistake of thinking they need null termination, when it would really suffice to just improve some of your interfaces to take a (pointer, length) pair, allowing you to pass/process substrings without copying them. For instance you can pass them to printf using: printf("%.*s", (int)length, start);

Haste answered 17/9, 2011 at 16:42 Comment(1)
Thanks for pointing out memchr. I have never used it but I have used strrchr before and this is quite convenient. ThanksLessee
L
2

You could use the sscanf function for this. If you actually need a whole line, something like this should do the trick:

sscanf(your_buffer, "%50[^\n]", line);

(This will read lines at most 50 chars long. As always, careful with the length and 0 terminators. And check the return value of sscanf in case something went wrong.)

You can use pointer arithmetics to move your buffer along (just add "returned" line length + 1).

Lavation answered 17/9, 2011 at 15:51 Comment(0)
J
0

There is sscanf which may or may not work for you.

Jewett answered 17/9, 2011 at 15:48 Comment(3)
doesn't seem like sscanf provides me with a pointer to the end of the matched string, though. I'd still need to do a search.Lessee
It returns int number of bytes processed.Jewett
I was fairly sure it returns the number of matches it made.Lessee
C
0

If you're looking for C functions, strtok() and strsep() will both split a string on a specified character.

Cenozoic answered 17/9, 2011 at 16:14 Comment(2)
I know for sure that strtok will modify the underlying string, which may not really be suited to the task, what of strstep ?Doornail
Yes, both functions modify the string in place. You'll need to cook something up with strchr / memcpy if you don't want that.Cenozoic
T
0

For C, this should work, I think:

// str (in/out): the unconsumed portion of the input string
static char *sgets(char *buf, int n, const char **str)
{
    const char *s = *str;
    const char *lf = strchr(s, '\n');
    int len = (lf == NULL) ? strlen(s) : (lf - s) + 1;

    if (len == 0)
        return NULL;
    if (len > n - 1)
        len = n - 1;

    memcpy(buf, s, len);
    buf[len] = 0;
    *str += len;
    return buf;
}
Tindle answered 10/6, 2021 at 21:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.