2

I have file that will contain either two numbers with variable whitespace in between them or just a blank line. I need to know when the input is just a blank line, and then to not assign into those variables using fscanf.

Doing:

FILE *pFile = fopen (my_file, "r");
if (pFile == NULL) perror ("Error opening file");
int succ = 1, num1 = 0, num2 = 0; 
while (succ != EOF)
{
  succ = fscanf(pFile, "%d   %d", &num1, &num2);
}

Works very well for detecting all of the numbers properly, but not the newline. I tried:

fscanf(pFile, "%d   %d %*[^\n]", &num1, &num2);

But it always properly assigns to both numbers. I want to be able to make a switch statement to do other logic based on if succ is 2 (indicating both numbers were assigned too) or 0 (indicating a blank line).

I'd prefer avoiding getline if possible; seems like that would be inefficient to use iostream stuff mixed with stdio functions.

I tried this guys suggestion, didn't work out, although logically I thought it would work, it didn't.

Honestly, I don't even understand why something like

"%d   %d \n"

Wouldn't work. It's simple... scan the file until a newline, return back how many assignments were done, that's it!

Community
  • 1
  • 1
  • 1
    In C, I suggest using `fgets()`! Then `sscanf()` or some more elaborate parsing. No idea about C++. – pmg Jan 31 '15 at 17:34
  • I don't know how long the line will be, which is needed by the second parameter, I just need everything up to the newline –  Jan 31 '15 at 17:36
  • You can also use `getchar()` repeatedly. That's perhaps your best option. – pmg Jan 31 '15 at 17:37
  • According to this answer: http://stackoverflow.com/questions/13221844/fscanf-and-newline-character, add a space at the end of your format specifier, "%d %d ". – Thomas Matthews Jan 31 '15 at 17:37
  • @ThomasMatthews - A good thought, but in practice it doesn't change the behaviour of the program at all; Because I wan't to detect the blank line. That will eat the rest of the line, and the blank line, and then resume –  Jan 31 '15 at 17:40
  • `scanf` is used for formatted data (*scan formatted*). Your data is not formatted. You should try a solution not based on `scanf`. – pmg Jan 31 '15 at 17:46
  • If you need to know about line boundaries, the file I/O members of the `scanf()` family of functions are the wrong tools to be using; they mostly ignore newlines, simply treating them as white space. You need to read lines using [`fgets()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/fgets.html) or [`getline()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/getline.html) and then, perhaps, parsing them with [`sscanf()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/sscanf.html). – Jonathan Leffler Jan 31 '15 at 18:47

1 Answers1

2

"%d %d \n" will not work to achieve OP goals as any white-space directive consumes any white-space. Using ' ' or '\n' make no difference they both consume 0 or more white-spaces. (expect in '[]' specifiers)

OP wants to detect a '\n' and fscanf() is not a good choice. fgets() is better.

#define N (100 /* longest line */)
char buf[N];
while (fgets(buf, sizeof buf, pFile) != NULL) {
  int cnt = sscanf("%d%d",&num1, &num2);
  switch (cnt) {
     case 0: Handle_NoNumbers(); break; 
     case 1: Handle_1Number(); break; 
     case 2: Handle_Success(); break; 
  }
}

The '%d' in fscanf(stream, "%d", &num) specifies to consume all leading white-space before a number without regard to '\n' or ' ', etc.

If code must use fscanf(), then code needs to consume leading white-space before calling fscanf(... "%d") in a way to distinguish '\n' from ' '.

// Consume white space except \n and EOF
int consume_ws(FILE *pFile) {
  do {
    int c = fgetc(pFile);  // could use fscanf(...%c...) here
    if (c == '\n' || c == EOF) return c;
  } while (isspace(c));
  ungetc(c, pFile);  // put the char back
  return 0;
}

...
while(1) {
  int num[2];
  int i;
  for (i = 0; i < 2; i++) { 
    if (consume_ws(pFile)) {
      Handle_ScantData();  // Not enough data
      return;
    }
    if (1 != fscanf(pFile, "%d", &num[i]) {
      Handle_NonnumericData();
      return;
    }
  }
  int ch = consume_ws(pFile);
  if (ch == 0) Handle_ExtraData();

  // Else do something with the 2 numbers

  if (ch == EOF) return;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256