Reading a table

Discussion in 'C Programming' started by Stephen.Schoenberger@gmail.com, Nov 26, 2007.

  1. Guest

    Hello,

    My C is a bit rusty (.NET programmer normally but need to do this in
    C) and I need to read in a text file that is setup as a table. The
    general form of the file is

    00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

    I need to read the file line by line and eventually parse out each
    piece of the file and store in arrays that correspond to the specific
    line. array1[1] would be the first entry in the first line and so on
    and so forth.

    Any suggestions would be great!

    Thanks.
    , Nov 26, 2007
    #1
    1. Advertising

  2. user923005 Guest

    On Nov 26, 11:04 am, wrote:
    > Hello,
    >
    > My C is a bit rusty (.NET programmer normally but need to do this in
    > C) and I need to read in a text file that is setup as a table. The
    > general form of the file is
    >
    > 00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000
    >
    > I need to read the file line by line and eventually parse out each
    > piece of the file and store in arrays that correspond to the specific
    > line. array1[1] would be the first entry in the first line and so on
    > and so forth.
    >
    > Any suggestions would be great!


    fopen() to open the file.
    fgets() to read in one line at a time.
    write your own function to parse it, because only you know the format.

    HTH
    user923005, Nov 26, 2007
    #2
    1. Advertising

  3. Guest

    On Nov 26, 2:10 pm, user923005 <> wrote:
    > On Nov 26, 11:04 am, wrote:
    >
    > > Hello,

    >
    > > My C is a bit rusty (.NET programmer normally but need to do this in
    > > C) and I need to read in a text file that is setup as a table. The
    > > general form of the file is

    >
    > > 00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

    >
    > > I need to read the file line by line and eventually parse out each
    > > piece of the file and store in arrays that correspond to the specific
    > > line. array1[1] would be the first entry in the first line and so on
    > > and so forth.

    >
    > > Any suggestions would be great!

    >
    > fopen() to open the file.
    > fgets() to read in one line at a time.
    > write your own function to parse it, because only you know the format.
    >
    > HTH


    Thanks!
    , Nov 26, 2007
    #3
  4. Default User Guest

    wrote:

    > Hello,
    >
    > My C is a bit rusty (.NET programmer normally but need to do this in
    > C) and I need to read in a text file that is setup as a table. The
    > general form of the file is
    >
    > 00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000
    >
    > I need to read the file line by line and eventually parse out each
    > piece of the file and store in arrays that correspond to the specific
    > line. array1[1] would be the first entry in the first line and so on
    > and so forth.
    >
    > Any suggestions would be great!


    Arrays in C are indexed from 0. You can leave the first one empty if
    you're determined to have 1-based indexing, but it's not an overly good
    idea.

    I'd also suggest a two-dimensional array, rather than separate ones
    named "array1" etc. That makes for easier handling, as the entire table
    OR individual rows can be passed to functions or whatever. So the first
    row would be table[0], and the first element would be table[0][0].

    It's especially easy if you happen to know the number of rows and
    columns going in, otherwise you'll probably need a dynamic array. Of
    course, you still need to come up with a data type for the elements
    themselves, presumably char*, but it's not clear what the parsing
    actually consists of. We'd need more information.




    Brian
    Default User, Nov 26, 2007
    #4
  5. Bill Reid Guest

    <> wrote in message
    news:...
    > On Nov 26, 2:10 pm, user923005 <> wrote:
    > > On Nov 26, 11:04 am, wrote:
    > >
    > > > Hello,

    > >
    > > > My C is a bit rusty (.NET programmer normally but need to do this in
    > > > C) and I need to read in a text file that is setup as a table. The
    > > > general form of the file is

    > >
    > > > 00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

    > >
    > > > I need to read the file line by line and eventually parse out each
    > > > piece of the file and store in arrays that correspond to the specific
    > > > line. array1[1] would be the first entry in the first line and so on
    > > > and so forth.

    > >
    > > > Any suggestions would be great!

    > >
    > > fopen() to open the file.
    > > fgets() to read in one line at a time.
    > > write your own function to parse it, because only you know the format.
    > >
    > > HTH

    >
    > Thanks!


    He forgot to tell you about fclose()!

    Anyway...

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

    #define LINEMAX 512

    extern unsigned
    assign_text_file_line_fields
    (char *,unsigned (*)(unsigned,char *,void *),void *);

    static FILE *text_file;

    static char text_line[LINEMAX];

    /* assigns field values from text file lines using callback function */
    unsigned assign_text_file_line_fields
    (char *text_file_path,
    unsigned assign_func(unsigned,char *,void *),void *assign_ptr) {
    unsigned line_num=0;
    ret_val=FALSE;

    /* try to open text file, return if failure */
    if((text_file=fopen(text_file_path,"rt"))==NULL) {
    printf("\nERROR: Could not open text file\n%s",
    text_file_path);
    goto EXIT_FUNCTION;
    }

    /* get every line in file, pass to callback function */
    while((fgets(text_line,LINEMAX,text_file))!=NULL) {

    if(!assign_func(line_num,text_line,assign_ptr)) {
    printf("ERROR: Could not assign line %d fields);
    goto CLOSE_TEXT_FILE;
    }

    line_num++;
    }

    /* OK, looks like we've succeeded */
    ret_val=TRUE;

    /* try to close file, warn if failure */
    CLOSE_TEXT_FILE :
    if((fclose(db_init_file))==EOF)
    printf("\nWARNING: Problem closing text file\n%s",
    text_file_path);

    /* buh-bye */
    EXIT_FUNCTION :
    return ret_val;
    }

    If you set up the above in its own little object file/library or
    whatever, you can link it into any program when you need to
    parse any type of text file with regularly-formatted lines of
    column-data, by writing a specific assign_func for each type
    of file, and declaring a suitable multi-dimensional array (or
    array of structs) to hold the data:

    typedef struct My_Data {
    double field_1;
    unsigned field_2;
    int field_3;
    } My_Data;

    My_Data my_data_array[100];

    My_Data *my_data_array_ptr=&my_data_array;

    static unsigned
    assign_my_file_fields
    (unsigned line_num,char *text_line,void *data_ptr) {
    My_Data *my_data_ptr=data_ptr;
    my_data_ptr+=line_num;

    /* line parsing and assigning goes here */

    }

    assign_text_file_line_fields
    (text_file_path,assign_my_file_fields,(void *)(my_data_array_ptr));

    And you'll never have to write the file opening, reading, and closing
    code ever again...the only reason I bring this up is because, of course,
    I have literally hundreds of different text file formats to read in my
    own code...

    ---
    William Ernest Reid
    Bill Reid, Nov 27, 2007
    #5
  6. pete Guest

    wrote:
    >
    > Hello,
    >
    > My C is a bit rusty (.NET programmer normally but need to do this in
    > C) and I need to read in a text file that is setup as a table. The
    > general form of the file is
    >
    > 00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000
    >
    > I need to read the file line by line and eventually parse out each
    > piece of the file and store in arrays that correspond to the specific
    > line. array1[1] would be the first entry in the first line and so on
    > and so forth.


    /* BEGIN file_parse.c output */

    Input file:
    0000000000 USNIST00Z 00000000_00 8 318 318 068 9318 068
    0000000001 USNIST00Z 00000000_00 9 619 119 119 7619 119
    0000000002 USNIST00Z 00000000_00 2 252 252 002 6252 002

    Resulting array:
    array[0][0] 0000000000
    array[0][1] USNIST00Z
    array[0][2] 00000000_00
    array[0][3] 8
    array[0][4] 318
    array[0][5] 318
    array[0][6] 068
    array[0][7] 9318
    array[0][8] 068


    array[1][0] 0000000001
    array[1][1] USNIST00Z
    array[1][2] 00000000_00
    array[1][3] 9
    array[1][4] 619
    array[1][5] 119
    array[1][6] 119
    array[1][7] 7619
    array[1][8] 119


    array[2][0] 0000000002
    array[2][1] USNIST00Z
    array[2][2] 00000000_00
    array[2][3] 2
    array[2][4] 252
    array[2][5] 252
    array[2][6] 002
    array[2][7] 6252
    array[2][8] 002


    /* END file_parse.c output */


    /* BEGIN file_parse.c */
    /*
    My C is a bit rusty
    (.NET programmer normally but need to do this in C)
    and I need to read in a text file that is setup as a table.
    The general form of the file is

    00000000 USNIST00Z 00000000_00 0 000 000 000 0000 000

    I need to read the file line by line and eventually parse out each
    piece of the file and store in arrays that correspond to the specific
    line. array1[1] would be the first entry in the first line and so on
    and so forth.
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <limits.h>
    #include <string.h>

    #define LINES_PER_FILE 3
    #define LU_RAND_SEED 123456789LU
    #define LU_RAND(S) ((S) * 69069 + 362437 & 0XFFFFFFFFLU)
    #define NMEMB(A) (sizeof (A) / sizeof *(A))

    struct list_node {
    struct list_node *next;
    void *data;
    };

    typedef struct list_node list_type;

    int get_line(char **lineptr, size_t *n, FILE *stream);
    int list_fputs(list_type *node, FILE *stream);
    list_type *list_append(list_type **head,
    list_type *tail,
    void *data,
    size_t size);
    void list_free(list_type *node, void (*free_data)(void *));
    void no_free(void *data);
    void free_ptrs(char ***p, size_t nmemb);
    void display_array(char ***p, size_t nmemb, size_t n_fields);

    int main(void)
    {
    long unsigned lu_seed, line, n_fields, field;
    int rc;
    char *buff, *ptr;
    size_t size;
    list_type *tail, *head;
    char fn[L_tmpnam];
    FILE *fp;
    char ***f;

    puts("/* BEGIN file_parse.c output */");
    /*
    ** Open temporary input text file for writing.
    */
    lu_seed = LU_RAND_SEED;
    tmpnam(fn);
    fp = fopen(fn, "w");
    if (fp == NULL) {
    fputs("fopen(fn), \"w\") == NULL\n", stderr);
    exit(EXIT_FAILURE);
    }
    for (line = 0; line != LINES_PER_FILE; ++line) {
    lu_seed = LU_RAND(lu_seed);
    fprintf(fp,
    "%.10lu %s %.1lu %.3lu %.3lu %.3lu %.4lu %.3lu\n",
    line, "USNIST00Z 00000000_00",
    lu_seed % 10, lu_seed % 1000,
    lu_seed % 500, lu_seed % 250,
    lu_seed % 10000, lu_seed % 125);
    }
    /*
    ** Close file.
    */
    fclose(fp);
    /*
    ** Open input text file for reading.
    ** Represent each line of the input text file
    ** as a string in a node of a linked list.
    ** Close temp input file after reading.
    */
    size = 0;
    buff = NULL;
    head = tail = NULL;
    fp = fopen(fn, "r");
    if (fp == NULL) {
    remove(fn);
    fputs("fopen(fn), \"r\") == NULL\n", stderr);
    exit(EXIT_FAILURE);
    }
    while ((rc = get_line(&buff, &size, fp)) > 0) {
    tail = list_append(&head, tail, buff, strlen(buff) + 1);
    if (tail == NULL) {
    fputs("tail == NULL\n", stderr);
    break;
    }
    }
    fclose(fp);
    /*
    ** Free allocated buffer used by get_line function.
    ** Remove temporary input file.
    */
    free(buff);
    remove(fn);
    if (rc != EOF) {
    list_free(head, free);
    fprintf(stderr, "rc == %d\n", rc);
    exit(EXIT_FAILURE);
    }
    /*
    ** Display linked list.
    */
    puts("\nInput file:");
    list_fputs(head, stdout);
    /*
    ** Create array.
    */
    n_fields = 1;
    for (ptr = head -> data; *ptr != '\0'; ++ptr) {
    if (*ptr == ' ') {
    ++n_fields;
    }
    }
    f = malloc(line * sizeof *f);
    if (f == NULL) {
    list_free(head, free);
    fputs("f == NULL\n", stderr);
    exit(EXIT_FAILURE);
    }
    for (line = 0; line != LINES_PER_FILE; ++line) {
    f[line] = malloc(n_fields * sizeof *f[line]);
    if (f[line] == NULL) {
    puts("f[line] == NULL");
    exit(EXIT_FAILURE);
    }
    }
    /*
    ** Tokenise list data and
    ** assign string addresses to pointers in array.
    */
    line = 0;
    for (tail = head; tail != NULL; tail = tail -> next) {
    f[line][0] = tail -> data;
    for (field = 1; field != n_fields; ++field) {
    f[line][field] = strchr(f[line][field - 1], ' ');
    if (f[line][field] == NULL) {
    puts("f[line][field] == NULL");
    exit(EXIT_FAILURE);
    }
    *f[line][field]++ = '\0';
    }
    ++line;
    }
    /*
    ** Free list nodes but not node->data.
    */
    list_free(head, no_free);
    /*
    ** Display resulting array.
    */
    puts("\nResulting array:");
    display_array(f, LINES_PER_FILE, n_fields);
    /*
    ** Free array.
    */
    free_ptrs(f, LINES_PER_FILE);
    free(f);
    puts("/* END file_parse.c output */");
    return 0;
    }

    void display_array(char ***p, size_t nmemb, size_t n_fields)
    {
    long unsigned line, field;

    for (line = 0; line != nmemb; ++line) {
    for (field = 0; field != n_fields; ++field) {
    printf("array[%lu][%lu] %s\n",
    line, field, p[line][field]);
    }
    puts("\n");
    }
    }

    void free_ptrs(char ***p, size_t nmemb)
    {
    while (nmemb-- != 0) {
    free(p[nmemb]);
    }
    }

    int get_line(char **lineptr, size_t *n, FILE *stream)
    {
    int rc;
    void *p;
    size_t count;

    count = 0;
    while ((rc = getc(stream)) != EOF) {
    if (count != (size_t)-2) {
    ++count;
    }
    if ((size_t)(count + 2u) > *n) {
    p = realloc(*lineptr, count + 2);
    if (p == NULL) {
    if (*n > count) {
    if (rc != '\n') {
    (*lineptr)[count] = '\0';
    (*lineptr)[count - 1] = (char)rc;
    } else {
    (*lineptr)[count - 1] = '\0';
    }
    } else {
    if (*n != 0) {
    **lineptr = '\0';
    }
    ungetc(rc, stream);
    }
    count = 0;
    break;
    }
    *lineptr = p;
    *n = count + 2;
    }
    if (rc == '\n') {
    (*lineptr)[count - 1] = '\0';
    break;
    }
    (*lineptr)[count - 1] = (char)rc;
    }
    if (rc != EOF) {
    rc = INT_MAX > count ? count : INT_MAX;
    } else {
    if (*n > count) {
    (*lineptr)[count] = '\0';
    }
    }
    return rc;
    }

    int list_fputs(list_type *node, FILE *stream)
    {
    while (node != NULL) {
    if (fputs(node -> data, stream) == EOF) {
    return EOF;
    }
    if (putc('\n', stream) == EOF) {
    return EOF;
    }
    node = node -> next;
    }
    return '\n';
    }

    list_type *list_append(list_type **head,
    list_type *tail,
    void *data,
    size_t size)
    {
    list_type *node;

    node = malloc(sizeof *node);
    if (node != NULL) {
    node -> next = NULL;
    node -> data = malloc(size);
    if (node -> data != NULL) {
    memcpy(node -> data, data, size);
    if (*head != NULL) {
    tail -> next = node;
    } else {
    *head = node;
    }
    } else {
    free(node);
    node = NULL;
    }
    }
    return node;
    }

    void list_free(list_type *node, void (*free_data)(void *))
    {
    list_type *next_node;

    while (node != NULL) {
    next_node = node -> next;
    free_data(node -> data);
    free(node);
    node = next_node;
    }
    }

    void no_free(void *data)
    {
    data;
    }

    /* END file_parse.c */


    --
    pete
    pete, Nov 29, 2007
    #6
  7. pete Guest

    pete wrote:

    > /* BEGIN file_parse.c */


    I rewrote some of the code.

    > long unsigned lu_seed, line, n_fields, field;


    Could use another variable to count file lines.

    long unsigned lu_seed, line, n_lines, n_fields, field;

    > for (line = 0; line != LINES_PER_FILE; ++line) {
    > f[line] = malloc(n_fields * sizeof *f[line]);
    > if (f[line] == NULL) {
    > puts("f[line] == NULL");
    > exit(EXIT_FAILURE);
    > }
    > }


    Some of the cleanup could be better.

    for (line = 0; line != n_lines; ++line) {
    f[line] = malloc(n_fields * sizeof *f[line]);
    if (f[line] == NULL) {
    free_ptrs(f, line);
    list_free(head, free);
    puts("f[line] == NULL");
    exit(EXIT_FAILURE);
    }
    f[line][0] = NULL;
    }

    > if (f[line][field] == NULL) {
    > puts("f[line][field] == NULL");
    > exit(EXIT_FAILURE);
    > }


    if (f[line][field] == NULL) {
    free_ptrs(f, n_lines);
    list_free(head, free);
    puts("f[line][field] == NULL");
    exit(EXIT_FAILURE);


    > free_ptrs(f, LINES_PER_FILE);
    > free(f);


    Instead of the above two lines, just this one:

    free_ptrs(f, n_lines);



    > void free_ptrs(char ***p, size_t nmemb)
    > {
    > while (nmemb-- != 0) {
    > free(p[nmemb]);
    > }
    > }


    This version of free_ptrs, frees the list data,
    which I had neglected to do before.

    void free_ptrs(char ***p, size_t nmemb)
    {
    while (nmemb-- != 0) {
    free(p[nmemb][0]);
    free(p[nmemb]);
    }
    free(p);
    }

    --
    pete
    pete, Nov 29, 2007
    #7
  8. On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
    >Anyway...
    >
    >#include <stdio.h>
    >#include <stdlib.h>
    >
    >#define LINEMAX 512
    >
    >extern unsigned
    >assign_text_file_line_fields
    >(char *,unsigned (*)(unsigned,char *,void *),void *);
    >
    >static FILE *text_file;
    >
    >static char text_line[LINEMAX];
    >
    >/* assigns field values from text file lines using callback function */
    >unsigned assign_text_file_line_fields
    >(char *text_file_path,
    >unsigned assign_func(unsigned,char *,void *),void *assign_ptr) {
    > unsigned line_num=0;
    > ret_val=FALSE;
    >
    > /* try to open text file, return if failure */
    > if((text_file=fopen(text_file_path,"rt"))==NULL) {
    > printf("\nERROR: Could not open text file\n%s",
    > text_file_path);
    > goto EXIT_FUNCTION;
    > }
    >
    > /* get every line in file, pass to callback function */
    > while((fgets(text_line,LINEMAX,text_file))!=NULL) {
    >
    > if(!assign_func(line_num,text_line,assign_ptr)) {
    > printf("ERROR: Could not assign line %d fields);
    > goto CLOSE_TEXT_FILE;
    > }
    >
    > line_num++;
    > }
    >
    > /* OK, looks like we've succeeded */
    > ret_val=TRUE;
    >
    > /* try to close file, warn if failure */
    > CLOSE_TEXT_FILE :
    > if((fclose(db_init_file))==EOF)
    > printf("\nWARNING: Problem closing text file\n%s",
    > text_file_path);
    >
    > /* buh-bye */
    > EXIT_FUNCTION :
    > return ret_val;
    > }


    Your callback solution has its merits. But you could have done it

    - without gotos
    - whithout static FILE
    - for arbitrary long lines (no hard-coded maximum line lenght)
    - with a typedef for the callback function for better readability
    - with an explanation for "rt" instead of "r"
    - returning error codes instead of using printfs
    - with self-explanatory names e.g. process_file_by_line (insted of
    assign_text_file_line_fields), process_line (instead of assign_func),
    data or context (instead of assign_ptr)



    --
    Roland Pibinger
    "The best software is simple, elegant, and full of drama" - Grady Booch
    Roland Pibinger, Nov 29, 2007
    #8
  9. Bill Reid Guest

    Roland Pibinger <> wrote in message
    news:...
    > On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
    > >Anyway...
    > >
    > >#include <stdio.h>
    > >#include <stdlib.h>
    > >
    > >#define LINEMAX 512
    > >
    > >extern unsigned
    > >assign_text_file_line_fields
    > >(char *,unsigned (*)(unsigned,char *,void *),void *);
    > >
    > >static FILE *text_file;
    > >
    > >static char text_line[LINEMAX];
    > >
    > >/* assigns field values from text file lines using callback function */
    > >unsigned assign_text_file_line_fields
    > >(char *text_file_path,
    > >unsigned assign_func(unsigned,char *,void *),void *assign_ptr) {
    > > unsigned line_num=0;
    > > ret_val=FALSE;
    > >
    > > /* try to open text file, return if failure */
    > > if((text_file=fopen(text_file_path,"rt"))==NULL) {
    > > printf("\nERROR: Could not open text file\n%s",
    > > text_file_path);
    > > goto EXIT_FUNCTION;
    > > }
    > >
    > > /* get every line in file, pass to callback function */
    > > while((fgets(text_line,LINEMAX,text_file))!=NULL) {
    > >
    > > if(!assign_func(line_num,text_line,assign_ptr)) {
    > > printf("ERROR: Could not assign line %d fields);
    > > goto CLOSE_TEXT_FILE;
    > > }
    > >
    > > line_num++;
    > > }
    > >
    > > /* OK, looks like we've succeeded */
    > > ret_val=TRUE;
    > >
    > > /* try to close file, warn if failure */
    > > CLOSE_TEXT_FILE :
    > > if((fclose(db_init_file))==EOF)
    > > printf("\nWARNING: Problem closing text file\n%s",
    > > text_file_path);
    > >
    > > /* buh-bye */
    > > EXIT_FUNCTION :
    > > return ret_val;
    > > }

    >
    > Your callback solution has its merits. But you could have done it
    >
    > - without gotos


    They're worth it just to irritate some people and don't hurt
    anything...

    > - whithout static FILE


    Possibly, but the idea here is just to read a single file and
    then close it right up...

    > - for arbitrary long lines (no hard-coded maximum line lenght)


    Yes, but again the idea here is we KNOW the maximum size
    of our file lines, almost certainly because we wrote them in the
    first place with trusted and checked data (note that I left out anything
    about sizing the array for the number of lines, that's left "up to the
    reader")...in real life, I do have a similar function that does dynamic
    resizing for arbitrarily long lines for other types of files...

    > - with a typedef for the callback function for better readability


    Uh, yeah, maybe, I'm not sure I'm following you here...

    > - with an explanation for "rt" instead of "r"


    Read the friggin' man page!

    > - returning error codes instead of using printfs


    Up to the original poster to implement their error handling
    routines; actually, I use something else in "real life" but modified
    it for "readability"...

    > - with self-explanatory names e.g. process_file_by_line (insted of
    > assign_text_file_line_fields), process_line (instead of assign_func),
    > data or context (instead of assign_ptr)


    Yeah, semantics, maybe...

    > "The best software is simple, elegant, and full of drama" - Grady Booch


    Ah, brinksmanship, most applicable to nuclear power plant software...

    ---
    William Ernest Reid
    Bill Reid, Nov 30, 2007
    #9
  10. CBFalconer Guest

    Bill Reid wrote:
    > Roland Pibinger <> wrote in message
    >

    .... snip ...
    >
    >> - whithout static FILE

    >
    > Possibly, but the idea here is just to read a single file and
    > then close it right up...
    >
    >> - for arbitrary long lines (no hard-coded maximum line lenght)

    >
    > Yes, but again the idea here is we KNOW the maximum size> of our
    > file lines,


    However, some people want to copy files without worrying about line
    length. With ggets (and fggets) you can handle this with ease, as
    in the following:

    [1] c:\c\junk>cc -o fcopylns.exe ggets.o junk.c

    [1] c:\c\junk>fcopylns <junk.c
    #include <stdio.h>
    #include <stdlib.h>
    #include "ggets.h"

    int main(void) {
    char *line;

    while (0 == ggets(&line)) {
    puts(line);
    free(line);
    }
    return 0;
    } /* main, fcopylns */

    Note the complexity. You can get the source etc. for ggets at:

    <http://cbfalconer.home.att.net/download/ggets.zip>

    --
    Chuck F (cbfalconer at maineline dot net)
    <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Nov 30, 2007
    #10
  11. pete Guest

    Bill Reid wrote:
    >
    > Roland Pibinger <> wrote in message
    > news:...
    > > On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:


    > > > if((text_file=fopen(text_file_path,"rt"))==NULL) {


    > > - with an explanation for "rt" instead of "r"

    >
    > Read the friggin' man page!


    That's the problem.

    Man pages aren't part of the C programming language.

    Using "rt" as a second argument in a fopen function call
    isn't part of the C programming language either.

    --
    pete
    pete, Nov 30, 2007
    #11
  12. Bill Reid Guest

    pete <> wrote in message
    news:...
    > Bill Reid wrote:
    > >
    > > Roland Pibinger <> wrote in message
    > > news:...
    > > > On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:

    >
    > > > > if((text_file=fopen(text_file_path,"rt"))==NULL) {

    >
    > > > - with an explanation for "rt" instead of "r"

    > >
    > > Read the friggin' man page!

    >
    > That's the problem.
    >
    > Man pages aren't part of the C programming language.
    >
    > Using "rt" as a second argument in a fopen function call
    > isn't part of the C programming language either.
    >

    Yeah, I guess you're right, from a completely strict interpretation
    of the "standard"...except, of course, that the "standard" itself is
    actually contradictory as a practical matter on the subject.

    If "rt" is NOT a part of the "C programming language" (standard),
    then of course it would be completely illegal to use "rt". But that's
    NOT what the "standard" says, now is it?

    Meanwhile, on my "implementation", there is a global file opening
    mode variable that can be over-ridden by using either 't' or 'b'. Since
    it is set to "O_TEXT" by default I don't actually NEED to use the "rt",
    but since this has also been the case for several wildly-different
    "implementations" in my experience, I am in the habit of setting it
    that way. I suspect there aren't a lot of C compilers out there where
    this would cause a problem, since a lot of them fudge around the
    "undefined behavior" in their "man pages", explicitly allowing the
    "rt" while acknowledging it is a waste of a character...

    But, I guess you're "technically" correct, I should have noted that
    to open a text file under the "C standard" you only need to use "r",
    and "rt" MIGHT cause a "portability" problem...

    ---
    William Ernest Reid
    Bill Reid, Nov 30, 2007
    #12
  13. Bill Reid Guest

    CBFalconer <> wrote in message
    news:...
    > Bill Reid wrote:
    > > Roland Pibinger <> wrote in message
    > >

    > ... snip ...
    > >
    > >> - whithout static FILE

    > >
    > > Possibly, but the idea here is just to read a single file and
    > > then close it right up...
    > >
    > >> - for arbitrary long lines (no hard-coded maximum line lenght)

    > >
    > > Yes, but again the idea here is we KNOW the maximum size> of our
    > > file lines,

    >
    > However, some people want to copy files without worrying about line
    > length. With ggets (and fggets) you can handle this with ease, as
    > in the following:
    >
    > [1] c:\c\junk>cc -o fcopylns.exe ggets.o junk.c
    >
    > [1] c:\c\junk>fcopylns <junk.c
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include "ggets.h"
    >
    > int main(void) {
    > char *line;
    >
    > while (0 == ggets(&line)) {
    > puts(line);
    > free(line);
    > }
    > return 0;
    > } /* main, fcopylns */
    >
    > Note the complexity. You can get the source etc. for ggets at:
    >
    > <http://cbfalconer.home.att.net/download/ggets.zip>
    >

    Sure, something like that might come in handy in some situations,
    but I actually take a somewhat different tack for parsing out text "tables"
    with potentially (unpredictably) HUGE "field" sizes.

    Consider that the file must STILL have a rigorously-applied delimiter
    strategy in order to be useful. Then consider that we can always replace
    the delimiter with '\0' in the text buffer, and that we can count the
    "lines" (rows) as being every occurence of a '\n' OUTSIDE of a
    potentially HUGE text field "protected" in some way to allow the
    use of the "field" (columns) and "line" (rows) delimiters in the text.

    So at the very least, if you use fgetc() until EOF, you will wind up
    with a buffer of strings delimited by NULs that corresponds to your
    count of "columns" and "rows", and if you haven't already completely
    parsed out the data and assigned it to your arrays, you can make
    a second pass to do so based on this information.

    If you're wondering why you would want a second pass in the
    first place, I actually do this on a weekly basis with some HUGE
    text files (well, several MB each) I download from the net, and I
    actually prefer for download speed and security to go through the
    download buffers in real-time applying the NUL to each "field", and
    then after closing each download connection doing some fairly
    time-consuming parsing of the fields (which involves writing thousands
    of files).

    In this case, I'm always doing dynamic memory re-allocation
    for the text buffer as the download buffer is filled on successive
    HTTP GETs; in the case of local files, a similar type of dynamic
    buffer re-sizing could also be used. Therefore, I never need to
    "get" a "line" of any length at all...

    But when it comes time to parse a file that I've written myself
    and KNOW exactly how big the maximum line length is, I just
    use fgets(), and typically nothing more fancy than sscanf() to parse
    out and assign the "fields" for each line...

    ---
    William Ernest Reid
    Bill Reid, Nov 30, 2007
    #13
  14. CBFalconer Guest

    Bill Reid wrote:
    > CBFalconer <> wrote in message
    >> Bill Reid wrote:
    >>> Roland Pibinger <> wrote in message
    >>>

    >> ... snip ...
    >>>
    >>>> - whithout static FILE
    >>>
    >>> Possibly, but the idea here is just to read a single file and
    >>> then close it right up...
    >>>
    >>>> - for arbitrary long lines (no hard-coded maximum line lenght)
    >>>
    >>> Yes, but again the idea here is we KNOW the maximum size> of our
    >>> file lines,

    >>
    >> However, some people want to copy files without worrying about line
    >> length. With ggets (and fggets) you can handle this with ease, as
    >> in the following:
    >>
    >> [1] c:\c\junk>cc -o fcopylns.exe ggets.o junk.c
    >>
    >> [1] c:\c\junk>fcopylns <junk.c
    >> #include <stdio.h>
    >> #include <stdlib.h>
    >> #include "ggets.h"
    >>
    >> int main(void) {
    >> char *line;
    >>
    >> while (0 == ggets(&line)) {
    >> puts(line);
    >> free(line);
    >> }
    >> return 0;
    >> } /* main, fcopylns */
    >>
    >> Note the complexity. You can get the source etc. for ggets at:
    >>
    >> <http://cbfalconer.home.att.net/download/ggets.zip>
    >>

    > Sure, something like that might come in handy in some situations,
    > but I actually take a somewhat different tack for parsing out text
    > "tables" with potentially (unpredictably) HUGE "field" sizes.


    Try out ggets. It will handle ANY size line. I deliberately
    designed it to replace gets, with the usage simplicity, but no
    worry about over-run. It's primary use is in interactive work, but
    the efficiency is not bad for general use.

    --
    Chuck F (cbfalconer at maineline dot net)
    <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Nov 30, 2007
    #14
  15. CBFalconer said:

    <snip>

    > Try out ggets. It will handle ANY size line.


    That's a dangerous claim. :)

    --
    Richard Heathfield <http://www.cpax.org.uk>
    Email: -http://www. +rjh@
    Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
    "Usenet is a strange place" - dmr 29 July 1999
    Richard Heathfield, Nov 30, 2007
    #15
  16. "Bill Reid" <> writes:
    > pete <> wrote in message
    > news:...
    >> Bill Reid wrote:
    >> >
    >> > Roland Pibinger <> wrote in message
    >> > news:...
    >> > > On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
    >> > > > if((text_file=fopen(text_file_path,"rt"))==NULL) {

    >>
    >> > > - with an explanation for "rt" instead of "r"
    >> >
    >> > Read the friggin' man page!

    >>
    >> That's the problem.
    >>
    >> Man pages aren't part of the C programming language.
    >>
    >> Using "rt" as a second argument in a fopen function call
    >> isn't part of the C programming language either.
    >>

    > Yeah, I guess you're right, from a completely strict interpretation
    > of the "standard"...except, of course, that the "standard" itself is
    > actually contradictory as a practical matter on the subject.


    Why do you insist on using scare-quotes for the word "standard"? And
    how is the standard contradictory?

    > If "rt" is NOT a part of the "C programming language" (standard),
    > then of course it would be completely illegal to use "rt". But that's
    > NOT what the "standard" says, now is it?


    Here's what the standard actually says:

    The argument mode points to a string. If the string is one of the
    following, the file is open in the indicated mode. Otherwise, the
    behavior is undefined.

    This is followed by a list of mode strings, including "r" but not
    including "rt". The "r" mode specifies opening a text file for
    reading.

    I see no contradiction. Using "rt" is not "completely illegal" (i.e.,
    the implementation isn't required to reject it); the standard simply
    assigns no meaning to it.

    > Meanwhile, on my "implementation", there is a global file opening
    > mode variable that can be over-ridden by using either 't' or 'b'. Since
    > it is set to "O_TEXT" by default I don't actually NEED to use the "rt",
    > but since this has also been the case for several wildly-different
    > "implementations" in my experience, I am in the habit of setting it
    > that way. I suspect there aren't a lot of C compilers out there where
    > this would cause a problem, since a lot of them fudge around the
    > "undefined behavior" in their "man pages", explicitly allowing the
    > "rt" while acknowledging it is a waste of a character...


    There are *no* conforming C implementations on which using just "r"
    rather than "rt" will cause a problem.

    > But, I guess you're "technically" correct, I should have noted that
    > to open a text file under the "C standard" you only need to use "r",
    > and "rt" MIGHT cause a "portability" problem...


    Here's a clue. A simpler version of the phrase "technically correct"
    is "correct". I can think of no reason to use "rt" rather than "r";
    where "rt" is supported, it presumably does the same thing, and where
    "rt" is not supported, using "r" is correct.

    --
    Keith Thompson (The_Other_Keith) <>
    Looking for software development work in the San Diego area.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
    Keith Thompson, Nov 30, 2007
    #16
  17. CBFalconer Guest

    Richard Heathfield wrote:
    > CBFalconer said:
    >
    > <snip>
    >
    >> Try out ggets. It will handle ANY size line.

    >
    > That's a dangerous claim. :)


    All right. Limited by available allocatable memory. It still
    won't overrun.

    --
    Chuck F (cbfalconer at maineline dot net)
    <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Nov 30, 2007
    #17
  18. pete Guest

    CBFalconer wrote:
    >
    > Bill Reid wrote:
    > > CBFalconer <> wrote in message
    > >> Bill Reid wrote:
    > >>> Roland Pibinger <> wrote in message
    > >>>
    > >> ... snip ...
    > >>>
    > >>>> - whithout static FILE
    > >>>
    > >>> Possibly, but the idea here is just to read a single file and
    > >>> then close it right up...
    > >>>
    > >>>> - for arbitrary long lines (no hard-coded maximum line lenght)
    > >>>
    > >>> Yes, but again the idea here is we KNOW the maximum size> of our
    > >>> file lines,
    > >>
    > >> However, some people want to copy files without worrying about line
    > >> length. With ggets (and fggets) you can handle this with ease, as
    > >> in the following:
    > >>
    > >> [1] c:\c\junk>cc -o fcopylns.exe ggets.o junk.c
    > >>
    > >> [1] c:\c\junk>fcopylns <junk.c
    > >> #include <stdio.h>
    > >> #include <stdlib.h>
    > >> #include "ggets.h"
    > >>
    > >> int main(void) {
    > >> char *line;
    > >>
    > >> while (0 == ggets(&line)) {
    > >> puts(line);
    > >> free(line);
    > >> }
    > >> return 0;
    > >> } /* main, fcopylns */
    > >>
    > >> Note the complexity. You can get the source etc. for ggets at:
    > >>
    > >> <http://cbfalconer.home.att.net/download/ggets.zip>
    > >>

    > > Sure, something like that might come in handy in some situations,
    > > but I actually take a somewhat different tack for parsing out text
    > > "tables" with potentially (unpredictably) HUGE "field" sizes.

    >
    > Try out ggets. It will handle ANY size line. I deliberately
    > designed it to replace gets, with the usage simplicity, but no
    > worry about over-run. It's primary use is in interactive work, but
    > the efficiency is not bad for general use.


    The definition of fggets declares no size_t type objects!

    The cast in this expression in fggets, doesn't do anything:
    realloc(buffer, (size_t)cursize))


    I think that ggets.h:

    int fggets(char* *ln, FILE *f);

    #define ggets(ln) fggets(ln, stdin)

    should also have this function declaration:

    int (ggets)(char* *ln);

    and that ggets.c should also have this function definition:

    int (ggets)(char* *ln)
    {
    return ggets(ln);
    }

    --
    pete
    pete, Nov 30, 2007
    #18
  19. CBFalconer Guest

    pete wrote:
    > CBFalconer wrote:
    >

    .... snip ...
    >
    >> Try out ggets. It will handle ANY size line. I deliberately
    >> designed it to replace gets, with the usage simplicity, but no
    >> worry about over-run. It's primary use is in interactive work,
    >> but the efficiency is not bad for general use.

    >
    > The definition of fggets declares no size_t type objects!
    >
    > The cast in this expression in fggets, doesn't do anything:
    > realloc(buffer, (size_t)cursize))


    You didn't read it. cursize has been increased when this is
    encountered. The testing in the zipfile proves it. Oh, you mean
    the parameter. That is harmless. cursize should probably be a
    size_t anyhow.

    > I think that ggets.h:
    >
    > int fggets(char* *ln, FILE *f);
    > #define ggets(ln) fggets(ln, stdin)
    >
    > should also have this function declaration:
    >
    > int (ggets)(char* *ln);


    Why?

    --
    Chuck F (cbfalconer at maineline dot net)
    <http://cbfalconer.home.att.net>
    Try the download section.



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Nov 30, 2007
    #19
  20. Bill Reid Guest

    Keith Thompson <> wrote in message
    news:...
    > "Bill Reid" <> writes:
    > > pete <> wrote in message
    > > news:...
    > >> Bill Reid wrote:
    > >> >
    > >> > Roland Pibinger <> wrote in message
    > >> > news:...
    > >> > > On Tue, 27 Nov 2007 02:19:55 GMT, "Bill Reid" wrote:
    > >> > > > if((text_file=fopen(text_file_path,"rt"))==NULL) {
    > >>
    > >> > > - with an explanation for "rt" instead of "r"
    > >> >
    > >> > Read the friggin' man page!
    > >>
    > >> That's the problem.
    > >>
    > >> Man pages aren't part of the C programming language.
    > >>
    > >> Using "rt" as a second argument in a fopen function call
    > >> isn't part of the C programming language either.
    > >>

    > > Yeah, I guess you're right, from a completely strict interpretation
    > > of the "standard"...except, of course, that the "standard" itself is
    > > actually contradictory as a practical matter on the subject.

    >
    > Why do you insist on using scare-quotes for the word "standard"?


    For your information, those are "sarcastic quote marks", and I have
    an annoying habit of using them, and look, I just did it again...

    > And
    > how is the standard contradictory?
    >

    It declares "non-standard" (whoops, did it again) function arguments
    as possibly causing errors because they could possibly open file types
    not intended by the programmer. This is some amazing circular logic
    that only a committee could cogitate...

    > > If "rt" is NOT a part of the "C programming language" (standard),
    > > then of course it would be completely illegal to use "rt". But that's
    > > NOT what the "standard" says, now is it?

    >
    > Here's what the standard actually says:
    >
    > The argument mode points to a string. If the string is one of the
    > following, the file is open in the indicated mode. Otherwise, the
    > behavior is undefined.
    >

    My only copy of the LATEST "standard" says more than this, as
    I indicated, they put some "scare language" in there to frighten people
    who've been fool enough to use "rt" as instructed by their "implementations"
    for years to "conform" to the will of the committee...

    > This is followed by a list of mode strings, including "r" but not
    > including "rt". The "r" mode specifies opening a text file for
    > reading.
    >
    > I see no contradiction. Using "rt" is not "completely illegal" (i.e.,
    > the implementation isn't required to reject it); the standard simply
    > assigns no meaning to it.
    >

    Read the LATEST "standard", or maybe read a little further in
    what you've been quoting here...

    > > Meanwhile, on my "implementation", there is a global file opening
    > > mode variable that can be over-ridden by using either 't' or 'b'. Since
    > > it is set to "O_TEXT" by default I don't actually NEED to use the "rt",
    > > but since this has also been the case for several wildly-different
    > > "implementations" in my experience, I am in the habit of setting it
    > > that way. I suspect there aren't a lot of C compilers out there where
    > > this would cause a problem, since a lot of them fudge around the
    > > "undefined behavior" in their "man pages", explicitly allowing the
    > > "rt" while acknowledging it is a waste of a character...

    >
    > There are *no* conforming C implementations on which using just "r"
    > rather than "rt" will cause a problem.


    So what's your point? My "implementation" DOES not only ALLOW
    it but REQUIRE it under certain circumstances...as a practical matter,
    what am I to do? Hold my breath until all the "non-conforming" compilers
    disappear retroactively?

    > > But, I guess you're "technically" correct, I should have noted that
    > > to open a text file under the "C standard" you only need to use "r",
    > > and "rt" MIGHT cause a "portability" problem...

    >
    > Here's a clue. A simpler version of the phrase "technically correct"
    > is "correct". I can think of no reason to use "rt" rather than "r";
    > where "rt" is supported, it presumably does the same thing, and where
    > "rt" is not supported, using "r" is correct.


    Try reading what I actually wrote...carefully this time. With many
    compilers, I might wind up opening the file as "binary" (now THAT'S
    scary!)...

    ---
    William Ernest Reid
    Bill Reid, Dec 1, 2007
    #20
    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. David Williams
    Replies:
    2
    Views:
    1,107
    Jacob Yang [MSFT]
    Aug 12, 2003
  2. Darrel
    Replies:
    3
    Views:
    657
    Kevin Spencer
    Nov 11, 2004
  3. Wael Soliman

    ASP.NET Reading problem (reading .xls)

    Wael Soliman, Jan 3, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    4,780
    =?Utf-8?B?dmluYXk=?=
    Jan 3, 2005
  4. Rio
    Replies:
    4
    Views:
    1,173
  5. Replies:
    0
    Views:
    771
Loading...

Share This Page