Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why "%d" is not equivalent to " %d" as a format string in scanf

Tags:

c

scanf

I'm reading a book and solving some problems. The question is

For each of the following pairs of scanf format strings, indicate whether or not the two strings are equivalent. If they're not, show how they can be distinguished.

(a) "%d" veruss " %d"

(b) "%d-%d-%d" versus "%d -%d -%d"

(c) "%f" versus "%f "

(d) "%f,%f" versus "%f, %f"

My solution is (a) they are equivalent since scanf discards the white space. For (b) they are not equivalent since scanf matches - with white space . For (c), they are not equivalent since scanf will put back the white space in the buffer. For (d), they are equivalent since scanf discards white space. According to the Chegg solutions, all preceding questions are not equivalent. Am I wrong? In this post, I would like to make sure that my answers are correct in comparison with Chegg solutions. I've already read the book and I have decent knowledge about scanf.

like image 510
CroCo Avatar asked Oct 29 '22 09:10

CroCo


1 Answers

"%d" and " %d" are the same per OP's reasoning.

They are certainly the same with expected numeric input like "123" and " 456". A remaining consideration would be where is the FILE pointer on failure as with "abc" versus " xyz"? "%d" by itself, first consumes leading white-space. So no difference.

... A conversion specification is executed in the following steps: C11dr §7.21.6.2 7

Input white-space characters ... are skipped, unless the specification includes a [, c, or n specifier. §7.21.6.2 8

then the conversion of text to numeric input (for "%d") happens.

Below code demonstrates equivalence.

void next_testi(const char *s, const char *fmt, const char *pad) {
  rewind(stdin);
  int i = 0;
  int count = scanf(fmt, &i);
  int next = fgetc(stdin);
  printf("format:\"%s\",%s count:%2d, i:%2d, next:%2d, text:\"%s\"\n", //
      fmt, pad, count, i, next, s);
}

void next_test(const char *s) {
  FILE *fout = fopen("test.txt", "w");
  fputs(s, fout);
  fclose(fout);

  freopen("test.txt", "r", stdin);
  next_testi(s, "%d", " ");
  next_testi(s, " %d", "");
  puts("");
}

int main() {
  next_test("3");
  next_test(" 4");
  next_test("");
  next_test(" ");
  next_test("+");
  next_test(" -");
  next_test("X");
  next_test(" Y");
}

Output

format:"%d",  count: 1, i: 3, next:-1, text:"3"  // scanf() return value 1:success
format:" %d", count: 1, i: 3, next:-1, text:"3"

format:"%d",  count: 1, i: 4, next:-1, text:" 4"
format:" %d", count: 1, i: 4, next:-1, text:" 4"

format:"%d",  count:-1, i: 0, next:-1, text:""  // scanf() return value EOF, next is EOF
format:" %d", count:-1, i: 0, next:-1, text:""

format:"%d",  count:-1, i: 0, next:-1, text:" "
format:" %d", count:-1, i: 0, next:-1, text:" "

format:"%d",  count: 0, i: 0, next:43, text:"+" // scanf() return value 0
format:" %d", count: 0, i: 0, next:43, text:"+"

format:"%d",  count: 0, i: 0, next:45, text:" -"
format:" %d", count: 0, i: 0, next:45, text:" -"

format:"%d",  count: 0, i: 0, next:88, text:"X"
format:" %d", count: 0, i: 0, next:88, text:"X"

format:"%d",  count: 0, i: 0, next:89, text:" Y"
format:" %d", count: 0, i: 0, next:89, text:" Y"
like image 164
chux - Reinstate Monica Avatar answered Nov 15 '22 07:11

chux - Reinstate Monica