Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > array of structures.

Reply
Thread Tools

array of structures.

 
 
santosh
Guest
Posts: n/a
 
      03-09-2008
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.

 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      03-09-2008
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[i].v.x), &(obj->vert[i].v.y),
>> &(obj->vert[i].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[i].v.x, obj->vert[i].v.y, obj-
>> vert[i].v.z);

> }
>
> for(i=0;i<obj->ntri;i++)
> {
> fscanf(fp, "%d %d %d",&(obj->tri[i].v0), &(obj->tri[i].v1), &(obj-
>> tri[i].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[i].v0, obj->tri[i].v1, obj->tri[i].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
http://www.velocityreviews.com/forums/(E-Mail Removed)lid
 
Reply With Quote
 
 
 
 
santosh
Guest
Posts: n/a
 
      03-09-2008
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[i]).v.x),
&((obj.vert[i]).v.y), &((obj.vert[i]).v.z)) != 3) {
fprintf(stderr, fscfail_msg, __LINE__);
rc = 0;
break;
}
printf("%f %f %f\n", (obj.vert[i]).v.x, (obj.vert[i]).v.y,
(obj.vert[i]).v.z);
}

for (i = 0; i < obj.ntri; i++) {
if (fscanf(fp, "%d %d %d", &((obj.tri[i]).v0),
&((obj.tri[i]).v1),
&((obj.tri[i]).v2)) != 3) {
fprintf(stderr, fscfail_msg, __LINE__);
rc = 0;
break;
}
printf("%d %d %d\n", (obj.tri[i]).v0, (obj.tri[i]).v1,
(obj.tri[i]).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.

 
Reply With Quote
 
santosh
Guest
Posts: n/a
 
      03-09-2008
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/>

 
Reply With Quote
 
CBFalconer
Guest
Posts: n/a
 
      03-10-2008
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

 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      03-11-2008
On Sun, 9 Mar 2008 08:51:03 -0700 (PDT), Cell <(E-Mail Removed)>
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
 
Reply With Quote
 
Cell
Guest
Posts: n/a
 
      03-11-2008
On Mar 9, 9:47 pm, santosh <(E-Mail Removed)> 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[i]).v.x),
> &((obj.vert[i]).v.y), &((obj.vert[i]).v.z)) != 3) {
> fprintf(stderr, fscfail_msg, __LINE__);
> rc = 0;
> break;
> }
> printf("%f %f %f\n", (obj.vert[i]).v.x, (obj.vert[i]).v.y,
> (obj.vert[i]).v.z);
> }
>
> for (i = 0; i < obj.ntri; i++) {
> if (fscanf(fp, "%d %d %d", &((obj.tri[i]).v0),
> &((obj.tri[i]).v1),
> &((obj.tri[i]).v2)) != 3) {
> fprintf(stderr, fscfail_msg, __LINE__);
> rc = 0;
> break;
> }
> printf("%d %d %d\n", (obj.tri[i]).v0, (obj.tri[i]).v1,
> (obj.tri[i]).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.
 
Reply With Quote
 
santosh
Guest
Posts: n/a
 
      03-11-2008
Cell wrote:

> On Mar 9, 9:47 pm, santosh <(E-Mail Removed)> 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.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
const and array of array (of array ...) Mara Guida C Programming 3 09-03-2009 07:54 AM
length of an array in a struct in an array of structs in a struct in an array of structs Tuan Bui Perl Misc 14 07-29-2005 02:39 PM
Length of Array of Array of Array Tom Perl Misc 3 12-20-2004 05:23 PM
How to combine 2 int Array into ONE int Array ? S300 Java 4 08-19-2003 07:04 PM
hashed array in array need the keys... and length Daniel Perl 1 08-14-2003 06:49 PM



Advertisments