473,395 Members | 1,689 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

reading data from a file into a 2d array

Okay, this if my first post so go easy on me plus I've only been using
C for a couple of weeks. I'm working on a program currently that
requires me to read data from a .dat file into a 2d array and then
print out the contents of the 2d array to the screen. I wil also need
to append data to the .dat file but mostly right now I'm worrying about
getting the info into the 2d array. My .dat file looks like this

1 20000
2 30000
3 40000

etc. The first number standing for an ID and the second standing for a
weight.

#include <stdio.h>
main()
{
FILE *pRead;
int array[20][3];
pRead = fopen("test.dat", "r");

if (pRead==NULL)
printf("\nFile cannot be opened\n");

else
printf("\nContents of test.dat\n\n");
fscanf(pRead,"%s,%s", array);

while ( !feof(pRead) )
{
printf("%s%s\n", array);
fscanf(pRead, "%s,%s", array);
}

}

I know I need to use a for loop or something to that idea so that I can
read in the column and then the row. I'm really drawing a blank here on
how to get that working. Could someone point me in the right direction?
Cause right now my output is coming out like this :

11
20002000
22
30003000

etc.
Also, if I use %d instead of %s here, I get segmentation faults. Can
anyone explain why this is happening? Thanks.

Feb 23 '06 #1
29 10361
do you mind telling me why you used a multi-dimintinal array? to me it
seems also you are
using an integer array and filling it with strings?

Feb 23 '06 #2
da*********@gmail.com writes:
do you mind telling me why you used a multi-dimintinal array? to me it
seems also you are
using an integer array and filling it with strings?


Please read <http://cfaj.freeshell.org/google/>. Thanks.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 23 '06 #3
On 2006-02-23, yourmycaffiene <dd****@gmail.com> wrote:
Okay, this if my first post so go easy on me plus I've only been using
C for a couple of weeks. I'm working on a program currently that
requires me to read data from a .dat file into a 2d array and then
print out the contents of the 2d array to the screen. I wil also need
to append data to the .dat file but mostly right now I'm worrying about
getting the info into the 2d array. My .dat file looks like this

1 20000
2 30000
3 40000

etc. The first number standing for an ID and the second standing for a
weight.

#include <stdio.h>
main()
{
FILE *pRead;
int array[20][3];
pRead = fopen("test.dat", "r");

if (pRead==NULL)
printf("\nFile cannot be opened\n");

else
printf("\nContents of test.dat\n\n");
fscanf(pRead,"%s,%s", array);

while ( !feof(pRead) )
{
printf("%s%s\n", array);
fscanf(pRead, "%s,%s", array);
}

}

I know I need to use a for loop or something to that idea so that I can
read in the column and then the row. I'm really drawing a blank here on
how to get that working. Could someone point me in the right direction?
Cause right now my output is coming out like this :

11
20002000
22
30003000

etc.
Also, if I use %d instead of %s here, I get segmentation faults. Can
anyone explain why this is happening? Thanks.


Have a look at this code and work from there:

#include <stdio.h>
main()
{

unsigned long a,b;

FILE * pRead = fopen("test.dat", "r");

if (pRead==NULL)
printf("File cannot be opened\n");

else
printf("Contents of test.dat : \n");

while ( !feof(pRead) ){
fscanf(pRead,"%u %u\n", &a,&b);
printf("%u %u\n",a,b);
}

}
Some pointers to help you on the way : fcanf can do the conversions
for you : use it if you use fscanf. You were reading in strings and
then storing them in "int" storage - this is naughty and very
unclean. Try to get a handle on the types and keep them
concistent. While C can and does allow you to stick data in the wrong
"type memory" it is a very bad idea.

The storage in the array we leave as an excercise :)

--
Remove evomer to reply
Feb 23 '06 #4
yourmycaffiene wrote:
Okay, this if my first post so go easy on me plus I've only been using
C for a couple of weeks. I'm working on a program currently that
requires me to read data from a .dat file into a 2d array and then
print out the contents of the 2d array to the screen. I wil also need
to append data to the .dat file but mostly right now I'm worrying about
getting the info into the 2d array. My .dat file looks like this

1 20000
2 30000
3 40000

