[comp.lang.c] Talking about scanf

martin@mwtech.UUCP (Martin Weitzel) (11/15/90)

In article <VXogs2w163w@cybrspc> roy%cybrspc@cs.umn.edu (Roy M. Silvernail) writes:
>[about reading formatted input] It's better, IMHO, to gets() a whole
>line, check its validity and _then_ sscanf() it into the target
>variables. (no need for strtol() or similar, since sscanf() looks at the
>validated string just as scanf() would have looked at the original
>input) It just makes things more bullet-resistant.

I agree completly, except for one point: Bullet resistant
programs should never use gets() -- fgets() is the way to go!

BTW: Recently there occured a problem, to which I couldn't find an
immediate solution. Take the following program fragment:

	#define X 100
	char word[X+1]; int z;

	scanf("%100[^:]:%d", word, &z);
	        ^^^----------------------- I'd rather want X here; still
	           better were `(sizeof word) - 1', so that I could ommit
	           the #define for X completly

What I want is to have only *one* place where I define the length of
a word. In this example, if I change the #define of X, I must never
forget to make a change at a second place, which may be far away from
the first.

What I could do is dynamically (at runtime) construct an appropriate
format specification. But IMHO this more a work-around than an elegant
solution to the problem.
-- 
Martin Weitzel, email: martin@mwtech.UUCP, voice: 49-(0)6151-6 56 83

fisher@sc2a.unige.ch (11/16/90)

In article <960@mwtech.UUCP>, martin@mwtech.UUCP (Martin Weitzel) writes:
> [...]
> BTW: Recently there occured a problem, to which I couldn't find an
> immediate solution. Take the following program fragment:
> 
> 	#define X 100
> 	char word[X+1]; int z;
> 
> 	scanf("%100[^:]:%d", word, &z);
> 	        ^^^----------------------- I'd rather want X here; still
> 	           better were `(sizeof word) - 1', so that I could ommit
> 	           the #define for X completly

Yeah, it would be nice if we could have a `scanf("%*s", sizeof(word), word)'
printf-like type of construct, but then the `*' is already used for something
else...

As another workaround, it seems that some compilers *do* expand macros inside
strings and character constants, in which case you could use the `X' there.
If not, try to look in the the `Token Replacement' chapter of your compiler's
`User Guide'.  In TC, for example, you can "stringize" a macro, with the `#'
symbol (i.e. `#X' is converted to `"100"').  Another feature of TC is the
automatic concatenation of string literals (i.e. `"hello " "world"' becomes
`"hello world"').  With these features, you can rewrite your example as

	scanf("%" #X "[^:]:%d", word, &z);

Not really portable, you this can be useful.

Markus Fischer, Dpt of Anthropology, Geneva.

scjones@thor.UUCP (Larry Jones) (11/17/90)

In article <960@mwtech.UUCP>, martin@mwtech.UUCP (Martin Weitzel) writes:
> BTW: Recently there occured a problem, to which I couldn't find an
> immediate solution. Take the following program fragment:
> 
> 	#define X 100
> 	char word[X+1]; int z;
> 
> 	scanf("%100[^:]:%d", word, &z);
> 	        ^^^----------------------- I'd rather want X here; still
> 	           better were `(sizeof word) - 1', so that I could ommit
> 	           the #define for X completly
> 
> What I could do is dynamically (at runtime) construct an appropriate
> format specification. But IMHO this more a work-around than an elegant
> solution to the problem.

Yes.  I never did understand why printf allowed "*" for run-time
specification of field width and precision, but scanf usurped "*"
for assignment suppression and so doesn't support run-time field
widths.

Any historians know how this came to be?
----
Larry Jones                         UUCP: uunet!sdrc!thor!scjones
SDRC                                      scjones@thor.UUCP
2000 Eastman Dr.                    BIX:  ltl
Milford, OH  45150-2789             AT&T: (513) 576-2070
Physical education is what you learn from having your face in
someone's armpit right before lunch. -- Calvin

karl@ima.isc.com (Karl Heuer) (11/18/90)

In article <1990Nov16.125504.305@sc2a.unige.ch> fisher@sc2a.unige.ch writes:
>As another workaround, it seems that some compilers *do* expand macros inside
>strings and character constants, in which case you could use the `X' there.

I refuse to believe that.  Some non-ANSI preprocessors expand *macro
arguments* inside string literals within the macro, but I've never heard of
one that expanded macros in string literals in the program.  It would break
too much code.

>In TC, for example, you can "stringize" a macro...

It's not a TC invention; stringizing and string literal pasting are available
in all ANSI C compilers.  Note that it doesn't help you if X was defined as an
expression like `(99+1)', since the C preprocessor (unlike, say, m4) doesn't
have a way to reduce constant expressions.

Karl W. Z. Heuer (karl@ima.isc.com or uunet!ima!karl), The Walking Lint

avery@netcom.UUCP (Avery Colter) (11/22/90)

martin@mwtech.UUCP (Martin Weitzel) writes:

>	scanf("%100[^:]:%d", word, &z);
>	        ^^^----------------------- I'd rather want X here; still
>	           better were `(sizeof word) - 1', so that I could ommit
>	           the #define for X completly

>What I could do is dynamically (at runtime) construct an appropriate
>format specification. But IMHO this more a work-around than an elegant
>solution to the problem.

It may be the only way unfortunately, unless you have some interesting
preprocessor at your disposal. 

How about just defining a string and an unsigned, uhh, lessee, assign
X to the unsigned, then make sscanf(string," %u",&uns.int), and then
a couple of strcats to put the rest of the format string around it,
and voilla. What is inelegant about this?

Or am I dealing with people who think that code has to be
a candidate for the SI Swimsuit Issue to be called elegant?

-- 
Avery Ray Colter    {apple|claris}!netcom!avery  {decwrl|mips|sgi}!btr!elfcat
(415) 839-4567   "I feel love has got to come on and I want it:
                  Something big and lovely!"         - The B-52s, "Channel Z"

avery@netcom.UUCP (Avery Colter) (11/22/90)

Oh yes...

Another thing in scanf's favor over gets...

While reading the new and improved 10 commandments, I was reminded of
gets' nasty habit of taking any size line given to it.

But I suppose fgets takes care of that... you just have to whack off
the endline character somehow.
-- 
Avery Ray Colter    {apple|claris}!netcom!avery  {decwrl|mips|sgi}!btr!elfcat
(415) 839-4567   "I feel love has got to come on and I want it:
                  Something big and lovely!"         - The B-52s, "Channel Z"

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (11/23/90)

In article <17295@netcom.UUCP>, avery@netcom.UUCP (Avery Colter) writes:
> Another thing in scanf's favor over gets...

> While reading the new and improved 10 commandments, I was reminded of
> gets' nasty habit of taking any size line given to it.

Why is this a point in favour of scanf()?
	scanf("%[^\n]%*c", buff) >= 0
and
	gets(buff) != NULL
do pretty much the same thing; scanf() will "take any size line given to it".

-- 
I am not now and never have been a member of Mensa.		-- Ariadne.