String for fscanf

I try to read a file with the following pattern:
"a,b,c,d,e,f\n"
"a,b,c,d,e,f\n"
...

a = 0-8 characters should be saved in buffer[8]
b = unsigned long long (0-17 characters, I don't need this later)
c = unsigned long long (0-17 characters, I don't need this later)
d = unsigned char (1 character)
e = unsigned char (2 characters)
f = unsigned char (1 character)

I would like to read line for line and save a in a char buffer[8], d in unsigned char move, e in unsigned char left and f in unsigned char state.
Can that be done with fscanf? I just can't manage to create a matching const char* format for fscanf.

Thank you for you answers.
If I understand you correctly:
1
2
3
char a[ 9 ];  /* extra char for null-terminator */
unsigned long b, c;  /* unused */
unsigned char d, e[ 2 ], f;

The fscanf() documentation here
http://www.cplusplus.com/reference/clibrary/cstdio/fscanf.html
is very good. It only seems to be missing information on scanset specifiers.

The only other unfortunate thing is that ISO C does not support the hh modifier, so you cannot scan unsigned chars directly. You must scan them in as an unsigned short and convert to char.

(Remember, signed char and unsigned char both represent byte-sized numbers, not ASCII characters.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* desired values */
char a[ 9 ];
unsigned char d, e[ 2 ], f;

/* temporaries */
unsigned short x[ 4 ];

/* read the values from file */
fscanf( f, "%8[^, \t\n\r], %*u, %*u, %hu, %hu %hu, %hu\n", a, x, x+1, x+2, x+3 );

/* convert those shorts to bytes */
d      = x[ 0 ];
e[ 0 ] = x[ 1 ];
e[ 1 ] = x[ 2 ];
f      = x[ 3 ];

You don't need to read everything at once. It is OK to split the format string up conveniently:
1
2
3
4
5
6
7
unsigned short x;
fscanf( f, "%8[^, \t\n\r],", a );
fscanf( f, "%*u, %*u," );
fscanf( f, "%hu,", &x ); d = x;
fscanf( f, "%hu ", &x ); e[ 0 ] = x;
fscanf( f, "%hu,", &x ); e[ 1 ] = x;
fscanf( f, "%hu\n", &x ); f = x;


Hope this helps.

[edit] Oh, yeah, you might want to google "scanf scanset specifiers", but the thing I specified is "a string of maximum length eight, composed of any characters except , space tab newline and carriage-return.
Last edited on
Thank you very much. What I was looking for was the not operator for scanf even though I didn't know that there is one.
The correct patter in my case is now: "%[^,], %*u, %*u, %hu, %hu, %*hu\n"
Width isn't even necessary, because there are never more than 8 bytes before the first comma.
Width isn't even necessary, because there are never more than 8 bytes before the first comma.

Width is always necessary. That is one of the reasons that scanf() is so dangerous --omitting the width is a security hole.

Just because input is always supposed to be formatted in a specific way doesn't mean that it always is in actuallity. Don't trust security concerns to those using the program (even if it is yourself).

BTW. You don't need to specify a size modifier (h) if you are using assignment suppression (*).

Glad to have been of help.
Topic archived. No new replies allowed.