C File I/O... working with array structures

P

padh.ayo

Hi, I have a array structure called people

It is properly initialized to 100 array structure elements. Now, I'm
reading in from the command line a txt file, and I get them to open
correctly. In this .txt file, there is a name and a weight.

Josh 123.32
Jim 212.123
Steph 213.2

.... etc.

Now, I have this code:

FILE *ptr, *ptr1;
ptr = fopen(argv[1], "r"); //argv[1] is the txt file with al the
people/weight

while( (fscanf(ptr, "%s %f", people.name, &people.weight)) == 1
)
{
printf("%s %f", people.name, people.weight);
i += 1;
}


Why doesn't this work? Nothing gets printed out.
 
R

Richard Heathfield

(e-mail address removed) said:

FILE *ptr, *ptr1;
ptr = fopen(argv[1], "r"); //argv[1] is the txt file with al the
people/weight

It's no big deal on this occasion, but in general it is wise to avoid //
comments in Usenet articles - they tend to wrap, making it difficult for
others to compile your code. Furthermore, they provoke diagnostic messages
from C90-conforming implementations.
while( (fscanf(ptr, "%s %f", people.name, &people.weight)) == 1
)


Two problems here. Firstly, you said you have 100 elements in your struct
array. What happens if i ever becomes 100?

The second problem is that you're asking fscanf to convert TWO input fields,
not one, so you should be comparing its return value against 2, not 1. And
that's why you're not getting any output - the loop is failing on the first
fscanf call. Do this instead:

while(i < 100 &&
fscanf(ptr,
"%s %f",
people.name,
&people.weight) == 2)
 
K

Keith Thompson

Hi, I have a array structure called people

What is an "array structure"? I think you mean an array of structures
(i.e., an array whose elements are structures), but you should say so.
It is properly initialized to 100 array structure elements. Now, I'm
reading in from the command line a txt file, and I get them to open
correctly. In this .txt file, there is a name and a weight.

Josh 123.32
Jim 212.123
Steph 213.2

... etc.

Now, I have this code:

FILE *ptr, *ptr1;

You don't use ptr1.
ptr = fopen(argv[1], "r"); //argv[1] is the txt file with al the
people/weight

fopen() can fail. You don't check the result.
while( (fscanf(ptr, "%s %f", people.name, &people.weight)) == 1
)


fscanf() returns the number of input items assigned, or EOF (a
negative value) if a failure occurs before any conversion. If this
call successfully reads the name and the weight, it will return 2, and
your while loop will never execute.
{
printf("%s %f", people.name, people.weight);
i += 1;


There's nothing wrong with "i += 1;", but "i++;" is more idiomatic.
}


Why doesn't this work? Nothing gets printed out.

See above.

Also, fscanf() doesn't deal well with input errors. It isn't
line-oriented; it skips whitespace (in most cases) before reading an
item, and that can include one or more newlines. The "%s" format is
dangerous; it reads a single whitespace-delimited string (e.g., given
"John Smith" it will only read the "John"), but it specifies no limit
on the size of the string. If you've allocated 20 characters for
people.name, but the input string is 25 characters, you'll clobber
adjacent memory, with arbitrarily bad results.

Is the "name" member a character array or a pointer? If it's a
pointer, you need to allocate memory for it explicitly before you read
a value into it. Either way, you can and should tell fscanf not to
read more characters than it can hold (see the documentation for the
syntax).

Another option is to read a line at a time using fgets() and then use
sscanf() to parse it. fgets() has some problems with long lines;
there are a number of workarounds if that's an issue. (See
CBFalconer's ggets(), for example.)
 
P

padh.ayo

Hi, I've sent you an e-mail of my code and supporting information.
Thanks :)

(e-mail address removed) said:

<snip>


FILE *ptr, *ptr1;
ptr = fopen(argv[1], "r"); //argv[1] is the txt file with al the
people/weightIt's no big deal on this occasion, but in general it is wise to avoid //
comments in Usenet articles - they tend to wrap, making it difficult for
others to compile your code. Furthermore, they provoke diagnostic messages
from C90-conforming implementations.


while( (fscanf(ptr, "%s %f", people.name, &people.weight)) == 1
)Two problems here. Firstly, you said you have 100 elements in your struct

array. What happens if i ever becomes 100?

The second problem is that you're asking fscanf to convert TWO input fields,
not one, so you should be comparing its return value against 2, not 1. And
that's why you're not getting any output - the loop is failing on the first
fscanf call. Do this instead:

while(i < 100 &&
fscanf(ptr,
"%s %f",
people.name,
&people.weight) == 2)
 
S

santosh

(e-mail address removed) wrote:
Please don't top-post. Also don't quote the sigs unless your commenting
on them.
(e-mail address removed) said:

<snip>


