0

I'm looking to have fscanf identify when a potential overflow happens, and I can't wrap my head around how best to do it.

For example, for a file containing the string

**a**bb**cccc**

I do a

char str[10];
while (fscanf(inputf, "*%10[^*]*", str) != EOF) {

}

because I'm guaranteed that what is between ** and ** is usually less than 10. But sometimes I might get a

**a**bb**cccc*

(without the last *) or even potentially a buffer overflow.

I considered using

while (fscanf(inputf, "*%10[^*]", str) != EOF) {

}

(without the last *) or even

while (fscanf(inputf, "*%10s*", str) != EOF) {

}

but that would return the entire string. I tried seeing if I could check for the presence or lack of a *, but I can't get that to work. I've also seen implementation of fgets, but I'd rather not make it complicated. Any ideas?

Rio
  • 14,182
  • 21
  • 67
  • 107

2 Answers2

3

While fscanf() seems to have been designed as a general purpose expression parser, few programmers rely on that ability. Instead, use fgets() to read a text line, and then use a parser of your choosing or design to dissect the text buffer.

Using the full features of fgets() is dodgy on different implementations and doesn't always provide full functionality, nor even get those implemented right.

wallyk
  • 56,922
  • 16
  • 83
  • 148
  • I think you meant `fscanf` where you wrote `fgets`? – zwol Apr 12 '11 at 04:31
  • @Zack: Nope, not `fscanf()` which sometimes works okay, but often doesn't or causes so much trouble you wish you had not used it. `fgets()` is a much more manageable i/o function: it reads until the buffer is full, or an end of line is encountered. Additional logic follows its call to do whatever fancy processing is needed. – wallyk Apr 12 '11 at 04:43
  • 1
    Right, but you're saying "fgets seems to have been designed as a general purpose expression parser" which doesn't make any sense (but does if you meant to write fscanf) – zwol Apr 12 '11 at 04:46
  • @Zack: thanks. I've corrected it. (Maybe now I'll get some votes?) – wallyk Apr 12 '11 at 05:28
2

I'm not clear on exactly what you want. Is it to skip over any number of stars, and then read up to 9 non-star characters into a buffer? If so, try this:

void read_field(FILE *fin, char buf[10])
{
    int c;
    char *ptr = buf;
    while ((c = getc(fin)) == '*')
        /*continue*/;
    while (c != '*' && c != EOF && ptr < buf+9)
    {
        *ptr++ = c;
        c = getc(fin);
    }
    *ptr = '\0';
    /* skip to next star here? */
}

You will note that I am not using fscanf. That is because fscanf is nearly always more trouble than it's worth. The above is more typing, but I can be confident that it does what I described it as doing.

zwol
  • 135,547
  • 38
  • 252
  • 361
  • Hm, but I was hoping to use fscanf... the idea is to read all of the characters within the stars or throw an error if it's above 10 characters. – Rio Apr 12 '11 at 04:41
  • Ok, then in that case just put "`if (ptr == buf+9) throw_error()`" after the second while loop. Really, trust us, you don't want `fscanf`. – zwol Apr 12 '11 at 04:47