[comp.unix.wizards] scanf quiz question

cracraft@ccicpg.UUCP (Stuart Cracraft) (07/18/87)

Suppose you have a line from a file such as:

str1      str2 str3 str4 ... strN    # strN+1 ... strN+I
 ^                 ^                          ^
 |                 |                          |
 Store in s1       |                          |
		   Store in s2                Store in s3

The above line consists of three fields:
   1) str1
   2) str2 ... strN (where N is up to 10)
   3) strN+1 ... strN+I (where I is up to 10)
(strX represents an arbitrary-length string, up to 20 characters.)

You want to use scanf to parse this line, storing
each of the three fields in its own variable. The obvious

   scanf("%s %[^#] %s",s1,s2,s3)

successfully parses s1 & s2, but doesn't correctly parse s3.

How do you use scanf to do it?

    Stuart

lopez@uiucdcsp.cs.uiuc.edu (07/19/87)

/*I only answer the easy ones*/

main()
{
    char s1[100], s2[100], s3[100];

sscanf("one two three four # five six seven", "%s %[^#] \# %[^$]", s1, s2, s3);

printf("s1=%s, s2=%s, s3=%s\n", s1, s2, s3);

} /*main*/

This works on my compiler. I hope this is what you wanted.


FML
Somewhere out there.

rlk@chinet.UUCP (Richard Klappal) (07/19/87)

In article <1220@ccicpg.UUCP> cracraft@ccicpg.UUCP (Stuart Cracraft) writes:
>Suppose you have a line from a file such as:
>
>str1      str2 str3 str4 ... strN    # strN+1 ... strN+I
> ^                 ^                          ^
> |                 |                          |
> Store in s1       |                          |
>		   Store in s2                Store in s3
>
 .....
>each of the three fields in its own variable. The obvious
>   scanf("%s %[^#] %s",s1,s2,s3)
>successfully parses s1 & s2, but doesn't correctly parse s3.
>How do you use scanf to do it?
>    Stuart

Since the number of strings following the '#' may be variable,
I would use strtok (see strings(3)), if you have it.

 { if not, look thru the net.sources, or mod.sources, archives
 for Henry Spencer's strings package. }

	...
	fgets(stream, MAXLINE, buffer);
	strcpy(s1,strtok(buffer," "));
	strcpy(s2,strtok(NULL,"#"));
	strcpy(s3,strtok(NULL,"\n"));

I have not included any error checking in this example, but you should
do so since strtok() returns NULL when no token remains.

-- 
---
UUCP: ..!ihnp4!chinet!uklpl!rlk || MCIMail: rklappal || Compuserve: 74106,1021
      ..!ihnp4!ihu1h!rlk
---

dcm@sfsup.UUCP (David C. Miller, consultant) (07/22/87)

In article <1220@ccicpg.UUCP> cracraft@ccicpg.UUCP (Stuart Cracraft) writes:
>Suppose you have a line from a file such as:
>
>str1      str2 str3 str4 ... strN    # strN+1 ... strN+I
> ^                 ^                          ^
> |                 |                          |
> Store in s1       |                          |
>		   Store in s2                Store in s3
>
>The above line consists of three fields:
>   1) str1
>   2) str2 ... strN (where N is up to 10)
>   3) strN+1 ... strN+I (where I is up to 10)
>(strX represents an arbitrary-length string, up to 20 characters.)
>
>You want to use scanf to parse this line, storing
>each of the three fields in its own variable. The obvious
>
>   scanf("%s %[^#] %s",s1,s2,s3)
>
>successfully parses s1 & s2, but doesn't correctly parse s3.
>
>How do you use scanf to do it?
>
>    Stuart

There are two problems with the format you used.

1.  There is no provision for disposing of the '#'.
2.  Field 3 is specified as ONE space separated field.

Correction follows:

    scanf("%s %[^#]# %[^\n]\n", s1, s2, s3);
		   ^    ^   ^
		   |    |   +----  Clean up newline
		   |    +--------  Field 3 is everything up to newline
		   +-------------  Clean up #

The newline may be replaced with any other character you
may use to designate end-of-line.  Hope this helps.

				Dave
David C. Miller, consultant
Comm Addresses:
    Paperware:  AT&T Information Systems,190 River Road,Summit,NJ 07901
    Liveware:  (201) 522-6107
    Software:  {allegra,burl,cbosgd,clyde,ihnp4,ulysses}!sfsup!dcm

cracraft@ccicpg.UUCP (Stuart Cracraft) (07/24/87)

There were a number of replies to this quiz question. Only one
person answered the question correctly. First, let me restate
the quiz question:

   >Suppose you have an input line of the form:
   >
       >str1      str2 str3 str4 ... strN    # strN+1 ... strN+I
   > ^                 ^                          ^
   > |                 |                          |
   > Store in s1       |                          |
   >		   Store in s2                Store in s3
   >
       >The above line consists of three fields:
   >      1) str1
   >   2) str2 ... strN (where N is up to 10)
   >   3) strN+1 ... strN+I (where I is up to 10)
   >(strX represents an arbitrary-length string, up to 20 characters.)
   >How do you parse this line using scanf?

Many people correctly answered for the first argument. It is simply
%s in the scanf scan string. Some people, though fewer, correctly
answered for the second argument. It is simply [^#] in the scan
string. This takes advantage of the scanf ^ 'complement' operator
to create a 'breakset'. When it came to the third argument however,
just about everyone missed, except for our winner.

Our winner correctly pointed out that a non-assignment argument must
also be supplied, and he correctly deduced the breakset for the
final argument as well. Here is the correct answer:

    scanf("%s %[^#] %*c %[^\n]",s1,s2,s3);

Congratulations to our winner, Leonard Binns!

	Stuart

P.S. Other answers may exist. The quiz manufacturer disclaims
     any responsibility for additional solutions.