etc. The first number standing for an ID and the second standing for a
weight.

#include <stdio.h>
Vertical space is cheap...
main()
Better spell it out:

int main(void)
{
FILE *pRead;
int array[20][3];
Why 3 as a second dimension if you only have two columns. Avoiding
zero-based indexing in this way is a waste of memory. Imagine if the
first dimension was 200,000.
pRead = fopen("test.dat", "r");

if (pRead==NULL)
printf("\nFile cannot be opened\n");
Vertical space here hinders reading...

You also probably want to abort execution at this point. The way it
stands, you'll still try to read from the file you failed to open.
else
printf("\nContents of test.dat\n\n");
Apart from lack of vertical spacing, you should really indent properly.
E.g.:

else
printf("Blah.\n");
fscanf(pRead,"%s,%s", array);
Quite a few problems here. You're specifying `%s` which expects a
string from the file, but you tell `fscanf` to put it into a
two-dimensional array of `int`s. Apart from failing to do what you
want, along that path lies the monster of buffer overflows. You also
tell `fscanf` to expect two strings, but pass only one address of a
variable to store them in.

BTW, what was wrong with including the above line into `while` loop? As
it stands, you'd have to guarantee the file is not empty (impossible).
Also, if you can guarantee that, a `do` loop would have been clearer.
while ( !feof(pRead) )
{
printf("%s%s\n", array);
Now you're trying to print contents of an array of `int`s as a string.
Also, you're telling `printf` to expect two strings, but only pass it
one pointer (of the wrong type, as well).
fscanf(pRead, "%s,%s", array);
Same comment as for the similar line above. Plus, You should really
have swapped the above two (or dropped this one, and put the first one
like this in the loop).
}
You should close the file as well:

fclose(pFile);

C99 will let you omit final `return 0;` but it's good practice to spell
things out.

return 0;
}
This is probably what you want:

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

#define DAT_MAX_LINES 20

int main(void)
{
int array[DAT_MAX_LINES][2];
int n = 0;
int i;

FILE * pRead = fopen("test.dat", "r");

if (!pRead)
{
printf("File cannot be opened\n");
return EXIT_FAILURE;
}

printf("Contents of test.dat:\n");

while ( (n < DAT_MAX_LINES) && (!feof(pRead)) )
{
fscanf(pRead,"%d%d\n", &array[n][0], &array[n][1]);
++n;
}

if ( (!feof(pFile)) && (n == DAT_MAX_FILES) )
{
printf("Error: file to large for array.\n");
}

fclose(pFile);

for (i = 0; i < n; ++i)
{
printf("%d: %d, %d\n", i, array[i][0], array[i][1]);
}

return EXIT_SUCCESS;
}

<snip>
Also, if I use %d instead of %s here, I get segmentation faults. Can
anyone explain why this is happening? Thanks.


See comment above about matching the formats and the parameters (and
the number of the latter). Your compiler should have warned you about
these (mine did). Turn up the warining level as high as you can.

--
BR, Vladimir

Feb 23 '06 #5
On Thu, 23 Feb 2006 08:48:59 +0000, Richard G. Riley wrote:
Have a look at this code and work from there:

#include <stdio.h>
main()
{

unsigned long a,b;

FILE * pRead = fopen("test.dat", "r");

if (pRead==NULL)
printf("File cannot be opened\n");

else
printf("Contents of test.dat : \n");

while ( !feof(pRead) ){
fscanf(pRead,"%u %u\n", &a,&b);
printf("%u %u\n",a,b);
}

}


This is a dodgy pattern to recommend. You get, I think, undefined
behaviour if you test a NULL FILE * with feof (I get a core dump rather
than any flying demons -- YMMV). You definitely get UB if you test for
end-of-file before reading anything (because there may be no data to read)
and your input is very sensitive to the format used (not technically a
problem, of course, but a beginenr will be baffled by the change in
behaviour caused by switching to "%u %u" from "%u %u\n").

I think the following is more beginner-friendly:

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

int main(void)
{
unsigned long a, b;
FILE *pRead = fopen("test.dat", "r");

if (pRead == NULL)
printf("File cannot be opened\n");
else {
printf("Contents of test.dat : \n");

while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);
}
return 0;
}

