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>