FILE *ptr, *ptr1;
ptr = fopen(argv[1], "r"); //argv[1] is the txt file with al the
people/weightIt's no big deal on this occasion, but in general it is wise to avoid //
comments in Usenet articles - they tend to wrap, making it difficult for
others to compile your code. Furthermore, they provoke diagnostic messages
from C90-conforming implementations.
Hi, I've sent you an e-mail of my code and supporting information.
Thanks :)

Why? What's wrong with posting to the group and letting others give
their opinions?
 
J

jaysome

(e-mail address removed) said:

FILE *ptr, *ptr1;
ptr = fopen(argv[1], "r"); //argv[1] is the txt file with al the
people/weight

It's no big deal on this occasion, but in general it is wise to avoid //
comments in Usenet articles - they tend to wrap, making it difficult for
others to compile your code. Furthermore, they provoke diagnostic messages
from C90-conforming implementations.

It's trivial to handle this: if your C90-conforming implementation
does not support // comments, just upgrade to their C99-conforming
implementation :^)
 
R

Richard Heathfield

jaysome said:

It's trivial to handle this: if your C90-conforming implementation
does not support // comments, just upgrade to their C99-conforming
implementation :^)

My C90-conforming implementation has no C99-conforming equivalent.
 
K

Keith Thompson

Richard Heathfield said:
jaysome said:



My C90-conforming implementation has no C99-conforming equivalent.

And even if it did, it wouldn't handle // comments that had been
broken by line-wrapping.
 
R

Richard Heathfield

(e-mail address removed) said:
Hi, I've sent you an e-mail of my code and supporting information.

Presumably, then, you have a follow-up question, but it's not easy to see
what that is. Here are the results of my compilation:

bio1.c: In function `main':
bio1.c:53: warning: double format, different type arg (arg 2)
bio1.c:14: warning: unused parameter `argc'
bio1.c:56: warning: control reaches end of non-void function

The principal line it is complaining about is this:

printf("%f %s\n", acids.count, acids.name);

where you try to print an int value as if it were a double. The format
specifier for double is %f, but acids.count has type int. What is the
correct printf format specifier for int? (Use one side of the paper only. 3
marks. The use of calculators is not permitted.)

The other problems it is complaining about are these: you define, but don't
use, a parameter called argc. The solution is to use it, and there's an
excellent reason why you should: if argc is 2 or less, then your second
fopen call will fail. If it's 1 or less, your first fopen call will fail.
So it's a good idea to check argc before dooming your program to disaster.

Also, note that you have - perfectly correctly - defined main to return int,
as is right and proper and well-defined (unlike any other return type for
main). When we say a function returns a value of a given type, it's good to
return a value of that type from that function. So, just after your final
printf("\n"); but before your closing brace, why not add this line?

return 0;

to indicate (perhaps a trifle optimistically) that your program succeeded in
executing correctly and producing the desired results?

Once you have made these corrections, however, you will notice that your
program continues to produce incorrect results. Just because a program
compiles cleanly (at a decent warning level), that doesn't mean it's
correct! The most obvious problem is that you carefully count (using the
object known as i) how much data you read in - how many records, how many
lines, whatever you want to call it - but then you discard that
information, re-using i as a counter in the next loop. So your program
forgets how many of the 100 available array elements it actually used, and
instead tries to print all 100, most of which are likely to contain
indeterminate values.

After modifying your program to store that value (the number of lines read)
instead of discarding it, and using it in the conditional expression of
subsequent loops, I was able to run your program with what look like
correct results. I suggest, therefore, that you do the same.

One last thing: in future, if you wish to use me as a private consultant, it
might be wiser to find out my fee scale in advance.
 
C

CBFalconer

Richard said:
(e-mail address removed) said:

.... snip ...

One last thing: in future, if you wish to use me as a private
consultant, it might be wiser to find out my fee scale in advance.

At a guess, you spent less than a half day on it, so a minimum
charge (for such a half day) would be reasonable. Padh.ayo should
probably forward you about 400 pounds Sterling. I suggest he use
Paypal.
 
C

CBFalconer

jaysome said:
Richard Heathfield said:
(e-mail address removed) said:

FILE *ptr, *ptr1;
ptr = fopen(argv[1], "r"); //argv[1] is the txt file with al the
people/weight

It's no big deal on this occasion, but in general it is wise to
avoid // comments in Usenet articles - they tend to wrap, making
it difficult for others to compile your code. Furthermore, they
provoke diagnostic messages from C90-conforming implementations.

It's trivial to handle this: if your C90-conforming implementation
does not support // comments, just upgrade to their C99-conforming
implementation :^)

How did you manage to compile "people/weight"? They seem to be
undefined. I am omitting any discussion as to the availability of
that C99-conforming implementation.
 

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,802
Messages
2,569,661
Members
45,429
Latest member
FayeWagsta

Latest Threads

Top