--
Ben.

Feb 23 '06 #6
On Thu, 23 Feb 2006 16:36:39 +0000, Ben Bacarisse wrote:
I think the following is more beginner-friendly:

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


second include is, of course, not needed. I was panning to "exit" and
decided to "return" instead!

--
Ben.

Feb 23 '06 #7
On 2006-02-23, Ben Bacarisse <be********@bsb.me.uk> wrote:
On Thu, 23 Feb 2006 08:48:59 +0000, Richard G. Riley wrote:
Have a look at this code and work from there:

#include <stdio.h>
main()
{

unsigned long a,b;

FILE * pRead = fopen("test.dat", "r");

if (pRead==NULL)
printf("File cannot be opened\n");

else
printf("Contents of test.dat : \n");

while ( !feof(pRead) ){
fscanf(pRead,"%u %u\n", &a,&b);
printf("%u %u\n",a,b);
}

}
This is a dodgy pattern to recommend. You get, I think, undefined


Thanks. You're right : I missed the return or bracketing at null check -
but then I wasnt looking to write it for him just to indicate the type
problems he had.
behaviour if you test a NULL FILE * with feof (I get a core dump rather
than any flying demons -- YMMV). You definitely get UB if you test for
end-of-file before reading anything (because there may be no data to read)
and your input is very sensitive to the format used (not technically a
problem, of course, but a beginenr will be baffled by the change in
behaviour caused by switching to "%u %u" from "%u %u\n").

I think the following is more beginner-friendly:

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

int main(void)
{
unsigned long a, b;
FILE *pRead = fopen("test.dat", "r");

if (pRead == NULL)
printf("File cannot be opened\n");
else {
printf("Contents of test.dat : \n");

while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);
}
return 0;
}

--
Remove evomer to reply
Feb 23 '06 #8

Ben Bacarisse wrote:

<snip>
This is a dodgy pattern to recommend. You get, I think, undefined
behaviour if you test a NULL FILE * with feof (I get a core dump rather
True, as it probably internally dereferences NULL pointer.
than any flying demons -- YMMV). You definitely get UB if you test for
end-of-file before reading anything (because there may be no data to read)
This however I believe is not the case. The Standard says only this:

7.19.10.2p2
The feof function tests the end-of-file indicator for the stream
pointed to by stream.

7.19.10.2p3
The feof function returns nonzero if and only if the end-of-file
indicator is set for
stream.

I see no requirement for any data to exist in the file (think empty
files), or any data to be read beforehand (think empty files again).
and your input is very sensitive to the format used (not technically a
problem, of course, but a beginenr will be baffled by the change in
behaviour caused by switching to "%u %u" from "%u %u\n").

I think the following is more beginner-friendly:

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

int main(void)
{
unsigned long a, b;
FILE *pRead = fopen("test.dat", "r");

if (pRead == NULL)
printf("File cannot be opened\n");
else {
printf("Contents of test.dat : \n");
Here, you make the same mistake as both OP and Richard. Even if the
`fopen` fails you'll try to read from the file.

while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);
}
return 0;
}


I believe my earlier post gave better advice.

--
BR, Vladimir

Feb 23 '06 #9
"Ben Bacarisse" <be********@bsb.me.uk> wrote in message
news:pa****************************@bsb.me.uk...
I think the following is more beginner-friendly:

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

int main(void)
{
unsigned long a, b;
FILE *pRead = fopen("test.dat", "r");

if (pRead == NULL)
printf("File cannot be opened\n");
else {
printf("Contents of test.dat : \n");

while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);
You should consider closing the file here: fclose(pRead); }
return 0;
}

Feb 23 '06 #10
Ben Bacarisse <be********@bsb.me.uk> writes:
This is a dodgy pattern to recommend. You get, I think, undefined
behaviour if you test a NULL FILE * with feof (I get a core dump rather
than any flying demons -- YMMV). You definitely get UB if you test for
end-of-file before reading anything (because there may be no data to read)
Not true, as someone else pointed out elsethread. Not UB, simply useless.
I think the following is more beginner-friendly:

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

