2

Brand new to C here. The program is supposed to read in a file of fragments on a single line, separated by a "#" before and after them. For example #fragment1##fragment2##fragment3#

The two errors I want to check for are that a fragment is not over 1000 characters, and that the file follows the correct format of "#" on either side of fragments. I don't really get how fscanf syntax works but I think the following would check for the errors:

  char buffer[MAX_FRAG_LEN+1];
  if (fscanf(fp, "#%1000[^#]#", buffer) == 1) {
    return strdup(buffer);
  } else {
    fprintf(stderr, "Error! Incorrect format.\n");
  }

However, I want to separate the errors so I can specifically deliver a message of which of the two it was. How can I make the checks individually? Much appreciated!

Jason Block
  • 155
  • 1
  • 3
  • 9
  • 1
    It would probably be easier to read the whole line into a buffer and either run through the array checking for your conditions or passing it to strtok() and let it break it up for you. – Duck Jul 10 '12 at 01:19

1 Answers1

1

To make your technique work, you should manually check if the next character after the buffer is a '#' after fscanf returns. This allows you to distinguish a too long string error from a missing "##" error.

  char buffer[MAX_FRAG_LEN+1];
  if (fscanf(fp, "#%1000[^#]", buffer) == 1) {
    int c = fgetc(fp);
    if (c == '#') return strdup(buffer);
    if (c != EOF) {
      ungetc(c, fp);
      fprintf(stderr, "Error! More than 1000 characters.\n");
    } else {
      fprintf(stderr, "Error! Last fragment did not end with '#'.\n");
    }
  } else {
    fprintf(stderr, "Error! Fragment did not start with '#'.\n");
  }

However, using fscanf for parsing is generally tricky. If the input is in a totally unexpected format, it can be difficult to recover from them correctly. So, it is usually easier to handle errors by reading in the entire line in a single buffer, and then parse that line instead, as suggested by Duck.

jxh
  • 69,070
  • 8
  • 110
  • 193
  • You should call `ungetc()` to put back the char, so it will be in the input stream for the next call to `fscanf()`. – steveha Jul 10 '12 at 01:43
  • @steveha: Good point, but only for the non EOF failure case. Thanks – jxh Jul 10 '12 at 01:46