newline - Using fscanf() to read a file with lines of 3 numbers each,why does "%d%d%d%*c" act as good as "%d%d%d"? -


i know %d format specifier,when used here in fscanf(), reads integer , ignores white-space preceding it,including newline(i verified it).but in following program uses fscanf() read file of multiple lines 3 integers each,the format string "%d%d%d%*c" works "%d%d%d".

why so?since fscanf() used %d first format specifier in format specifier string ignores whitespace preceding integer, why doesn't %*c used last specifier cause error or side-effect?had %d specifier not been ignoring newline after each group of 3 numbers in line,then %*c have make sense eat away newline.but why works without error or side-effect if fscanf() ignores whitespace %d default? shouldn't fscanf() stop scanning when %*c can't find character eat , there mismatch between specifier , input? isn't fscanf() supposed stop when there mismatch,just scanf() does?

edit: works if use "%*c%d%d%d"!!shouldn't scanning , processing of subsequent characters stop once there mismatch between format specifier , input @ beginning?

#include <stdio.h> #include <stdlib.h>   int main () { int n1,n2,n3; file *fp; fp=fopen("d:\\data.txt","r");  if(fp==null) { printf("error"); exit(-1); }  while(fscanf(fp,"%d%d%d%*c",&n1,&n2,&n3)!=eof) //works line below //while(fscanf(fp,"%d%d%d",&n1,&n2,&n3)!=eof) printf("%d,%d,%d\n",n1,n2,n3); fclose(fp);  } 

here's format of data in file data.txt:

243 343 434 393 322 439 984 143 943 438 243 938 

output:

243 343 434 393 322 439 984 143 943 438 243 938 

consider variation of program in question:

#include <stdio.h> #include <stdlib.h>  int main(int argc, char **argv) {     char *file = "d:\\data.txt";     file *fp;     char *formats[] =     {     "%d%d%d%*c",     "%d%d%d",     "%*c%d%d%d",     };      if (argc > 1)         file = argv[1];      (int = 0; < 3; i++)     {         if ((fp = fopen(file, "r")) == 0)         {             fprintf(stderr, "failed open file %s\n", file);             break;         }         printf("format: %s\n", formats[i]);         int n1,n2,n3;         while (fscanf(fp, formats[i], &n1, &n2, &n3) == 3)             printf("%d, %d, %d\n", n1, n2, n3);         fclose(fp);     }     return 0; } 

the repeated opens not efficient, isn't concern here. clarity , showing behaviour more important.

it written (a) use file name specified on command line don't have futz names such d:\data.txt inconvenient create on unix systems, , (b) shows 3 formats in use.

given data file question:

243 343 434 393 322 439 984 143 943 438 243 938 

the output of program is:

format: %d%d%d%*c 243, 343, 434 393, 322, 439 984, 143, 943 438, 243, 938 format: %d%d%d 243, 343, 434 393, 322, 439 984, 143, 943 438, 243, 938 format: %*c%d%d%d 43, 343, 434 393, 322, 439 984, 143, 943 438, 243, 938 

note first digit of first number consumed %*c when first part of format. after first 3 numbers read, %*c reads newline after third number on line, %d skips further white space (except there isn't any) , reads number.

otherwise, behaviour expounded in commentary below, largely lifted related question.


some of code under discussion in related question use fscanf() read given line was:

fscanf(f, "%*d %*d %*d%*c"); fscanf(f, "%d%d%d", &num1, &num2, &num3); 

i noted code should test return value fscanf(). however, 3 %*d conversion specifications, might return value of eof if encountered eof before reaching specified line. you've no way of know first line contained letter instead of digit, unfortunately, until execute second fscanf(). should test second fscanf() too; might eof, or 0 or 1 or 2 (all of indicate problems), or might 3 indicating success 3 conversions. note adding \n format means blank lines skipped, going happen anyway; %d skips white space first digit.

is there other way can read ignore entire lines clumsily did fscanf(f,"%*d%*d%*d")?is using %*[^\n] nearest thing 1 can this?

the best way skip whole lines use fgets(), in last version of code in answer. obviously, there's outside chance miscount lines if of lines longer 4095 bytes. otoh, that's improbable.

i have confusion , don't want put in question. can tell me this—fscanf() ignores whitespace automatically, after first line, when 3 integers read , ignored according %*d%*d%*d specifier, expect fscanf() ignore newline when starts reading in next run of loop. why doesn't additional %*c or \n cause problems , program runs fine when use %*d%*d%*d%*c or %*d%*d%*d\n in code?

you can't tell went wrong formats; can detect eof, otherwise, fscanf() return 0. however, since %*d skips leading white space — including newlines — doesn't matter whether read newline after third number %*c or not, , when have \n there, that's white space read skips newline , trailing or leading white space, stopping when reaches non-white space character. of course, have newlines in middle of 3 numbers, or have more 3 numbers on line.

note trailing \n in format particularly weird when user typing @ terminal. user hits return, , keeps on hitting return, program doesn't continue until user types non-blank character. why fscanf() difficult use when data not reliable. when it's reliable, it's easy, if goes wrong, diagnostics , recovery painful. that's why better use fgets() , sscanf(); have control on being parsed, can try again different format if want to, , can report whole line, not fscanf() has not managed interpret.

note %c (and %*c) not skip on white space; therefore, %*c @ end of format reads (and discards) character after number read. if newline, that's character read , ignored. scan set %[...] other conversion specification not skip white space; other standard conversion specifications skip leading white space.


Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -