array of structures.

Discussion in 'C Programming' started by Cell, Mar 9, 2008.

  1. Cell

    Cell Guest

    I have structures like this in my program -

    typedef vector vectorstruct
    {
    double x, y,z;
    } vector;

    typedef struct verticesstruct
    {
    vector v;
    } vertex; /*a vertex is a vector */

    typedef struct trianglestruct
    {
    int v0,v1, v2;
    }triangle;

    typedef struct objectstruct
    {
    int nvert;
    int ntri;
    vertex *vert;
    triangle *tri;
    }object;

    ................
    ...............

    later somewhere in the program i have a statement like this -

    object *obj;

    obj->vert = malloc( nvert * sizeof(vertex)); /* Creating an array of
    vertices */

    obj->tri = malloc(ntri * sizeof(triangle));

    for(i=0;i<obj->nvert; i++)/* trying to take input for each vertex
    which has x, y, z components as it is a vector*/
    scanf("%f %f %f", &obj->vert.x, &obj->vert.y, &obj->vert.z);

    ^^^^^^^^ is this above notation of creating an array and then
    accessing the elements correct ??


    later on i also do this -

    for(i=0;i<obj->ntri;i++)
    scanf("%d %d %d", &obj->tri.v0, &obj->tri.v1, &obj->tri.v2);
     
    Cell, Mar 9, 2008
    #1
    1. Advertising

  2. On Sun, 09 Mar 2008 06:45:54 -0700, Cell wrote:
    > I have structures like this in my program -
    >
    > typedef vector vectorstruct


    Syntax error. "vector" should be "struct". Please try to copy and paste
    from code you've actually tried to use as much as possible, so that errors
    such as these can be avoided.

    > {
    > double x, y,z;
    > } vector;
    >
    > typedef struct verticesstruct
    > {
    > vector v;


    This is fine, but...

    > } vertex; /*a vertex is a vector */


    ....vertex is a structure with one member. This member is named "v", and
    has type vector.

    > typedef struct trianglestruct
    > {
    > int v0,v1, v2;
    > }triangle;


    Okay, so a triangle has three members v0, v1, and v2.

    > typedef struct objectstruct
    > {
    > int nvert;
    > int ntri;
    > vertex *vert;
    > triangle *tri;
    > }object;
    >
    > ...............
    > ..............
    >
    > later somewhere in the program i have a statement like this -
    >
    > object *obj;
    >
    > obj->vert = malloc( nvert * sizeof(vertex)); /* Creating an array of
    > vertices */


    What is nvert? You haven't declared it. Did you mean obj->nvert? Please
    try to copy and paste from code you've actually tried to use as much as
    possible, so that errors such as these can be avoided.

    > obj->tri = malloc(ntri * sizeof(triangle));


    See above.

    > for(i=0;i<obj->nvert; i++)/* trying to take input for each vertex which
    > has x, y, z components as it is a vector*/ scanf("%f %f %f",
    > &obj->vert.x, &obj->vert.y, &obj->vert.z);


    A vertex has one member. This member has a name "v". A vertex does not
    have any members x, y, or z. A vector does.

    > ^^^^^^^^ is this above notation of creating an array


    The array creation is okay.

    > and then accessing
    > the elements correct ??


    The access is not okay.

    > later on i also do this -
    >
    > for(i=0;i<obj->ntri;i++)
    > scanf("%d %d %d", &obj->tri.v0, &obj->tri.v1, &obj->tri.v2);


    A triangle has members v0, v1, and v2, and you're accessing members v0,
    v1, and v2. Not surprisingly, this works. :)
     
    Harald van Dijk, Mar 9, 2008
    #2
    1. Advertising

  3. Cell

    Eric Sosman Guest

    Cell wrote:
    > I have structures like this in my program -


    A problem with "like this" code fragments is that when
    someone sees a problem with them and then tries to explain to
    you the nature of the problem, it may have nothing to do with
    the actual problems of the actual original code.

    Long ago when kings were regarded as semi-divine, it was
    seen that their divinity did not shield them from illness and
    they sometimes needed treatment from doctors. But most doctors
    were not of noble blood, and in some places it was unthinkable
    for a commoner to touch the Royal Person. So the king would
    nominate some less-divine person as a surrogate, who would
    imitate the king's malady while submitting to the doctor's
    examination. The proprieties were respected, but what do you
    think of the likely accuracy of such diagnosis by proxy?

    > typedef vector vectorstruct


    For example, this line is invalid and will not compile.
    It serves no purpose except to distract attention from the
    question you are actually interested in.

    > {
    > double x, y,z;
    > } vector;
    >
    > typedef struct verticesstruct
    > {
    > vector v;
    > } vertex; /*a vertex is a vector */


    Seems a rather pointless (pun intended) struct; why
    bother having it at all?

    > typedef struct trianglestruct
    > {
    > int v0,v1, v2;
    > }triangle;
    >
    > typedef struct objectstruct
    > {
    > int nvert;
    > int ntri;
    > vertex *vert;
    > triangle *tri;
    > }object;
    >
    > ...............
    > ..............
    >
    > later somewhere in the program i have a statement like this -
    >
    > object *obj;
    >
    > obj->vert = malloc( nvert * sizeof(vertex)); /* Creating an array of
    > vertices */


    You're carefully allocating space for a bunch of vertices,
    but you've forgotten to allocate space for the object. The
    pointer variable `obj' has not been initialized; it "has a
    garbage value." When you try to store a value in `obj->vert',
    anything at all might happen.

    (Oh, you say you *do* allocate some space and point obj
    at it? Well, why didn't you say so in the first place, by
    posting actual code instead of "like this" code?)

    If we assume that obj actually points to something usable
    and that nvert is an integer that is non-negative and not too
    huge, then the allocation is all right. It can be improved
    just a little bit by writing it as

    obj->vert = malloc(nvert * sizeof *obj->vert);

    Either way, the allocation attempt should be followed
    (usually immediately, but sometimes a little distance is
    permissible) by a test to see whether the attempt succeeded:

    if (obj->vert == NULL) die_or_take_corrective_action();

    > obj->tri = malloc(ntri * sizeof(triangle));


    Same remarks.

    > for(i=0;i<obj->nvert; i++)/* trying to take input for each vertex
    > which has x, y, z components as it is a vector*/
    > scanf("%f %f %f", &obj->vert.x, &obj->vert.y, &obj->vert.z);
    >
    > ^^^^^^^^ is this above notation of creating an array and then
    > accessing the elements correct ??


    Yes, under reasonable assumptions about what the code
    actually looks like. But you're using scanf() incorrectly:
    "%f" is the wrong conversion specifier for double, and any
    input failure will escape your notice entirely.

    > later on i also do this -
    >
    > for(i=0;i<obj->ntri;i++)
    > scanf("%d %d %d", &obj->tri.v0, &obj->tri.v1, &obj->tri.v2);


    As before, the array accesses look fine given similar
    assumptions, and as before the use of scanf() is broken.

    Real code next time, please.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Mar 9, 2008
    #3
  4. Cell

    Cell Guest

    On Mar 9, 7:21 pm, Eric Sosman <> wrote:
    > Cell wrote:
    > > I have structures like this in my program -

    >
    > A problem with "like this" code fragments is that when
    > someone sees a problem with them and then tries to explain to
    > you the nature of the problem, it may have nothing to do with
    > the actual problems of the actual original code.
    >
    > Long ago when kings were regarded as semi-divine, it was
    > seen that their divinity did not shield them from illness and
    > they sometimes needed treatment from doctors. But most doctors
    > were not of noble blood, and in some places it was unthinkable
    > for a commoner to touch the Royal Person. So the king would
    > nominate some less-divine person as a surrogate, who would
    > imitate the king's malady while submitting to the doctor's
    > examination. The proprieties were respected, but what do you
    > think of the likely accuracy of such diagnosis by proxy?
    >
    > > typedef vector vectorstruct

    >
    > For example, this line is invalid and will not compile.
    > It serves no purpose except to distract attention from the
    > question you are actually interested in.
    >
    > > {
    > > double x, y,z;
    > > } vector;

    >
    > > typedef struct verticesstruct
    > > {
    > > vector v;
    > > } vertex; /*a vertex is a vector */

    >
    > Seems a rather pointless (pun intended) struct; why
    > bother having it at all?
    >
    >
    >
    >
    >
    > > typedef struct trianglestruct
    > > {
    > > int v0,v1, v2;
    > > }triangle;

    >
    > > typedef struct objectstruct
    > > {
    > > int nvert;
    > > int ntri;
    > > vertex *vert;
    > > triangle *tri;
    > > }object;

    >
    > > ...............
    > > ..............

    >
    > > later somewhere in the program i have a statement like this -

    >
    > > object *obj;

    >
    > > obj->vert = malloc( nvert * sizeof(vertex)); /* Creating an array of
    > > vertices */

    >
    > You're carefully allocating space for a bunch of vertices,
    > but you've forgotten to allocate space for the object. The
    > pointer variable `obj' has not been initialized; it "has a
    > garbage value." When you try to store a value in `obj->vert',
    > anything at all might happen.
    >
    > (Oh, you say you *do* allocate some space and point obj
    > at it? Well, why didn't you say so in the first place, by
    > posting actual code instead of "like this" code?)
    >
    > If we assume that obj actually points to something usable
    > and that nvert is an integer that is non-negative and not too
    > huge, then the allocation is all right. It can be improved
    > just a little bit by writing it as
    >
    > obj->vert = malloc(nvert * sizeof *obj->vert);
    >
    > Either way, the allocation attempt should be followed
    > (usually immediately, but sometimes a little distance is
    > permissible) by a test to see whether the attempt succeeded:
    >
    > if (obj->vert == NULL) die_or_take_corrective_action();
    >
    > > obj->tri = malloc(ntri * sizeof(triangle));

    >
    > Same remarks.
    >
    > > for(i=0;i<obj->nvert; i++)/* trying to take input for each vertex
    > > which has x, y, z components as it is a vector*/
    > > scanf("%f %f %f", &obj->vert.x, &obj->vert.y, &obj->vert.z);

    >
    > > ^^^^^^^^ is this above notation of creating an array and then
    > > accessing the elements correct ??

    >
    > Yes, under reasonable assumptions about what the code
    > actually looks like. But you're using scanf() incorrectly:
    > "%f" is the wrong conversion specifier for double, and any
    > input failure will escape your notice entirely.
    >
    > > later on i also do this -

    >
    > > for(i=0;i<obj->ntri;i++)
    > > scanf("%d %d %d", &obj->tri.v0, &obj->tri.v1, &obj->tri.v2);

    >
    > As before, the array accesses look fine given similar
    > assumptions, and as before the use of scanf() is broken.
    >
    > Real code next time, please.
    >
    > --
    > Eric Sosman
    >


    I apologize.

    I will post the entire code and provide full details.

    please help.
     
    Cell, Mar 9, 2008
    #4
  5. Cell

    Cell Guest

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

    typedef struct vectorstruct
    {
    double x, y, z;
    }vector;

    typedef struct verticesstruct
    {
    vector v;
    }vertex;

    typedef struct trianglestruct
    {
    int v0, v1, v2;
    }triangle;

    typedef struct objectstruct
    {
    int nvert;
    int ntri;
    vertex *vert;
    triangle *tri;
    }object;

    int read_dat_file( char * dat_file, object * obj )
    {

    FILE *fp;
    int i;

    if(!(fp = fopen(dat_file,"r")))
    return -1;
    while(fp!=NULL)
    {
    fscanf(fp, "%d %d", &(obj->nvert), &(obj->ntri));
    printf("\n%d %d", obj->nvert, obj->ntri);

    obj->vert= malloc(obj->nvert * sizeof(vertex));

    obj->tri = malloc(obj->ntri * sizeof(triangle));

    for(i=0;i<obj->nvert;i++)
    {
    fscanf(fp, "%f %f %f",&(obj->vert.v.x), &(obj->vert.v.y), &(obj-
    >vert.v.z));

    printf("%f %f %f", obj->vert.v.x, obj->vert.v.y, obj-
    >vert.v.z);

    }

    for(i=0;i<obj->ntri;i++)
    {
    fscanf(fp, "%d %d %d",&(obj->tri.v0), &(obj->tri.v1), &(obj-
    >tri.v2));

    printf("%d %d %d", obj->tri.v0, obj->tri.v1, obj->tri.v2);
    }

    }
    return 1;
    }

    int main()
    {

    object *obj;
    char *s;
    clrscr();
    obj = malloc(sizeof(object));
    strcpy(s, "sphere.dat");
    if(!(read_dat_file(s , obj)))
    printf("unsuccessful");
    return 0;

    }
     
    Cell, Mar 9, 2008
    #5
  6. Cell

    Cell Guest

    the sphere.dat file contains description of a sphere which has been
    triangulated..

    the first line of sphere.dat is something like this -

    nvert ntri /*the number of vertices, number of triangles */

    in the case of a sphere, nvert = 602, ntri = 1200

    from the second line we have coordinates of each vertex. A combination
    of 3 vertices forms a triangle.

    x1 y1 z1
    x2 y2 z2
    .........
    .........
    .........
    xnvert ynvert znvert

    I stored this in a list of vertices. Hence the vert pointer in object
    structure. Similarly there is a tri pointer which can be used for
    dynamically creating a list of triangles.

    After the n vertices, we have the description of triangles (1200
    entries)

    12 0 1
    3 4 5
    23 8 5
    .......
    .......
    .......

    Those numbers are basically indices to vertex list. So 12 indicates
    the 12th vertex or 12 the entry in the vertex list. 0 indicates
    0th(first entry) in the vertex list 1 indicates 1st element of vertex
    list. So basically a combination of 3 vertices is forming a triangle.
    And this is what Im trying to read from the file and print.
     
    Cell, Mar 9, 2008
    #6
  7. Cell

    santosh Guest

    Cell wrote:

    > #include<stdio.h>
    > #include<stdlib.h>
    > #include<string.h>
    >
    > typedef struct vectorstruct
    > {
    > double x, y, z;
    > }vector;
    >
    > typedef struct verticesstruct
    > {
    > vector v;
    > }vertex;
    >
    > typedef struct trianglestruct
    > {
    > int v0, v1, v2;
    > }triangle;
    >
    > typedef struct objectstruct
    > {
    > int nvert;
    > int ntri;
    > vertex *vert;
    > triangle *tri;
    > }object;
    >
    > int read_dat_file( char * dat_file, object * obj )
    > {
    >
    > FILE *fp;
    > int i;
    >
    > if(!(fp = fopen(dat_file,"r")))
    > return -1;
    > while(fp!=NULL)
    > {
    > fscanf(fp, "%d %d", &(obj->nvert), &(obj->ntri));
    > printf("\n%d %d", obj->nvert, obj->ntri);
    >
    > obj->vert= malloc(obj->nvert * sizeof(vertex));
    >
    > obj->tri = malloc(obj->ntri * sizeof(triangle));
    >
    > for(i=0;i<obj->nvert;i++)
    > {
    > fscanf(fp, "%f %f %f",&(obj->vert.v.x), &(obj->vert.v.y), &(obj-
    >>vert.v.z));

    > printf("%f %f %f", obj->vert.v.x, obj->vert.v.y, obj-
    >>vert.v.z);

    > }
    >
    > for(i=0;i<obj->ntri;i++)
    > {
    > fscanf(fp, "%d %d %d",&(obj->tri.v0), &(obj->tri.v1), &(obj-
    >>tri.v2));

    > printf("%d %d %d", obj->tri.v0, obj->tri.v1, obj->tri.v2);
    > }
    >
    > }
    > return 1;
    > }
    >
    > int main()
    > {
    >
    > object *obj;
    > char *s;
    > clrscr();


    This is not a portable function. The next compiler you compile it on
    might not have such a function.

    > obj = malloc(sizeof(object));
    > strcpy(s, "sphere.dat");


    You have not allocates space for copying.

    > if(!(read_dat_file(s , obj)))


    Anything other than zero is regarded as "true" in C. Therefore the -1
    that you return from read_dat_file will also be regarded as true. The
    following printf statement will execute only when read_dat_file returns
    zero, which it never does.

    > printf("unsuccessful");
    > return 0;
    >
    > }
     
    santosh, Mar 9, 2008
    #7
  8. Cell

    Cell Guest


    > This is not a portable function. The next compiler you compile it on
    > might not have such a function.
    >


    are you talking about clrscr() ? Ok I will remove it then.

    > You have not allocates space for copying.


    Will this work in your opinion -

    char *s = "sphere.dat";

    or

    char s[] = "sphere.dat";

    But other wise what is wrong in using strcpy ?

    >
    > > if(!(read_dat_file(s , obj)))

    >
    > Anything other than zero is regarded as "true" in C. Therefore the -1
    > that you return from read_dat_file will also be regarded as true. The
    > following printf statement will execute only when read_dat_file returns
    > zero, which it never does.
    >
    > > printf("unsuccessful");
    > > return 0;

    >
    > > }


    So I guess I should return 0 in read_dat_file function in case the
    file cannot be read and 1 if the operation is successful.
     
    Cell, Mar 9, 2008
    #8
  9. Cell

    Cell Guest

    i corrected the things santosh said and now the program is giving
    "unsuccessful" as o/p. I do not understand what is the problem in
    reading the file and printing it.
     
    Cell, Mar 9, 2008
    #9
  10. Cell

    santosh Guest

    Cell wrote:

    >
    >> This is not a portable function. The next compiler you compile it on
    >> might not have such a function.
    >>

    >
    > are you talking about clrscr() ? Ok I will remove it then.
    >
    >> You have not allocates space for copying.

    >
    > Will this work in your opinion -
    >
    > char *s = "sphere.dat";
    >
    > or
    >
    > char s[] = "sphere.dat";


    Yes, both will.

    > But other wise what is wrong in using strcpy ?


    Nothing. But in the statement:

    strcpy(s, "sphere.dat");

    the string pointed to by the second argument is copied to the address
    given as the first argument. But 's' has not been previously
    initialised to point to some valid storage, so the strcpy call will
    write to some random address, which could lead to anything from silent
    memory corruption to a system crash.

    You can initialise 's' like this:

    s = malloc(strlen("sphere.dat") + 1);

    >> > if(!(read_dat_file(s , obj)))

    >>
    >> Anything other than zero is regarded as "true" in C. Therefore the -1
    >> that you return from read_dat_file will also be regarded as true. The
    >> following printf statement will execute only when read_dat_file
    >> returns zero, which it never does.
    >>
    >> > printf("unsuccessful");
    >> > return 0;

    >>
    >> > }

    >
    > So I guess I should return 0 in read_dat_file function in case the
    > file cannot be read and 1 if the operation is successful.


    That's one possibility. All that C knows about is that zero is false, a
    non-zero value is true.
     
    santosh, Mar 9, 2008
    #10
  11. Cell

    santosh Guest

    Cell wrote:

    > i corrected the things santosh said and now the program is giving
    > "unsuccessful" as o/p. I do not understand what is the problem in
    > reading the file and printing it.


    Please check all your fscanf calls. Here is what the standard says
    regarding what fscanf returns:

    >>>>>

    The fscanf function returns the value of the macro EOF if an input
    failure occurs before any conversion. Otherwise, the function returns
    the number of input items assigned, which can be fewer than provided
    for, or even zero, in the event of an early matching failure.
    <<<<<

    Also the format for scanning doubles is %lf not %f.
     
    santosh, Mar 9, 2008
    #11
  12. Cell

    Eric Sosman Guest

    Cell wrote:
    > #include<stdio.h>
    > #include<stdlib.h>
    > #include<string.h>
    >
    > typedef struct vectorstruct
    > {
    > double x, y, z;
    > }vector;
    >
    > typedef struct verticesstruct
    > {
    > vector v;
    > }vertex;
    >
    > typedef struct trianglestruct
    > {
    > int v0, v1, v2;
    > }triangle;
    >
    > typedef struct objectstruct
    > {
    > int nvert;
    > int ntri;
    > vertex *vert;
    > triangle *tri;
    > }object;
    >
    > int read_dat_file( char * dat_file, object * obj )


    A minor improvement: Change the first argument to
    `const char * dat_file' to "advertise" the fact that the
    function will not modify the string it points to.

    > {
    >
    > FILE *fp;
    > int i;
    >
    > if(!(fp = fopen(dat_file,"r")))


    Works, but most would find `if ((fp = fopen(...)) != NULL)'
    clearer. Many would even prefer to use two statements:

    fp = fopen(...);
    if (fp == NULL)

    > return -1;
    > while(fp!=NULL)


    First serious error: You have just determined that fp
    is not NULL, and there is nothing in the body of the loop
    that will ever set it to NULL. Thus, there is nothing to
    stop the loop, and it will keep on running until you pull
    the plug. If you're trying to keep reading until you've
    read the entire file, this is not the way to do it. Some
    time with your textbook or with the FAQ is in order.

    > {
    > fscanf(fp, "%d %d", &(obj->nvert), &(obj->ntri));


    If there's an input error or if the file starts with
    "4,17" (note the comma), how will you discover the failure?
    Look up "The Ten Commandments for C Programmers" and pay
    attention to them.

    > printf("\n%d %d", obj->nvert, obj->ntri);


    Echoing the input values is fine, but is a rather weak
    form of validity checking. A few tests to ensure that the
    values are reasonable would be a good idea -- what if the
    file begins with "4 -44", for example?

    > obj->vert= malloc(obj->nvert * sizeof(vertex));


    You should test the returned value to see whether the
    attempt to allocate memory succeeded or failed. See the
    Ten Commandments.

    > obj->tri = malloc(obj->ntri * sizeof(triangle));


    Same remark.

    > for(i=0;i<obj->nvert;i++)
    > {
    > fscanf(fp, "%f %f %f",&(obj->vert.v.x), &(obj->vert.v.y),
    >> &(obj->vert.v.z));


    (Slightly reformatted.) Second serious error: "%f" is
    not the correct conversion specifier for double values. And
    once again you will remain oblivious to any trouble in the
    input.

    > printf("%f %f %f", obj->vert.v.x, obj->vert.v.y, obj-
    >> vert.v.z);

    > }
    >
    > for(i=0;i<obj->ntri;i++)
    > {
    > fscanf(fp, "%d %d %d",&(obj->tri.v0), &(obj->tri.v1), &(obj-
    >> tri.v2));


    Again, you will not find out about input problems. Also,
    you've said in another message that the values read here are
    supposed to be array indices. Therefore, something is wrong
    if any of them are negative or are too large; you should test
    them for validity.

    > printf("%d %d %d", obj->tri.v0, obj->tri.v1, obj->tri.v2);
    > }
    >
    > }
    > return 1;
    > }
    >
    > int main()
    > {
    >
    > object *obj;
    > char *s;
    > clrscr();


    You haven't defined this function.

    > obj = malloc(sizeof(object));


    Always check the value returned by malloc().

    > strcpy(s, "sphere.dat");


    Third serious error: The variable `s' has not been
    initialized and "points to garbage." There's no telling
    what will happen.

    > if(!(read_dat_file(s , obj)))
    > printf("unsuccessful");


    Fourth serious error: The read_dat() function is written
    to return either 1 or -1, and both of those are "true" for
    the purposes of the `if' statement.

    > return 0;
    >
    > }


    --
    Eric Sosman
    lid
     
    Eric Sosman, Mar 9, 2008
    #12
  13. Cell

    santosh Guest

    Cell wrote:

    > i corrected the things santosh said and now the program is giving
    > "unsuccessful" as o/p. I do not understand what is the problem in
    > reading the file and printing it.


    Here is my version of your code. Please try with your file.

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

    typedef struct vectorstruct {
    double x, y, z;
    } vector;

    typedef struct verticesstruct {
    vector v;
    } vertex;

    typedef struct trianglestruct {
    int v0, v1, v2;
    } triangle;

    typedef struct objectstruct {
    int nvert;
    int ntri;
    vertex *vert;
    triangle *tri;
    } object;

    int read_dat_file(FILE *fp, object obj)
    {
    int rc = 1, i;
    char *mfail_msg = "malloc() failed. line: %d\n";
    char *fscfail_msg = "fscanf() failed. line: %d\n";

    while (1) {
    if (fscanf(fp, "%d %d", &(obj.nvert), &(obj.ntri)) != 2) {
    fprintf(stderr, fscfail_msg, __LINE__);
    rc = 0;
    break;
    }
    printf("%d %d\n", obj.nvert, obj.ntri);

    obj.vert = malloc(obj.nvert * sizeof *(obj.vert));
    obj.tri = malloc(obj.ntri * sizeof *(obj.tri));
    if (!obj.vert || !obj.tri) {
    fprintf(stderr, mfail_msg, __LINE__);
    rc = 0;
    break;
    }

    for (i = 0; i < obj.nvert; i++) {
    if (fscanf(fp, "%lf %lf %lf", &((obj.vert).v.x),
    &((obj.vert).v.y), &((obj.vert).v.z)) != 3) {
    fprintf(stderr, fscfail_msg, __LINE__);
    rc = 0;
    break;
    }
    printf("%f %f %f\n", (obj.vert).v.x, (obj.vert).v.y,
    (obj.vert).v.z);
    }

    for (i = 0; i < obj.ntri; i++) {
    if (fscanf(fp, "%d %d %d", &((obj.tri).v0),
    &((obj.tri).v1),
    &((obj.tri).v2)) != 3) {
    fprintf(stderr, fscfail_msg, __LINE__);
    rc = 0;
    break;
    }
    printf("%d %d %d\n", (obj.tri).v0, (obj.tri).v1,
    (obj.tri).v2);
    }
    }
    if (feof(fp)) return !rc;
    else return rc;
    }

    int main(void)
    {
    int rc;
    object obj;
    FILE *fp = fopen("sphere.dat", "r");

    if (!fp) { puts("Failed to open file."); return EXIT_FAILURE; }
    rc = read_dat_file(fp, obj);
    if (rc == 0) {
    puts("read_dat_file() failed.");
    }
    else {
    puts("read_dat_file() done.");
    }

    return !rc;
    }

    Here for an example file containing:

    3 3
    1.1 2.1 3.1
    4.1 5.1 6.1
    7.1 8.1 9.1
    0 1 2
    0 1 2
    0 1 2

    The output of the program is:

    3 3
    1.100000 2.100000 3.100000
    4.100000 5.100000 6.100000
    7.100000 8.100000 9.100000
    0 1 2
    0 1 2
    0 1 2
    fscanf() failed. line: 31
    read_dat_file() done.
     
    santosh, Mar 9, 2008
    #13
  14. Cell

    santosh Guest

    Cell wrote:

    > i corrected the things santosh said and now the program is giving
    > "unsuccessful" as o/p. I do not understand what is the problem in
    > reading the file and printing it.


    As Eric Sosman mentioned, if you want your program to be robust you need
    to rethink the way you parse your data file. A corruption in this file
    (regardless of whether it is accidental or deliberate) will likely
    choke fscanf and either cause it to fail (which is the better option)
    or make it return wrong values (which is worse.)

    One alternative is to use fgets to read in a complete line from the file
    and convert the appropriate elements of that line with the strto*
    family of functions. strtol is for long (can also be used for int,
    short and signed char), strtoul is for unsigned long (also for unsigned
    int, unsigned short, and unsigned char), strtoull is for unsigned long
    long, strtoll is for long long, strtod is for double, strtof is for
    float, strtold is for long double. There are others too like strtoimax
    and strtoumax for intmax_t and uintmax_t.

    The strto* functions return more information about what exactly went
    wrong with the conversion, point you to the place where the conversion
    failed, and do not exhibit undefined behaviour on overflow or
    underflow.

    You'll still need to check the converted values for semantic validity of
    course.

    For reference of all the useful functions of the Standard C library see:

    <http://www.dinkumware.com/manuals/>
     
    santosh, Mar 9, 2008
    #14
  15. Cell

    CBFalconer Guest

    Cell wrote:
    >
    > i corrected the things santosh said and now the program is giving
    > "unsuccessful" as o/p. I do not understand what is the problem in
    > reading the file and printing it.


    Nor do I. I quoted your entire post above, and I can see nothing
    objectionable in it, apart from the lower case i. However, it
    won't compile.

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



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Mar 10, 2008
    #15
  16. On Sun, 9 Mar 2008 08:51:03 -0700 (PDT), Cell <>
    wrote:

    >i corrected the things santosh said and now the program is giving
    >"unsuccessful" as o/p. I do not understand what is the problem in
    >reading the file and printing it.


    You may think you did but until you show us the updated code we will
    not be able to help.


    Remove del for email
     
    Barry Schwarz, Mar 11, 2008
    #16
  17. Cell

    Cell Guest

    On Mar 9, 9:47 pm, santosh <> wrote:
    > Cell wrote:
    > > i corrected the things santosh said and now the program is giving
    > > "unsuccessful" as o/p. I do not understand what is the problem in
    > > reading the file and printing it.

    >
    > Here is my version of your code. Please try with your file.
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    >
    > typedef struct vectorstruct {
    > double x, y, z;
    >
    > } vector;
    >
    > typedef struct verticesstruct {
    > vector v;
    >
    > } vertex;
    >
    > typedef struct trianglestruct {
    > int v0, v1, v2;
    >
    > } triangle;
    >
    > typedef struct objectstruct {
    > int nvert;
    > int ntri;
    > vertex *vert;
    > triangle *tri;
    >
    > } object;
    >
    > int read_dat_file(FILE *fp, object obj)
    > {
    > int rc = 1, i;
    > char *mfail_msg = "malloc() failed. line: %d\n";
    > char *fscfail_msg = "fscanf() failed. line: %d\n";
    >
    > while (1) {
    > if (fscanf(fp, "%d %d", &(obj.nvert), &(obj.ntri)) != 2) {
    > fprintf(stderr, fscfail_msg, __LINE__);
    > rc = 0;
    > break;
    > }
    > printf("%d %d\n", obj.nvert, obj.ntri);
    >
    > obj.vert = malloc(obj.nvert * sizeof *(obj.vert));
    > obj.tri = malloc(obj.ntri * sizeof *(obj.tri));
    > if (!obj.vert || !obj.tri) {
    > fprintf(stderr, mfail_msg, __LINE__);
    > rc = 0;
    > break;
    > }
    >
    > for (i = 0; i < obj.nvert; i++) {
    > if (fscanf(fp, "%lf %lf %lf", &((obj.vert).v.x),
    > &((obj.vert).v.y), &((obj.vert).v.z)) != 3) {
    > fprintf(stderr, fscfail_msg, __LINE__);
    > rc = 0;
    > break;
    > }
    > printf("%f %f %f\n", (obj.vert).v.x, (obj.vert).v.y,
    > (obj.vert).v.z);
    > }
    >
    > for (i = 0; i < obj.ntri; i++) {
    > if (fscanf(fp, "%d %d %d", &((obj.tri).v0),
    > &((obj.tri).v1),
    > &((obj.tri).v2)) != 3) {
    > fprintf(stderr, fscfail_msg, __LINE__);
    > rc = 0;
    > break;
    > }
    > printf("%d %d %d\n", (obj.tri).v0, (obj.tri).v1,
    > (obj.tri).v2);
    > }
    > }
    > if (feof(fp)) return !rc;
    > else return rc;
    >
    > }
    >
    > int main(void)
    > {
    > int rc;
    > object obj;
    > FILE *fp = fopen("sphere.dat", "r");
    >
    > if (!fp) { puts("Failed to open file."); return EXIT_FAILURE; }
    > rc = read_dat_file(fp, obj);
    > if (rc == 0) {
    > puts("read_dat_file() failed.");
    > }
    > else {
    > puts("read_dat_file() done.");
    > }
    >
    > return !rc;
    >
    > }
    >
    > Here for an example file containing:
    >
    > 3 3
    > 1.1 2.1 3.1
    > 4.1 5.1 6.1
    > 7.1 8.1 9.1
    > 0 1 2
    > 0 1 2
    > 0 1 2
    >
    > The output of the program is:
    >
    > 3 3
    > 1.100000 2.100000 3.100000
    > 4.100000 5.100000 6.100000
    > 7.100000 8.100000 9.100000
    > 0 1 2
    > 0 1 2
    > 0 1 2
    > fscanf() failed. line: 31
    > read_dat_file() done.



    Can you please explain why the fscanf is showing error at line 31 ?

    Im getting similar messages for random line numbers.
     
    Cell, Mar 11, 2008
    #17
  18. Cell

    santosh Guest

    Cell wrote:

    > On Mar 9, 9:47 pm, santosh <> wrote:
    >> Cell wrote:
    >> > i corrected the things santosh said and now the program is giving
    >> > "unsuccessful" as o/p. I do not understand what is the problem in
    >> > reading the file and printing it.

    >>
    >> Here is my version of your code. Please try with your file.


    <snip code>

    >> The output of the program is:
    >>
    >> 3 3
    >> 1.100000 2.100000 3.100000
    >> 4.100000 5.100000 6.100000
    >> 7.100000 8.100000 9.100000
    >> 0 1 2
    >> 0 1 2
    >> 0 1 2
    >> fscanf() failed. line: 31
    >> read_dat_file() done.

    >
    >
    > Can you please explain why the fscanf is showing error at line 31 ?


    It is because of attempting to read at end-of-file. It has, as you can
    see from the file contents I showed you and the output, read all the
    values in the file, and thus the next call during the loop fails due to
    the file having reached end-of-file. If fscanf had failed due to
    reasons other than end-of-file, the output "read_dat_file() failed."
    would have been printed instead.

    > Im getting similar messages for random line numbers.


    This probably means that the exact format of your file is not what the
    various fscanf calls are expecting it to be.

    Unless you post a complete, compilable version of your program that
    exhibits the errors along with the complete (or a representative)
    contents of your data file, it hard to say what exactly might be wrong
    with your code.

    The *scanf functions are, as I said before, rather difficult to use in a
    robust manner. You might try my advice of using fgets with
    strtol/strtoul/strtod.
     
    santosh, Mar 11, 2008
    #18
    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. michi

    Array of structures

    michi, Nov 18, 2004, in forum: C++
    Replies:
    8
    Views:
    533
    Andrey Tarasevich
    Nov 19, 2004
  2. tweak
    Replies:
    14
    Views:
    2,813
    Eric Sosman
    Jun 11, 2004
  3. Alfonso Morra
    Replies:
    11
    Views:
    740
    Emmanuel Delahaye
    Sep 24, 2005
  4. valerio
    Replies:
    3
    Views:
    383
  5. Amit  Limaye
    Replies:
    4
    Views:
    467
    Phlip
    Apr 10, 2006
Loading...

Share This Page