int main(void)
{
unsigned long a, b;
FILE *pRead = fopen("test.dat", "r");

if (pRead == NULL)
printf("File cannot be opened\n");
else {
printf("Contents of test.dat : \n");

while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);
}
return 0;
}


Mm. This still has the flaw that if the file can't be opened, fscanf()
will attempt to read it anyway.

Also, while the above loop does terminate once the end of the file has
been reached, it will also terminate (silently) if a line is
encountered that doesn't have the expected format, or if a read error
occurs. At the very least, it's worth noting the latter.

It'd be worthwhile to declare an int (we'll call it nread), and save
the value from fscanf() so we can distinguish the cases:

while ((nread = fscanf(pRead, "%u %u", &a, &b)) == 2)
printf("%u %u\n", a, b);
if (ferror(pRead))
fputs("An error occurred while attempting to read test.dat.\n",
stderr);
else if (!feof(pRead))
fputs("A malformatted line was encountered, or a "
"number is too large.\n", stderr);

To polish this up a bit, it would be useful to keep a line-counter so
you can inform the user which line was malformatted.

Also, the program will of course accept input in the format:

1 12389 2 12788
3
4409 4
12489 5 2933 6
9280

It might be well to explicitly enforce that there are exactly two
numbers per line, if this is the expected format.
Feb 23 '06 #11
"Micah Cowan" <mi***@cowan.name> wrote in message
news:87************@mcowan.barracudanetworks.com.. .
Mm. This still has the flaw that if the file can't be opened, fscanf()
will attempt to read it anyway.
scanf() is contained in the compound statement under "else", why will the
file be read if fopen fails?
while ((nread = fscanf(pRead, "%u %u", &a, &b)) == 2)
printf("%u %u\n", a, b);


I believe those format specifiers should be changed to "%lu" since a and b
are of type unsigned long.
Feb 24 '06 #12
On Thu, 23 Feb 2006 08:53:13 -0800, Vladimir S. Oka wrote:

Ben Bacarisse wrote:

<snip>
This is a dodgy pattern to recommend. You get, I think, undefined
behaviour if you test a NULL FILE * with feof (I get a core dump rather
True, as it probably internally dereferences NULL pointer.
than any flying demons -- YMMV). You definitely get UB if you test for
end-of-file before reading anything (because there may be no data to
read)


This however I believe is not the case. The Standard says only this:

<std file behaviour snipped> I see no requirement for any data to exist in the file (think empty
files), or any data to be read beforehand (think empty files again).


I know you can have empty data! I meant the program exhibited UB when
presented with an empty file because of what is does *after* testing for
eof. The test if fine, but it won't return true so scanf is called with
no data to read -- that was what I was trying to say with "... because
there may be no data to read". I should have been more explicit about the
UB comming from the read, not the eof test.
if (pRead == NULL)
printf("File cannot be opened\n");
else {
printf("Contents of test.dat : \n");


Here, you make the same mistake as both OP and Richard. Even if the
`fopen` fails you'll try to read from the file.


I don't think so. The fscanf is in the "else". It was the main point I
wanted to correct.
while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);
}
return 0;
}


I believe my earlier post gave better advice.


I thought that feof would not return true unless an input operation had
failed. I may not be up on the latest standard so I will await correction
here, but if I am not mistaken your suggestion involved reading when there
might be nothing to read (and hence demons etc...).

--
Ben.

Feb 24 '06 #13
On Thu, 23 Feb 2006 19:40:48 +0200, stathis gotsis wrote:
"Ben Bacarisse" <be********@bsb.me.uk> wrote in message
news:pa****************************@bsb.me.uk...
I think the following is more beginner-friendly: <snip>
while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);


You should consider closing the file here: fclose(pRead);


Absolutely, thank you. It was intened, after all, as an example for
beginners to copy so it should not be missing the fclose!
}
return 0;
}


--
Ben.

Feb 24 '06 #14
"stathis gotsis" <st***********@hotmail.com> writes:
"Micah Cowan" <mi***@cowan.name> wrote in message
news:87************@mcowan.barracudanetworks.com.. .
Mm. This still has the flaw that if the file can't be opened, fscanf()
will attempt to read it anyway.


