kjb@zycad.UUCP (Kevin Buchs) (11/22/87)
I want to print out a string whose length I will not know ahead, and which is not null terminated. I thought the following use of the asterisk precision delimiter would work: char *a = "hello"; int i; for (i=0; i<6; i++) printf("%*s\n", i, a); I thought it would print: h he hel hell hello but I got: hello hello hello hello hello Does the asterisk not work with the s descriptor? Or, am I using it wrong. Is there another way to do this (except fwrite)? -- Kevin Buchs 3500 Zycad Dr. Oakdale, MN 55109 (612)779-5548 Zycad Corp. {rutgers,ihnp4,amdahl,umn-cs}!meccts!nis!zycad!kjb
moran@yale.UUCP (11/23/87)
In article <692@zycad.UUCP> kjb@zycad.UUCP (Kevin Buchs) writes: > >I want to print out a string whose length I will not know ahead, and which >is not null terminated. I thought the following use of the asterisk >precision delimiter would work: > >char *a = "hello"; int i; >for (i=0; i<6; i++) printf("%*s\n", i, a); ...some examples omitted > >Does the asterisk not work with the s descriptor? Or, am I using it wrong. >Is there another way to do this (except fwrite)? I think the reason is that the i would specify the minimum field width, and in this case, the field would always be larger than that. Running this will show you what is really going on here. main() { static char a[2] = "h"; int i; for(i=0;i<6;i++) printf("foo%*s string\n",i,a); } it looks like -> fooh string fooh string foo h string foo h string foo h string foo h string So, in answer to your question: no, * sets a min. width not the actual width. Perhaps you should look at the BSD routines which deal with strings which are not null terminated i.e. you could copy the string segement into one which is null terminated and then print that, but it isn't really clear to me whether printing the pieces is important to you. William L. Moran Jr. moran@{yale.arpa, cs.yale.edu, yalecs.bitnet} ...{ihnp4!hsi,decvax}!yale!moran Gonna get my PhD...I'm a teenage lobotomy! - The Ramones
hunt@spar.SPAR.SLB.COM (Neil Hunt) (11/23/87)
In article <692@zycad.UUCP> kjb@zycad.UUCP (Kevin Buchs) writes: > >I want to print out a string whose length I will not know ahead, and which >is not null terminated. I thought the following use of the asterisk >precision delimiter would work: > >char *a = "hello"; int i; >for (i=0; i<6; i++) printf("%*s\n", i, a); > >I thought it would print: > >h >he >hel >hell >hello > >but I got: > >hello >hello >hello >hello >hello > >Does the asterisk not work with the s descriptor? Or, am I using it wrong. >Is there another way to do this (except fwrite)? The format "%8s" prints a string in a min field width of 8 characters. The format "%.8s" trucactes a string to a max field width of 8. I just tried it, and the same applies to a variable specified field: try: char *a = "hello"; int i; for (i=0; i<6; i++) printf("%.*s\n", i, a); which prints what you were expecting. Neil/.
lvc@tut.UUCP (11/24/87)
In article <692@zycad.UUCP>, kjb@zycad.UUCP (Kevin Buchs) writes: > > I want to print out a string whose length I will not know ahead, and which > is not null terminated. I thought the following use of the asterisk > precision delimiter would work: > > char *a = "hello"; int i; > for (i=0; i<6; i++) printf("%*s\n", i, a); > > ... * here is the minimum field length , use .* for the precision. See K&R pg 146-147. For your example you need: for (i=0; i<6; i++) printf("%.*s\n", i, a); Larry Cipriani AT&T Network Systems at cbosgd!osu-cis!tut!lvc Ohio State University
moore@prefect.uucp (Peter Moore) (11/24/87)
what you want is: printf("%.*s", i, string); In a declaration of the form %10.5s, the 10 is the minimum width that the string will take, being padded if necessary. The 5 is the maximum number of characters from the string that will be printed. Peter Moore
fauman@cgl.ucsf.edu (Eric Fauman%Stroud) (11/24/87)
In article <692@zycad.UUCP> kjb@zycad.UUCP (Kevin Buchs) writes: > >I want to print out a string whose length I will not know ahead, and which >is not null terminated. I thought the following use of the asterisk >precision delimiter would work: > >char *a = "hello"; int i; >for (i=0; i<6; i++) printf("%*s\n", i, a); > >Does the asterisk not work with the s descriptor? Or, am I using it wrong. The number following the % is a width specifier, which in the case of a string > is the minimum width to use. To specify the precision, the number should follow the %, an optional width field, and a period. The following code will produce the desired output: char *cp; int i; cp = "hello"; for (i=1;i<6;++i) printf("%.*s\n",i+1,cp); Eric Fauman - University of California - San Francisco
ark@alice.UUCP (11/24/87)
In article <692@zycad.UUCP>, kjb@zycad.UUCP writes: > > I want to print out a string whose length I will not know ahead, and which > is not null terminated. I thought the following use of the asterisk > precision delimiter would work: > > char *a = "hello"; int i; > for (i=0; i<6; i++) printf("%*s\n", i, a); Almost. You want to say for (i=0; i<6; i++) printf("%*.s\n", i, a); When printing a string (or anything else), the number immediately after the % means the "field width" and represents the MINIMUM amount of space the field should occupy in the output. The number after the . means different things for different format types; for strings it represents the MAXIMUM number of characters transferred to the output.
msb@sq.UUCP (11/27/87)
There have been several followups to this one, but they have all missed a significant point. > I want to print out a string whose length I will not know ahead, and which > is not null terminated. > [I tried] ... printf("%*s\n", i, a); Most people pointed out that he meant "%.*s". However, according to the ANSI Draft Standard, that usage is NOT portable. The reason is that the Draft requires that the argument a "shall be a pointer to a string". And a string is defined as "an array of characters *terminated by a null character*" [my emphasis]. This means that an implementation may, on encountering the above, cheerfully go on reading characters past the end of a until it runs off the end of memory (or the segment of memory) and aborts... no matter what the value of i is. Fully portable ways to do this would be: [1] { int j; for (j = 0; j < i; ++j) putchar (a[j]); } putchar ('\n'); [2] { char *tmp = malloc (j+1); if (!tmp) abort(); strncpy (tmp, a, j); tmp[j] = 0; printf ("%s\n", tmp); free (tmp); } If you know a maximum size for a, you can avoid the malloc(). If a is known not to be const, there is also: [3] if (j) { char last = a[j-1]; a[j-1] = '\0'; printf ("%s%c", a, last); a[j-1] = last; } putchar ('\n'); It seems to me that both [1] and [2] are likely to be significantly slower than the "%.*s" method, which I expect will work on most or all existing implementations; and [3] is ugly and not always usable. I can't think of another reasonable approach, anyway. (You can't use fwrite(), for instance, because the Draft allows an implementation to distinguish text streams from binary streams.) Doug Gwyn pointed out the "string" requirement to me when I asked him by email about the acceptability of printf ("%.1s", &char_variable) to print a char unless it was a null. I agreed that this was a minor convenience at best. But thinking about the above example, and what you'd have to do, does make me wonder whether the Committee really considered this point before deciding to restrict all forms of %s to "strings". They might have decided that C was so strongly oriented to null-terminated strings that anyone who wants to use data structures like a is doing so at their own risk; or it might just have slipped by. You there, Doug? Mark Brader, SoftQuad Inc., Toronto "Suspicion breeds confidence." utzoo!sq!msb, msb@sq.com -- BRAZIL
gwyn@brl-smoke.ARPA (Doug Gwyn ) (11/28/87)
In article <1987Nov27.024339.12253@sq.uucp> msb@sq.UUCP (Mark Brader) writes:
-... But thinking about the above example, and what you'd have to do,
-does make me wonder whether the Committee really considered this point
-before deciding to restrict all forms of %s to "strings". They might have
-decided that C was so strongly oriented to null-terminated strings that
-anyone who wants to use data structures like a is doing so at their own
-risk; or it might just have slipped by. You there, Doug?
Hi. I think the idea was that X3J11 wanted to allow the implementation
to be able to snarf up the argument with strcpy() etc. and this required
insisting that it be a properly-formed string. However, I might misremember.
msb@sq.UUCP (11/29/87)
To my question of why X3J11 did require that a %s-with-precision ("%.2s") only be guaranteed to work with null-terminated strings, Doug Gwyn said: > I think the idea was that X3J11 wanted to allow the implementation > to be able to snarf up the argument with strcpy() etc. I hope that's not all it was. "etc." says it. Use strncpy()! There might also be case for removing the restriction on the grounds of conformance with existing practice, depending on the behavior of the widely used implementations. I'm sure I'm not the only one who's assumed in good faith that the null was not needed. I realize it's quite late, but the more I think about it the more I think that the restriction is unreasonable and should be lifted. What chance? Mark Brader "The last 10% of the performance sought contributes Toronto one-third of the cost and two-thirds of the problems." utzoo!sq!msb, msb@sq.com -- Norm Augustine
gwyn@brl-smoke.ARPA (Doug Gwyn ) (12/01/87)
In article <1987Nov29.082912.2800@sq.uucp> msb@sq.UUCP (Mark Brader) writes: >I realize it's quite late, but the more I think about it the more I >think that the restriction is unreasonable and should be lifted. >What chance? Presumably if you get your comments into X3 or Tom Plum this week, flagged as an "unsatisfactory response" received on one of your formal review comments, X3J11 will be obliged to consider them at the meeting next week. The plan is for this to be the last meeting at which substantive changes to the draft proposed ANS will be made, but nobody knows whether things will happen that way. So long as we keep making changes, publication of the C standard keeps getting delayed. A lot of people really want to get the standard out soon.