[comp.lang.c] Can pre-ANSI C Preprocessor handle symbolic constants in strings?

dlbres14@pc.usl.edu (Brumley David M) (05/31/91)

In ANSI C it seems possible to use the Preprocessor to do macro
substitution of constants in strings:

#define FIELDSIZE 42
#define quote(val) #val

char buffer[FIELDSIZE+1];
...
/* read a field of length FIELDSIZE */
scanf("%" quote(FIELDSIZE) "s", buffer); 
...

So that after the Preprocessor, the 'scanf' call becomes:

scanf("%42s", buffer);


Question:  How do I do this with a preprocessor that doesn't
understand the new ANSI '#' operator nor string concatenation?  Do I
have to build the string argument dynamically (allocating an extra
buffer in the process)?

P.S. I've searched the FAQ list, and the Second (ANSI) edition of K&R
to no avail.  


	
--
David M. Brumley
<dmb8516@usl.edu>

bliss@sp64.csrd.uiuc.edu (Brian Bliss) (05/31/91)

the following work on a sun and most other non-ANSI cpp's:

#define quote(x) "x"

if you're afraid that some preprocessor won't do macro substitution
inside strings, try:

#define quote2(x) "x
#define quote(x) quote2(x")

bb

bliss@sp64.csrd.uiuc.edu (Brian Bliss) (05/31/91)

oops! that second example should be:

#define quote2(x) "x
#define quote(x) quote2(x)"
bb

dlbres14@pc.usl.edu (Brumley David M) (06/01/91)

In article <1991May31.154937.24240@csrd.uiuc.edu> bliss@sp64.csrd.uiuc.edu (Brian Bliss) writes:
>   the following work on a sun and most other non-ANSI cpp's:
>
>   #define quote(x) "x"
>
This doesn't work on the compiler in question (Laser C on an Atari
ST, admittedly not a canonical compiler) which doesn't substitute for
quoted arguments.  The C compiler on our university's Pyramid-90x
running OSx4.1 does the substitution (and hence is less compliant with
ANSI than the PC compiler), but only once.  So that with:

	#define CONSTANT 42
	#define quote(x) "x"

	printf(quote(CONSTANT));

we get 
	printf("CONSTANT"); 
not
	printf("42");

In any case this is all academic without string concatenation.


 

--
David M. Brumley
<dmb8516@usl.edu>

rjohnson@shell.com (Roy Johnson) (06/04/91)

In article <DLBRES14.91May31050315@pc.usl.edu> dlbres14@pc.usl.edu (Brumley David M) writes:
> In ANSI C it seems possible to use the Preprocessor to do macro
> substitution of constants in strings:

> #define FIELDSIZE 42
> #define quote(val) #val

> char buffer[FIELDSIZE+1];
> ...
> /* read a field of length FIELDSIZE */
> scanf("%" quote(FIELDSIZE) "s", buffer); 
> ...

> So that after the Preprocessor, the 'scanf' call becomes:

> scanf("%42s", buffer);

> Question:  How do I do this with a preprocessor that doesn't
> understand the new ANSI '#' operator nor string concatenation?  Do I
> have to build the string argument dynamically (allocating an extra
> buffer in the process)?

You might, for this example, want to do

scanf("%*s", FIELDSIZE, buffer);

which is standard/portable.  Otherwise you will have to hack
string concatenation until you get an ANSI compiler.
--
=============== !You!can't!get!here!from!there!rjohnson ===============
Feel free to correct me, but don't preface your correction with "BZZT!"
Roy Johnson, Shell Development Company

scs@adam.mit.edu (Steve Summit) (06/05/91)

In article <RJOHNSON.91Jun4101340@olorin.shell.com> rjohnson@shell.com (Roy Johnson) writes:
>In article <DLBRES14.91May31050315@pc.usl.edu> dlbres14@pc.usl.edu (Brumley David M) writes:
>> /* read a field of length FIELDSIZE */
>> scanf("%" quote(FIELDSIZE) "s", buffer); 
>> So that after the Preprocessor, the 'scanf' call becomes:
>> scanf("%42s", buffer);

>You might, for this example, want to do
>scanf("%*s", FIELDSIZE, buffer);
>which is standard/portable.

I won't say "BZZT!", because I had halfway composed an article
making the same suggestion, until I noticed that Mr. Brumley had
asked about *scanf*, not printf.  There's this thoroughly
annoying asymmetry between printf and scanf: for scanf, the '*'
format-specifier flag indicates assignment suppression, *not*
that the field width should be picked up from the argument list.
Building a format string (either at compile time with string
concatenation if you can hack it, or at run time with strcat
and/or sprintf) is really what you have to do to get "variable"
scanf field widths (unless you have an 8-10th edition scanf...).

                                            Steve Summit
                                            scs@adam.mit.edu

rjohnson@shell.com (Roy Johnson) (06/10/91)

In article <1991Jun4.201629.29013@athena.mit.edu> scs@adam.mit.edu (Steve Summit) writes:
> In article <RJOHNSON.91Jun4101340@olorin.shell.com> rjohnson@shell.com (Roy Johnson) writes:
> >In article <DLBRES14.91May31050315@pc.usl.edu> dlbres14@pc.usl.edu (Brumley David M) writes:
> >> /* read a field of length FIELDSIZE */
> >> scanf("%" quote(FIELDSIZE) "s", buffer); 
> >> So that after the Preprocessor, the 'scanf' call becomes:
> >> scanf("%42s", buffer);

> >You might, for this example, want to do
> >scanf("%*s", FIELDSIZE, buffer);
> >which is standard/portable.

> I won't say "BZZT!", because I had halfway composed an article
> making the same suggestion, until I noticed that Mr. Brumley had
> asked about *scanf*, not printf.  There's this thoroughly
> annoying asymmetry between printf and scanf: for scanf, the '*'
> format-specifier flag indicates assignment suppression, *not*
> that the field width should be picked up from the argument list.
> Building a format string (either at compile time with string
> concatenation if you can hack it, or at run time with strcat
> and/or sprintf) is really what you have to do to get "variable"
> scanf field widths (unless you have an 8-10th edition scanf...).

You're right; I bone-headed it (cancelled my other posting
after seeing your correction, too).

In compensation, I illustrate your suggestion:

char fmt[10];

/* The first two %'s make one % in the string */
sprintf(fmt, "%%%ds", FIELDSIZE);
scanf(fmt, buffer);

which is, dare I say, standard, portable, and correct?
--
=============== !You!can't!get!here!from!there!rjohnson ===============
Feel free to correct me, but don't preface your correction with "BZZT!"
Roy Johnson, Shell Development Company

dlbres14@pc.usl.edu (Brumley David M) (06/12/91)

In article <RJOHNSON.91Jun10114252@olorin.shell.com> rjohnson@shell.com (Roy Johnson) writes:
   In compensation, I illustrate your suggestion:

   char fmt[10];

   /* The first two %'s make one % in the string */
   sprintf(fmt, "%%%ds", FIELDSIZE);
   scanf(fmt, buffer);

   which is, dare I say, standard, portable, and correct?

Yes, I just can't believe you have to build the format string
dynamically with pre-ANSI compilers.
--
David M. Brumley
<dmb8516@usl.edu>