scanf() is contained in the compound statement under "else", why will the
file be read if fopen fails?


I wish you had retained that bit of context... in any event, yes,
you're right: I misread it.
while ((nread = fscanf(pRead, "%u %u", &a, &b)) == 2)
printf("%u %u\n", a, b);


I believe those format specifiers should be changed to "%lu" since a and b
are of type unsigned long.


Absolutely right: I had missed that as well.

-Micah
Feb 24 '06 #15
On Thu, 23 Feb 2006 22:28:35 +0000, Micah Cowan wrote:
Ben Bacarisse <be********@bsb.me.uk> writes:
This is a dodgy pattern to recommend. You get, I think, undefined
behaviour if you test a NULL FILE * with feof (I get a core dump rather
than any flying demons -- YMMV). You definitely get UB if you test for
end-of-file before reading anything (because there may be no data to
read)


Not true, as someone else pointed out elsethread. Not UB, simply useless.


I am claiming that the original program exhibits UB because it tests eof
before the input operations. The UB is from doing fscanf on an empty file
or one which may not contain two numbers and then using the uninitialised
variable(s). I may not have been clear but I don't think I was wrong.

<snip>
FILE *pRead = fopen("test.dat", "r");

if (pRead == NULL)
printf("File cannot be opened\n");
else {
printf("Contents of test.dat : \n");

while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);
}
return 0;
}


Mm. This still has the flaw that if the file can't be opened, fscanf()
will attempt to read it anyway.


<pantomime shouting>It's in the "else" part!</panto>

Excellent suggestions for enhancement snipped.

--
Ben.

Feb 24 '06 #16
In article <pa****************************@bsb.me.uk>
Ben Bacarisse <be********@bsb.me.uk> wrote:
I thought that feof would not return true unless an input operation had
failed.


This is correct. Not only must an input operation have failed,
it must have failed due to EOF. If it fails due to file-error
(corrupted file, unreadable CD-ROM, etc), you will get repeated
"EOF" indications from read operations, but feof(fp) will remain
false.

More commonly, bad input in a file will cause the scanf() engine
to jam up. Here, a loop that fails to test the fscanf() return
value will run forever:

some_loop_construct_here {
fscanf(fp, "%u%u", &a, &b);
/* fscanf() returns 0 because input stream contains, e.g., "fish" */

use(a, b);
/* use() gets previous values of a and b (or junk if there
are no previous values */
}

In any case, *any* time you see a "while" or "for" loop whose test
condition uses "feof", be suspicious. The loop is probably broken.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Feb 24 '06 #17
In article <87************@mcowan.barracudanetworks.com>
Micah Cowan <mi***@cowan.name> wrote:
It'd be worthwhile to declare an int (we'll call it nread), and save
the value from fscanf() so we can distinguish the cases:

while ((nread = fscanf(pRead, "%u %u", &a, &b)) == 2)
printf("%u %u\n", a, b);
if (ferror(pRead))
fputs("An error occurred while attempting to read test.dat.\n",
stderr);
else if (!feof(pRead))
fputs("A malformatted line was encountered, or a "
"number is too large.\n", stderr);
This code fragment does not use "nread" after exiting the loop.
To polish this up a bit, it would be useful to keep a line-counter so
you can inform the user which line was malformatted.


This is a good idea; however, doing so requires discarding the
scanf system, as "%u" includes an implicit "skip whitespace"
directive, and "whitespace" includes newlines. No amount of fiddling
with the scan format can repair this problem. The *only* solution
is to read input with something other than scanf (or, overly
complicated, scanf combined with something other than scanf, or
scanf with "%c" to read one character at a time, but these are just
silly ways of proving you can cut cheese with a "knife" made of
tofu).
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Feb 24 '06 #18
On 22 Feb 2006 19:52:36 -0800, "yourmycaffiene" <dd****@gmail.com>
wrote:
Okay, this if my first post so go easy on me plus I've only been using
C for a couple of weeks. I'm working on a program currently that
requires me to read data from a .dat file into a 2d array and then
print out the contents of the 2d array to the screen. I wil also need
to append data to the .dat file but mostly right now I'm worrying about
getting the info into the 2d array. My .dat file looks like this

