array of structures.

C

Cell

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);
 
H

Harald van Dijk

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. :)
 
E

Eric Sosman

Cell said:
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.
 
C

Cell

Cell said:
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.


I apologize.

I will post the entire code and provide full details.

please help.
 
C

Cell

#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;

}
 
C

Cell

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.
 
S

santosh

Cell said:
#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.
 
C

Cell

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 ?
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.

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.
 
C

Cell

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.
 
S

santosh

Cell said:
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);
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.
 
S

santosh

Cell said:
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.
 
E

Eric Sosman

Cell said:
#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.
 
S

santosh

Cell said:
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.
 
S

santosh

Cell said:
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/>
 
C

CBFalconer

Cell said:
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.
 
B

Barry Schwarz

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
 
C

Cell

Cell said:
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.
 
S

santosh

Cell said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top