need some more help with fgets, stdin, EOF 
Author Message
 need some more help with fgets, stdin, EOF

I'm new at using these things, so I'm getting stuck writing a program.
I have to write a program that outputs the n'th token in a line. The
program is called nth, so if I type in "nth 3" then the program gets
input from stdin (the keyboard). If I type "hello there, robert" as
input, then the program will output the third token, "robert", and
wait for me to enter another line. It will keep doing this, waiting
for me to type lines, then giving me the n'th token of that line,
until I type control-D. Lines in this program can be as long as 500
characters.

Also, I can have more than one argument. The first argument is
obviously n, the number of the token I want, but any subsequent
arguments are files containing input to be processed as above. If I
call "nth 3 input.txt" and input.txt is a file containing the line
"hello, there robert", then the output will be the same as the first
example where I typed the line in manually. I should be able to put as
many file names as I like for arguments and they'll be processed
sequentially. So "nth 3 input.txt input.txt" would output:

robert
robert

If the n'th token doesn't exist, for example I type "nth 10 input.txt"
then a newline is printed.

With my very limited knowledge of C, I've got this sort of working,
but can't fix my bugs. I've got it partially working in the case where
it reads input from stdin. It does what it is supposed to do, except
exit when I type control-D.
I think I need some test to see if the character entered is EOF, but I
can't find where to put it.

And in the case where the program gets input from a file, I can only
get the program to read and give the n'th token of the{*filter*}line. If I
have an input2.txt that looks like this:

Hello there, what's up?
How are you
I'm ok thanks

Then "nth 2 input2.txt" should  output:

there
are
ok

"nth 4 input2.txt" would output the token "up?" then two newlines.

I can only get the program to output the first line, "there". I know I
need a loop somewhere, but every loop I try just goes on infinitely.

Here's my code. Thank you to anyone who can tell me where I'm going
wrong!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
 * process - helper function which prints the nth line of a given
 * file, f.
 */
void process(FILE *f, int n_value) {
     char *p;
     char buf[500];
     int i;

     fgets(buf, sizeof buf, f);
     p = strtok(buf, " \n\t");

     for (i = 1; i < n_value; i++) {
          p = strtok((char *)NULL, " \n\t");
     }

     if (p == NULL) {
          printf("\n");
     } else {
          printf("%s\n", p);
     }

Quote:
}

int main(int argc, char **argv) {
     int i;
     int nth_element = atoi(argv[1]);

     while (argc == 2) {
          process(stdin, nth_element);
     }

    if (argc > 2) {
         FILE *fp;
         for (i = 2; i < argc; i++) {

              if ((fp = fopen(argv[i], "r")) == NULL) {
                   perror(argv[i]);
                   return(0);
               }
               process(fp, nth_element);
               fclose(fp);
          }
     }
     return(0);

Quote:
}



Tue, 26 Jul 2005 04:32:22 GMT  
 need some more help with fgets, stdin, EOF

<snip>

Quote:

> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>

> /*
>  * process - helper function which prints the nth line of a given
>  * file, f.
>  */
> void process(FILE *f, int n_value) {

Change this to
  int  process(FILE *f, int n_value) {
so that you can return a status code indicating whether or not there's more
processing to be done.

Quote:
>      char *p;
>      char buf[500];
>      int i;

>      fgets(buf, sizeof buf, f);

How about checking the return value of fgets?  fgets returns NULL if there
was an error reading from the file or if end of file was encountered.  So
something like:
       if ( fgets(buf, sizeof buf, f) == NULL )
           return 1; /* return 1 to show that this file is done */
If you want to, you can try and distinguish between an error and eof and
handle them differently.

Quote:
>      p = strtok(buf, " \n\t");

If you don't do the check of fgets' return value, you will invoke undefined
behavior here as the array buf is uninitialized.

Quote:
>      for (i = 1; i < n_value; i++) {

Change this to:
       for ( i = 1; i < n_value && p != NULL; ++i ) {
checking whether p != NULL lets you quit the loop as soon as there are no
more useful tokens in the string.  I don't think there's any problem
calling strtok even after it has returned a NULL, but why waste your breath
when you know nothing can be gained by calling it again?

Quote:
>           p = strtok((char *)NULL, " \n\t");

No need for the cast.

Quote:
>      }

>      if (p == NULL) {
>           printf("\n");
>      } else {
>           printf("%s\n", p);
>      }

       return 0; /* to show that we aren't done with this file */
Quote:
> }

> int main(int argc, char **argv) {
>      int i;
>      int nth_element = atoi(argv[1]);

oops.  what happens if the user doesn't supply any argument to your program?
undefined behavior.  check if argc < 2 and print an error message and bail
out if it is.

Quote:
>      while (argc == 2) {
>           process(stdin, nth_element);
>      }

I am surprised that you ever come out of this loop.  argc never ever changes
value in your program and this becomes an infinite loop.  What you probably
want is:
      if ( argc == 2 ) {
          /* remember that we return 1 if we're all done */
          while ( process(stdin, nth_element) != 1 )
              ;
      }

Quote:

>     if (argc > 2) {
>          FILE *fp;
>          for (i = 2; i < argc; i++) {

>               if ((fp = fopen(argv[i], "r")) == NULL) {
>                    perror(argv[i]);
>                    return(0);
>                }
>                process(fp, nth_element);
>                fclose(fp);

oops.  process will just process the first line and then you close this
file.  obviously, like you mentioned, you need some kind of loop here.
i'll leave it as an exercise for you to figure that out.

Quote:
>           }
>      }
>      return(0);
> }

HTH,
nrk.


Tue, 26 Jul 2005 06:51:11 GMT  
 
 [ 2 post ] 

 Relevant Pages 

1. Help needed - fgets and EOF

2. Help needed - fgets and EOF

3. flushing stdin after using fgets( foo, 100, stdin )

4. *NIX/C: ^D(EOF) prob-- need to ignore from stdin

5. fgets() EOF trouble

6. Newbie: EOF test with fgets

7. How to check for EOF after fgets

8. fgets -- segfault at EOF

9. fgets() sscanf() EOF confusion

10. STDIN and EOF

11. fgets not waiting for input from stdin

12. question about fgets and stdin

 

 
Powered by phpBB® Forum Software