1 20000
2 30000
3 40000

etc. The first number standing for an ID and the second standing for a
weight.

#include <stdio.h>
main()
{
FILE *pRead;
int array[20][3];
Why do you think the second dimension should be 3? There are only two
elements per line.
pRead = fopen("test.dat", "r");

if (pRead==NULL)
printf("\nFile cannot be opened\n");

else
printf("\nContents of test.dat\n\n");
fscanf(pRead,"%s,%s", array);
Multiple undefined behavior.

You have two format specifications. Each requires an
argument. You only have one argument.

%s requires a pointer to char. You provided an array name
which evaluates to a pointer to int.

Your format string says the values are separated by a comma.
There was no comma in your sample.

Since you want to read up to 20 pairs of ints, one method would be a
loop that repeatedly executes a statement like
fscanf(pread,"%d %d", &array[i][0], &array[i][1]);

while ( !feof(pRead) )
Read the faq for why this doesn't do what you want.
{
printf("%s%s\n", array);
fscanf(pRead, "%s,%s", array);
Why are you attempting to read more data when you have already
detected eof above?
}

}

I know I need to use a for loop or something to that idea so that I can
read in the column and then the row. I'm really drawing a blank here on
how to get that working. Could someone point me in the right direction?
Cause right now my output is coming out like this :
After undefined behavior, any output is possible.

11
20002000
22
30003000

etc.
Also, if I use %d instead of %s here, I get segmentation faults. Can
anyone explain why this is happening? Thanks.


Actually, segmentation faults are one of the more desirable forms of
undefined behavior. It eliminates any possible illusion that the code
is working properly.
Remove del for email
Feb 24 '06 #19
Chris Torek <no****@torek.net> writes:
[...]
but these are just
silly ways of proving you can cut cheese with a "knife" made of
tofu).


If you melt the cheese and dip the knife in liquid nitrogen.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Feb 24 '06 #20
Ben Bacarisse wrote:
On Thu, 23 Feb 2006 08:53:13 -0800, Vladimir S. Oka wrote:

Ben Bacarisse wrote:

<snip>
This is a dodgy pattern to recommend. You get, I think, undefined
behaviour if you test a NULL FILE * with feof (I get a core dump
rather


True, as it probably internally dereferences NULL pointer.
than any flying demons -- YMMV). You definitely get UB if you test
for end-of-file before reading anything (because there may be no
data to read)


This however I believe is not the case. The Standard says only this:

<std file behaviour snipped>
I see no requirement for any data to exist in the file (think empty
files), or any data to be read beforehand (think empty files again).


I know you can have empty data! I meant the program exhibited UB when
presented with an empty file because of what is does *after* testing
for
eof. The test if fine, but it won't return true so scanf is called
with no data to read -- that was what I was trying to say with "...
because
there may be no data to read". I should have been more explicit about
the UB comming from the read, not the eof test.
if (pRead == NULL)
printf("File cannot be opened\n");
else {
printf("Contents of test.dat : \n");


Here, you make the same mistake as both OP and Richard. Even if the
`fopen` fails you'll try to read from the file.


I don't think so. The fscanf is in the "else". It was the main point
I wanted to correct.


Sorry, I failed to notice a trailing `{` in the `else` part, and didn't
count the bottom ones. I saw just a `;` after `printf` and mentally
terminated the `else`. Comes from being used to a different coding
style that mandates curly braces on their own lines.
while (fscanf(pRead,"%u %u", &a,&b) == 2)
printf("%u %u\n", a, b);
}
return 0;
}


I believe my earlier post gave better advice.


I thought that feof would not return true unless an input operation
had
failed. I may not be up on the latest standard so I will await
correction here, but if I am not mistaken your suggestion involved
reading when there might be nothing to read (and hence demons etc...).


As a I looked it up in the Standard, the `feof` does not require any
data to be read before testing for EOF condition. Looking elsethread, I
see that I have failed to test success of `fscanf`, and relied only on
`feof` for looping, but that's a different issue, I think.

--
BR, Vladimir

Hatred, n.:
A sentiment appropriate to the occasion of another's
superiority.
-- Ambrose Bierce, "The Devil's Dictionary"

