fgets

Discussion in 'C Programming' started by Magix, Aug 27, 2004.

  1. Magix

    Magix Guest

    Hi,

    I'm not too sure on reading specify string with the first < > from file
    stream,and make the file pointer go to next line, with fgets. or any better
    idea.

    E.g
    let say text.txt has
    <11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    <22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    <333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>

    while(fgets(num, 7, fp)!=NULL)
    {
    // filter the < and >
    printf( "%s",num );
    // go to new line
    }

    it will print num:
    11111
    22222
    33333

    Advise...pls. Thanks

    Regards.
    Magix, Aug 27, 2004
    #1
    1. Advertising

  2. Magix

    Magix Guest

    "Magix" <> wrote in message
    news:412ed35b$...
    > Hi,
    >
    > I'm not too sure on reading specify string with the first < > from file
    > stream,and make the file pointer go to next line, with fgets. or any

    better
    > idea.
    >
    > E.g
    > let say text.txt has
    > <11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    > <22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    > <333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>
    >
    > while(fgets(num, 7, fp)!=NULL)
    > {
    > // filter the < and >
    > printf( "%s",num );
    > // go to new line
    > }
    >
    > it will print num:
    > 11111
    > 22222
    > 33333
    >
    > Advise...pls. Thanks
    >
    > Regards.
    >
    >


    Sorry, it will print num:
    11111
    22222222
    333
    Magix, Aug 27, 2004
    #2
    1. Advertising

  3. Magix

    Mike Wahler Guest

    "Magix" <> wrote in message
    news:412ed3cd$...
    >
    > "Magix" <> wrote in message
    > news:412ed35b$...
    > > Hi,
    > >
    > > I'm not too sure on reading specify string with the first < > from file
    > > stream,and make the file pointer go to next line, with fgets. or any

    > better
    > > idea.
    > >
    > > E.g
    > > let say text.txt has
    > > <11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    > > <22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    > > <333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>
    > >
    > > while(fgets(num, 7, fp)!=NULL)


    Why 7?

    > > {
    > > // filter the < and >
    > > printf( "%s",num );
    > > // go to new line
    > > }
    > >
    > > it will print num:
    > > 11111
    > > 22222
    > > 33333
    > >
    > > Advise...pls. Thanks
    > >
    > > Regards.
    > >
    > >

    >
    > Sorry, it will print num:
    > 11111
    > 22222222
    > 333



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

    #define LINE_SIZE 100 /* adjust to your needs */
    #define LDELIM '<'
    #define RDELIM '>'

    int main()
    {
    FILE *fp = fopen("test.txt", "r");
    static char line[LINE_SIZE];

    if(!fp)
    {
    fprintf(stderr, "Cannot open input\n");
    return EXIT_FAILURE;
    }

    while(fgets(line, sizeof line, fp))
    {
    char *left = 0;
    char *right = 0;

    if(left = strchr(line, LDELIM))
    right = strchr(++left, RDELIM);

    if(left && right)
    {
    *right = 0;
    printf("%s\n", left);
    }
    }

    if(!feof(fp))
    {
    fprintf(stderr, "Error reading input\n";
    return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
    }

    Input:

    <11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    <22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    <333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>


    Output:

    11111
    22222222
    333

    The above will only work correctly if all lines are less than
    ;LINE_SIZE; characters. If they're larger and you don't increase
    'LINE_SIZE' to accomodate, you'll need to handle cases where
    a single 'fgets()' call doesn't extract a newline character.

    -Mike

    >
    >
    Mike Wahler, Aug 27, 2004
    #3
  4. Magix

    Michael Mair Guest

    Hi Magix,

    >>I'm not too sure on reading specify string with the first < > from file
    >>stream,and make the file pointer go to next line, with fgets. or any

    >
    > better
    >
    >>idea.
    >>
    >>E.g
    >>let say text.txt has
    >><11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    >><22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    >><333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>
    >>
    >>while(fgets(num, 7, fp)!=NULL)
    >>{
    >> // filter the < and >
    >> printf( "%s",num );
    >> // go to new line
    >>}
    >>

    >
    > It will print num:
    > 11111
    > 22222222
    > 333


    You can also use fscanf():

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

    #define STRINGIZE(s) # s
    #define MAKESTRING(s) STRINGIZE(s)

    #define FIELDWIDTH 7

    int main (void)
    {
    FILE *fp;
    char str[FIELDWIDTH+1];

    if ( (fp=fopen("magix.inp","r")) == NULL )
    exit(EXIT_FAILURE);

    while (1) {
    int howmany = fscanf(fp, "<%"MAKESTRING(FIELDWIDTH)
    "[^>]%*[^<]<%*[^>]><%*[^>]>",
    str);
    if (howmany!=1)
    break;
    puts(str);
    }
    fclose(fp);

    exit(EXIT_SUCCESS);
    }

    The format string does the following:
    It gobbles a '<', then scans for up to FIELDWIDTH non-'>'
    characters into str. As we do not know whether this covers
    the first "<tag>", we now scan for the beginning of
    the second, then gobble the second and third tags, respectively.
    The leading ' ' is for gobbling any left over white spaces
    from previous line.

    Note, however, that this does not give you the certainty that
    your line was of the required format. You could scan for the
    final '>' or try to fgetc() the following '\n' to be on the
    safe side.

    It might be a good idea to #define left/right delimiter
    characters instead of '<','>'. You can insert them quite
    in the same way as the FIELDWIDTH.


    Cheers,
    Michael
    Michael Mair, Aug 27, 2004
    #4
  5. "Michael Mair" <-stuttgart.de>
    wrote in message
    news:cgn1fl$7hk$-stuttgart.de...
    > Hi Magix,
    >
    > >>I'm not too sure on reading specify string with the first < >

    from file
    > >>stream,and make the file pointer go to next line, with fgets.

    or any
    > >
    > > better
    > >
    > >>idea.
    > >>
    > >>E.g
    > >>let say text.txt has
    > >><11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    > >><22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    > >><333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>
    > >>
    > >>while(fgets(num, 7, fp)!=NULL)
    > >>{
    > >> // filter the < and >
    > >> printf( "%s",num );
    > >> // go to new line
    > >>}
    > >>

    > >
    > > It will print num:
    > > 11111
    > > 22222222
    > > 333

    >
    > You can also use fscanf():
    >
    > while (1) {
    > int howmany = fscanf(fp, "<%"MAKESTRING(FIELDWIDTH)
    > "[^>]%*[^<]<%*[^>]><%*[^>]>",
    > str);
    >
    > The format string does the following:
    > It gobbles a '<', then scans for up to FIELDWIDTH non-'>'
    > characters into str. As we do not know whether this covers
    > the first "<tag>", we now scan for the beginning of
    > the second, then gobble the second and third tags,

    respectively.
    > The leading ' ' is for gobbling any left over white spaces
    > from previous line.
    >
    > Note, however, that this does not give you the certainty that
    > your line was of the required format. You could scan for the
    > final '>' or try to fgetc() the following '\n' to be on the
    > safe side.
    >
    > It might be a good idea to #define left/right delimiter
    > characters instead of '<','>'. You can insert them quite
    > in the same way as the FIELDWIDTH.
    >


    Why so complicated?

    What happens if there is a space in the input string?
    What happens if there aren't exactly three pairs of tags on a
    line (which I don't see any requirement for - the example just
    happens to have three on each line)?

    For what the OP is asking for, if I understand it correctly, you
    don't need to perform string operations at all.

    This is the way I read what is being asked for (which,
    admittedly, involved reading between the lines):

    1) Lines consist of strings of characters delimited by '<'
    (LDELIM) and '>' (RDELIM) characters.
    2) There may be one or more such strings on a given line.
    3) Output should consist only of the first such string on each
    line.

    IF we are willing to assume (for the first pass at the algorithm)
    that the strings really do obey Rule #1, then we have the
    following:

    1) WHILE: End of File not reached
    1.1) WHILE: (Next character is NOT LDELIM)
    1.1.1) Do nothing - go on to next character.
    1.2) WHILE: (Next character is NOT RDELIM)
    1.2.1) Print the character.
    1.3) Print a newline character.
    1.4) WHILE: (Next character is NOT the end of the line)
    1.4.1) Do nothing - go on to the next character.

    Each of the tests should include checks for EOF and (if desired)
    newline characters in unexpected places.

    At the risk of doing someone's homework (hopefully they'll at
    least learn something from seeing the problem stated clearly, an
    algorithm developed based on the problem statement, and code
    developed based on the algorithm).

    #include <stdio.h> /* FILE, NULL, fopen(), putchar(), printf()
    */

    #define EXIT_OK (0)
    #define EXIT_FAIL_NoOpen (1)

    #define FILENAME "data.txt"

    #define LDELIM ('<')
    #define RDELIM ('>')

    int main(void)
    {
    int c;
    FILE *fp;

    fp = fopen(FILENAME, "rt");
    if(NULL == fp)
    {
    printf("Error opening %s for reading - aborting.\n",
    FILENAME);
    return EXIT_FAIL_NoOpen;
    }

    do /* Until end of file is reached */
    {
    /* Strip up to and including first occurrence of LDELIM
    */
    while( (EOF != (c = getc(fp))) && ('\n' != c) &&
    (LDELIM != c) )
    /* EMPTY LOOP */;

    /* Print out characters up to first occurrence of
    RDELIM */
    while( (EOF != (c = getc(fp))) && ('\n' != c) &&
    (RDELIM != c) )
    putchar(c);
    putchar('\n');

    /* Strip remaining characters on line */
    while( (EOF != (c = getc(fp))) && ('\n' != c) )
    /* EMPTY LOOP */;

    } while (EOF != c);

    fclose(fp);

    return EXIT_OK;
    }


    As usual, I welcome comments and criticisms.

    NOTE TO THE OP: By using the subject line you did, you imply that
    your question is specifically dealing with a specific function -
    namely fgets() - and people might assume that, for whatever
    reason, you either have to use that function or are trying to
    learn more about that function by doing so. Your post content
    implies that this is not the case. A better subject line might
    have been something like: "Trying to output initial part of each
    line".
    William L. Bahn, Aug 27, 2004
    #5
  6. "Magix" <> wrote in message news:<412ed3cd$>...
    > "Magix" <> wrote in message
    > news:412ed35b$...


    > > I'm not too sure on reading specify string with the first < > from file
    > > stream,and make the file pointer go to next line, with fgets. or any
    > > better idea.


    I'm afraid I don't understand you. Do you mean "I want to read the
    text
    enclosed by <>, and then skip to the next line"?

    > > E.g
    > > let say text.txt has
    > > <11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    > > <22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    > > <333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>
    > >
    > > while(fgets(num, 7, fp)!=NULL)
    > > {
    > > // filter the < and >
    > > printf( "%s",num );
    > > // go to new line
    > > }
    > >
    > > it will print num:
    > > 11111
    > > 22222
    > > 33333

    >
    > Sorry, it will print num:
    > 11111
    > 22222222
    > 333


    no it won't. Do you mean that's what you want it to do? If so you
    could get a character at a time.


    --
    Nick Keighley

    My god it's full of stars!
    Dave Bowman, on seeing HAL's source code
    Nick Keighley, Aug 27, 2004
    #6
  7. Magix

    Michael Mair Guest

    Hello William,


    > Why so complicated?
    >
    > What happens if there is a space in the input string?

    (Then scan for white spaces which are not return between > and
    <... but that is beside the point, see below)

    > What happens if there aren't exactly three pairs of tags on a
    > line (which I don't see any requirement for - the example just
    > happens to have three on each line)?
    >
    > For what the OP is asking for, if I understand it correctly, you
    > don't need to perform string operations at all.


    That may be the problem -- I did not entirely understand his
    intention, so I made up one that seemed to fit... :-/
    It seemed to me that he defined an input format which I
    put into a format string as I do not think that fgets()
    is the best thing to use. OTOH, he seemed to want to do
    it "in one go", so I tried to give him that.


    > This is the way I read what is being asked for (which,
    > admittedly, involved reading between the lines):
    >
    > 1) Lines consist of strings of characters delimited by '<'
    > (LDELIM) and '>' (RDELIM) characters.
    > 2) There may be one or more such strings on a given line.
    > 3) Output should consist only of the first such string on each
    > line.


    Er, right. Then the way is clear. My assumptions from his
    input file were that
    1,2) Lines consist of exactly three strings delimited by < and >
    with no spaces between > and <, and a '\n' in the end.
    3) Output should consist only of the first FIELDWIDTH (7 for the
    OP) characters of the first string (or less, if the string has
    strlen(string)<FIELDWIDTH) on each line.


    Cheers
    Michael
    Michael Mair, Aug 27, 2004
    #7
  8. Magix

    CBFalconer Guest

    Nick Keighley wrote:
    > "Magix" <> wrote in message
    >> "Magix" <> wrote in message

    >
    >>> I'm not too sure on reading specify string with the first < >
    >>> from file stream,and make the file pointer go to next line,
    >>> with fgets. or any better idea.

    >
    > I'm afraid I don't understand you. Do you mean "I want to read
    > the text enclosed by <>, and then skip to the next line"?
    >
    >>> E.g
    >>> let say text.txt has
    >>> <11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    >>> <22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    >>> <333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>


    If we say 'the initial text so delimited' then things should be
    very simple:

    Input the whole string, search for the first '<' and save the
    pointer. Then search for the next '>' and zero that. Print the
    string denoted by the saved pointer. Roughly:

    if (firstp = strchr(buffer, '<')) firstp++;
    if (firstp && (endp = strchr(firstp, '>')))
    *endp = '\0';
    puts(firstp);
    else {
    /* something isn't there */
    }


    --
    "The most amazing achievement of the computer software industry
    is its continuing cancellation of the steady and staggering
    gains made by the computer hardware industry..." - Petroski
    CBFalconer, Aug 27, 2004
    #8
  9. Magix

    Malcolm Guest

    "Magix" <> wrote
    >
    > I'm not too sure on reading specify string with the first < > from file
    > stream,and make the file pointer go to next line, with fgets. or any

    better
    > idea.
    >
    > E.g
    > let say text.txt has
    > <11111><Joe><aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa>
    > <22222222><Ron><bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb>
    > <333><Jim><ccccccccccccccccccccccccccccccccccccccccccc>
    >
    > while(fgets(num, 7, fp)!=NULL)
    > {
    > // filter the < and >
    > printf( "%s",num );
    > // go to new line
    > }
    >
    >

    fgets() is useful if you can specify a maximum line length, and reject every
    input over that limit (say 1024 characters). If you need to be able to
    handle lines of any length, or if the input doesn't naturally fall into
    lines, then it is not really useful and you need to write your own function
    to read data into dynamically allocated memory.

    You can parse simple input, like a block of text containing a few tag
    delimited by <> just using a commonsense approach.

    Once things get more complicated, for instance you allow nested tags, escape
    sequences, and different types of tag, then you need to move to a recursive
    parser. It is not easy to explain how to write one in a short post, but
    basically you need a parsetag() function which calls itself when it hits a
    nested tag. It also needs a match() function to flag an error if the closing
    '>' is not detected at the appropriate place.
    Malcolm, Aug 27, 2004
    #9
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Charles Wilkins

    cin before fgets

    Charles Wilkins, Aug 7, 2003, in forum: C++
    Replies:
    4
    Views:
    710
    Charles Wilkins
    Aug 7, 2003
  2. Mike Mimic

    fgets and newline

    Mike Mimic, May 15, 2004, in forum: C++
    Replies:
    4
    Views:
    8,010
    John Harrison
    May 15, 2004
  3. DJP
    Replies:
    7
    Views:
    7,367
    glen herrmannsfeldt
    Oct 21, 2004
  4. Replies:
    6
    Views:
    1,235
    Mark McIntyre
    Jun 25, 2003
  5. Eigenvector

    fgets and problems reading into array

    Eigenvector, Jul 26, 2003, in forum: C Programming
    Replies:
    12
    Views:
    625
    Glen Herrmannsfeldt
    Jul 29, 2003
Loading...

Share This Page