Feb 24 '06 #21
On Fri, 24 Feb 2006 06:50:28 +0000, Vladimir S. Oka wrote:
I thought that feof would not return true unless an input operation had
failed. I may not be up on the latest standard so I will await
correction here, but if I am not mistaken your suggestion involved
reading when there might be nothing to read (and hence demons etc...).


As a I looked it up in the Standard, the `feof` does not require any data
to be read before testing for EOF condition. Looking elsethread, I see
that I have failed to test success of `fscanf`, and relied only on `feof`
for looping, but that's a different issue, I think.


It is possible we are having an agreement! feof does not need any data to
be read before testing, but it can never be true unless data has been read
(read standard entry for fopen) so loop that use it are, at best,
suspicious. All I was saying is that your loop used fscanf (again
well-defined when there is no data) to read into *uninitialied variables*
when there was no data, hence was not a good candidate to show a beginner.

The UB is from your whole loop failing to do something defined when there
is no data. The OP's loop had the same UB and I was critised twice for
pointing it out!

--
Ben.

Feb 24 '06 #22
On Fri, 24 Feb 2006 03:56:16 +0000, Chris Torek wrote:
In article <pa****************************@bsb.me.uk> Ben Bacarisse
<be********@bsb.me.uk> wrote:
I thought that feof would not return true unless an input operation had
failed.


This is correct. Not only must an input operation have failed, it must
have failed due to EOF. If it fails due to file-error (corrupted file,
unreadable CD-ROM, etc), you will get repeated "EOF" indications from read
operations, but feof(fp) will remain false.


Thank you.

I was so puzzled by two people saying I was wrong that I downloaded a
recent draft standard to see if this behaviour was now in doubt -- and, of
course, I find that it not. I can see that I will have alter my writing
style: "I thought that..." should have been "I am certain that..."!

--
Ben.

Feb 24 '06 #23

Ben Bacarisse wrote:
On Fri, 24 Feb 2006 06:50:28 +0000, Vladimir S. Oka wrote:
I thought that feof would not return true unless an input operation had
failed. I may not be up on the latest standard so I will await
correction here, but if I am not mistaken your suggestion involved
reading when there might be nothing to read (and hence demons etc...).


As a I looked it up in the Standard, the `feof` does not require any data
to be read before testing for EOF condition. Looking elsethread, I see
that I have failed to test success of `fscanf`, and relied only on `feof`
for looping, but that's a different issue, I think.


It is possible we are having an agreement!


I'll drink to that! ;-)

--
BR, Vladimir

Feb 24 '06 #24
Chris Torek <no****@torek.net> writes:
In article <87************@mcowan.barracudanetworks.com>
Micah Cowan <mi***@cowan.name> wrote:
It'd be worthwhile to declare an int (we'll call it nread), and save
the value from fscanf() so we can distinguish the cases:

while ((nread = fscanf(pRead, "%u %u", &a, &b)) == 2)
printf("%u %u\n", a, b);
if (ferror(pRead))
fputs("An error occurred while attempting to read test.dat.\n",
stderr);
else if (!feof(pRead))
fputs("A malformatted line was encountered, or a "
"number is too large.\n", stderr);


This code fragment does not use "nread" after exiting the loop.


Um, quite. Guess I though I was gonna need it... and then didn't.
To polish this up a bit, it would be useful to keep a line-counter so
you can inform the user which line was malformatted.


This is a good idea; however, doing so requires discarding the
scanf system, as "%u" includes an implicit "skip whitespace"
directive, and "whitespace" includes newlines.No amount of fiddling
with the scan format can repair this problem. The *only* solution
is to read input with something other than scanf (or, overly
complicated, scanf combined with something other than scanf, or
scanf with "%c" to read one character at a time, but these are just
silly ways of proving you can cut cheese with a "knife" made of
tofu).


Yup. I knew this, but probably should've mentioned it at that
point. Thanks for elaborating.
Feb 24 '06 #25

"Keith Thompson" <ks***@mib.org> wrote in message
news:ln************@nuthaus.mib.org...
Chris Torek <no****@torek.net> writes:
[...]
but these are just
silly ways of proving you can cut cheese with a "knife" made of
tofu).


If you melt the cheese and dip the knife in liquid nitrogen


, the cold knife will shatter when it hits the hot cheese.

Rod Pemberton
Feb 24 '06 #26
On Fri, 24 Feb 2006 13:11:59 +0000, Ben Bacarisse
<be********@bsb.me.uk> wrote:
It is possible we are having an agreement! feof does not need any data to
be read before testing, but it can never be true unless data has been read
(read standard entry for fopen) so loop that use it are, at best,
suspicious. <snip>


To be precise, feof (and ferror for input) can only be true after an
_attempt_ has been made to read data, but that could be without
actually succeeding in reading anything.

And while I'm at it, to be really picky, test-at-top (while) loops
using feof are suspicious. Test-at-bottom (do-while) can be correct
though rarely useful since you usually need N-and-a-half or at least
N-and-a-fraction-that-fits-in-the-while-test.

- David.Thompson1 at worldnet.att.net
Mar 6 '06 #27
Dave Thompson <da*************@worldnet.att.net> writes:
And while I'm at it, to be really picky, test-at-top (while) loops
using feof are suspicious. Test-at-bottom (do-while) can be correct
though rarely useful since you usually need N-and-a-half or at least
N-and-a-fraction-that-fits-in-the-while-test.


In my experience, feof() should only be tested after a read has
failed, so that you can tell whether it failed due to a read
error or end-of-file. ferror() serves a similar purpose.
--
"Some programming practices beg for errors;
this one is like calling an 800 number
and having errors delivered to your door."
--Steve McConnell
Mar 6 '06 #28
Ben Pfaff wrote:
In my experience, feof() should only be tested after a read has
failed, so that you can tell whether it failed due to a read
error or end-of-file.


Dan Pop liked to use an feof test after this kind of a scanf call.
He said it had something to do with "sticky EOF".

rc = scanf("%" xstr(LENGTH) "[^\n]%*[^\n]", array);
if (!feof(stdin)) {
getchar();
}

--
pete
Mar 6 '06 #29
pete <pf*****@mindspring.com> writes:
Ben Pfaff wrote:
In my experience, feof() should only be tested after a read has
failed, so that you can tell whether it failed due to a read
error or end-of-file.


Dan Pop liked to use an feof test after this kind of a scanf call.
He said it had something to do with "sticky EOF".


I won't claim to fathom the full meaning of scanf(), or Dan Pop.
--
"...Almost makes you wonder why Heisenberg didn't include postinc/dec operators
in the uncertainty principle. Which of course makes the above equivalent to
Schrodinger's pointer..."
--Anthony McDonald
Mar 6 '06 #30

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Foxy Kav | last post by:
Hi, another question from me again, i was just wondering if anyone could give me a quick example of reading data from a file then placing the data into an array for some manipulation then reading...
2
by: Jeevan | last post by:
Hi, I have an array of data (which I am getting from a socket connection). I am working on a program which acts on this data but the program is written to work on data from a file (not from an...
3
by: Nick | last post by:
I have found a class that compresses and uncompresses data but need some help with how to use part of it below is the deflate method which compresses the string that I pass in, this works OK. At...
7
by: John Dann | last post by:
I'm trying to read some binary data from a file created by another program. I know the binary file format but can't change or control the format. The binary data is organised such that it should...
10
by: nuke1872 | last post by:
Hello guys, I have a file names network.txt which contains a matrix. I want to read this matrix as store it as an array. I am new to stuff like these...can anybody help me out !! Thanks nuke
6
by: arne.muller | last post by:
Hello, I've come across some problems reading strucutres from binary files. Basically I've some strutures typedef struct { int i; double x; int n; double *mz;
7
by: ianenis.tiryaki | last post by:
well i got this assignment which i dont even have a clue what i am supposed to do. it is about reading me data from the file and load them into a parallel array here is the question: Step (1) ...
21
by: Stephen.Schoenberger | last post by:
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...
3
by: jordanbondo | last post by:
I have no clue why this isn't working. The top part that reads into size, shortTime, longTime, and threshold work fine. Down below where I try to do the exact same thing and read into x, i get...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.