473,779 Members | 2,023 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Missing Lines With fscanf()

Hello, trying to get back into c and was having issue with reading a
simple text file with an aribtrary # of lines with 3 int's per line,
with the eventual purpose of putting each int into an element of an
array (eventually will be other things, but I'm sticking to int's for
now). I.e.:
0 1 1
1 1 1
2 1 1 etc...

The problem is it'll read and print all but the last line. Is there
something I'm forgetting about an End Of Line or EOF with fscanf? If
it means anything, I'm using gcc on win32 (djgpp) and haven't been
able to compile it under Linux yet (if there's much difference.) Here
is the minimalist version of the code with all the fault protection
and good stuff taken out for brevity:

#include <stdio.h>

int main() {
char buff[BUFSIZ];
FILE *infile;
int nums[10];

infile = fopen("a.dat", "r");
fscanf(infile, "%d %d %d\n", &nums[0],&nums[1], &nums[2]);
while (!feof(infile)) {
/*future home of parsing junk*/
printf("%d %d %d\n", nums[0], nums[1], nums[2]);
fscanf(infile, "%d %d %d\n", &nums[0], &nums[1], &nums[2]);
}
fclose(infile);

return 0;
}

Much appreciation in advance.
Nov 14 '05 #1
4 3060
Psibur wrote:
Hello, trying to get back into c and was having issue with reading a
simple text file with an aribtrary # of lines with 3 int's per line,
with the eventual purpose of putting each int into an element of an
array [...]
The problem is it'll read and print all but the last line. Is there
something I'm forgetting about an End Of Line or EOF with fscanf? If
it means anything, I'm using gcc on win32 (djgpp) and haven't been
able to compile it under Linux yet (if there's much difference.) Here
is the minimalist version of the code with all the fault protection
and good stuff taken out for brevity:

#include <stdio.h>

int main() {
char buff[BUFSIZ];
FILE *infile;
int nums[10];

infile = fopen("a.dat", "r");
fscanf(infile, "%d %d %d\n", &nums[0],&nums[1], &nums[2]);
while (!feof(infile)) {
/*future home of parsing junk*/
printf("%d %d %d\n", nums[0], nums[1], nums[2]);
fscanf(infile, "%d %d %d\n", &nums[0], &nums[1], &nums[2]);
}
fclose(infile);

return 0;
}


The two problems I can see are addressed in Questions 12.17
and 12.2 of the comp.lang.c Frequently Asked Questions (FAQ) list:

http://www.eskimo.com/~scs/C-faq/top.html

(To understand what role 12.2 plays here, I think you'd do better
to study 12.17 first.)

--
Er*********@sun .com

Nov 14 '05 #2
Psibur wrote:

Hello, trying to get back into c and was having issue with reading a
simple text file with an aribtrary # of lines with 3 int's per line,
with the eventual purpose of putting each int into an element of an
array (eventually will be other things, but I'm sticking to int's for
now). I.e.:
0 1 1
1 1 1
2 1 1 etc...

The problem is it'll read and print all but the last line. Is there
something I'm forgetting about an End Of Line or EOF with fscanf? If
it means anything, I'm using gcc on win32 (djgpp) and haven't been
able to compile it under Linux yet (if there's much difference.) Here
is the minimalist version of the code with all the fault protection
and good stuff taken out for brevity:

#include <stdio.h>

int main() {
char buff[BUFSIZ];
FILE *infile;
int nums[10];

infile = fopen("a.dat", "r");
fscanf(infile, "%d %d %d\n", &nums[0],&nums[1], &nums[2]);
while (!feof(infile)) {
/*future home of parsing junk*/
printf("%d %d %d\n", nums[0], nums[1], nums[2]);
fscanf(infile, "%d %d %d\n", &nums[0], &nums[1], &nums[2]);
}
fclose(infile);

return 0;
}


Try (untested):

#include <stdio.h>

int main(void)
{
FILE *infile;
int nums[10];

if (infile = fopen("a.dat", "r")) {
while (3 == fscanf(infile, "%d %d %d\n",
&nums[0], &nums[1], &nums[2])) {
/*future home of parsing junk*/
printf("%d %d %d\n", nums[0], nums[1], nums[2]);
}
fclose(infile);
}
return 0;
}

NEVER fail to test the result of an input operation. USUALLY test
the result of any system call.

--
"The most amazing achievement of the computer software industry
is its continuing cancellation of the steady and staggering
gains made by the computer hardware industry..." - Petroski
Nov 14 '05 #3
On Fri, 4 Jun 2004, Psibur wrote:
Hello, trying to get back into c and was having issue with reading a
simple text file with an aribtrary # of lines with 3 int's per line,
with the eventual purpose of putting each int into an element of an
array (eventually will be other things, but I'm sticking to int's for
now). I.e.:
0 1 1
1 1 1
2 1 1 etc...

The problem is it'll read and print all but the last line. Is there
something I'm forgetting about an End Of Line or EOF with fscanf? If
it means anything, I'm using gcc on win32 (djgpp) and haven't been
able to compile it under Linux yet (if there's much difference.) Here
is the minimalist version of the code with all the fault protection
and good stuff taken out for brevity:

#include <stdio.h>

int main() {
char buff[BUFSIZ];
FILE *infile;
int nums[10];

infile = fopen("a.dat", "r");
fscanf(infile, "%d %d %d\n", &nums[0],&nums[1], &nums[2]);
while (!feof(infile)) {
/*future home of parsing junk*/
printf("%d %d %d\n", nums[0], nums[1], nums[2]);
fscanf(infile, "%d %d %d\n", &nums[0], &nums[1], &nums[2]);
}
fclose(infile);

return 0;
}


The fscanf in the while loop triggers EOF on reading the last line. After
the last fscanf it goes to the top of the loop, the exit condition is met
and you leave the loop before printing the last lines.

I usually use fgets to read a line then parse it. Another option is to get
the result from fscanf and see how many directives were successful, e.g.

result = fscanf(infile, "%d %d %d\n", &num[0], &num[1], &num[2]);

then exit if result != 3. I'd actually use the fscanf in the while
expression rather than having two calls, e.g.

while(fscanf(in file, "%d %d %d\n", &num[0], &num[1], &num[2]) == 3) {
printf("%d %d %d\n", nums[0], nums[1], nums[2]);
}

This will work even if the last line does not contain a newline character.
It will not print out a line that only has 1 or 2 numbers on it. Something
like:

1 0 1
1 2 1
1 3
1 2 0

will quit after the second line is read.

--
Send e-mail to: darrell at cs dot toronto dot edu
Don't send e-mail to vi************@ whitehouse.gov
Nov 14 '05 #4
In article <news:Pi******* *************** ********@drj.pf >
Darrell Grainger <da*****@NOMORE SPAMcs.utoronto .ca.com> writes:
I usually use fgets to read a line then parse it.
(I think this is usually the best approach.)
Another option is to get the result from fscanf and see how many
directives were successful ...
This has some pitfalls, including one you ran into here:
rather than having two calls, e.g.
while(fscanf(in file, "%d %d %d\n", &num[0], &num[1], &num[2]) == 3) {
printf("%d %d %d\n", nums[0], nums[1], nums[2]);
}
This will work even if the last line does not contain a newline character.
True (assuming the implementation supports such lines in the first
place), but this:
It will not print out a line that only has 1 or 2 numbers on it. Something
like:

1 0 1
1 2 1
1 3
1 2 0

will quit after the second line is read.


is not the case.

The problem lies in the scanf engine's interpretation of "white
space", which disagrees with what most programmers believe is the
"most reasonable" interpretation.

The directive sequence "%d %d %d\n" does *not* mean "three
integers separated by blanks and terminated by a newline." The
final "\n", for instance, means "as much blank space as possible,
including any arbitrary number of newlines, and including no newlines."

The blanks separating the "%d"s *also* mean "as much blank space
as possible, including any arbitrary number of newlines, and including
no newlines."

That means that the third input line -- "1 3\n" -- will be treated
as the number 1 (first "%d"), one blank (first " "), the number 3
(second "%d"), one newline (second " ")... and then the fourth input
line's "1" will be read and converted to satisfy the third "%d". The
newline in the scanf directive will then match the blank after the
1, leaving "2 0\n" in the input stream.

One might attempt to fix this by rewriting the call as:

while (fscanf(infile, "%d%d%d\n", ...) ...)

so that there is no " " directive to match the newline after the
two integers on the third input line ("1 3\n"). But this is no
help, because %d directives include an implied whitespace directive
first. "%d%d%d\n" means exactly the same thing to scanf as
"%d %d %d\n", or even " %d%d \v %d \t\f\r\n"! *All* whitespace
in format directives is equivalent, and any whitespace is equivalent
to an arbitrarily long string of whitespace. Most scanf directives
-- the exceptions are %c and %[ -- have an "implied blank" in front
of them. A final "\n" in a scanf directive means the same thing as
a trailing blank, or "\t", or "\f".

What this all boils down to is that *only* the %c and %[ directives
give you control over "lines". *All* other scanf conversions will
behave poorly in any kind of file-parsing or interactive application.
In other words, these are the only *useful* directives -- unless
you first read in a line, then use sscanf() to pick it apart. (By
using sscanf(), you avoid the problem, because you have a tightly
controlled string in memory, rather than an uncontrolled input
stream coming from a file or user-at-keyboard or whatnot.)
--
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.
Nov 14 '05 #5

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

Similar topics

12
2264
by: AMT2K5 | last post by:
Hello. I have a file (for a school assignment) with the following format and delimiter format. Each record in the file has the following format: 123423454567987,29873,James,Ha­rry,St. Louis,416-555-5555; "accountNumber,balance,lastNam­e,city,phoneNumber;" Each record is guranteed to be no longer than 350 characters. "balance" is no longer than 20 characters, "accountNumber" is exactly 15 characters and the total number of characters in...
2
2696
by: CJ | last post by:
Newbie here. Trying to tackle following: Read text file containing list of files delimited by end of line chars. I need to somehow write a loop that filters out each of the lines of text within the text file as a filename to which I can then apply a number of functions.
7
5458
by: Thomas Sourmail | last post by:
Hi, I hope I am missing something simple, but.. here is my problem: I need my program to check the last column of a file, as in : a b c d target ref 0 0 0 0 1 a 1 0 0 0 1.5 b 2 0 0 0 2 c
7
27768
by: bhanuprakash | last post by:
I am trying to use fscanf to read my test file. In my test file i sometimes have blank lines. When I try to read using the following format. fscanf(fp,"%\n",temp_str); If there is any blank line it reads contents from the next line. How do I read blank into my variable if the line is blank. Example
9
3466
by: Justme | last post by:
Novice programmer needs help with using fgets to read and ignore the first two lines of a file. I've gone thru the previous posting regarding fgets, but none of them seems to help my situation. I have airdata file that i have to read, but in other teh fscanf to work properly, i need to ignore the first two lines, because scanf does not read spaces. This is what my current code looks like #include <stdio.h>
9
3228
by: quyvle | last post by:
I can't seem to get this function to work correctly. I'm wondering if anyone could help me out with this. So I'm using the fscanf function to read the input stream and store each string in the appropriate variables. Here's what I'm reading from another file: "# Number of power catergories: 9"
13
510
by: PeterOut | last post by:
I am using MS Visual C++ 6.0 on Windows XP 5.1 (SP2). I am not sure if this is a C, C++ or MS issue but fscanf has been randomly hanging on me. I make the call hundreds, if not thousands, of times but it hangs in different places with the same data. The offending code follows. ReadFile(char *csFileName) { float fFloat1, fFloat2;
6
506
by: tolkien | last post by:
Hi,i have this problem.I'm reading strings from a text file and i want to know in which line of the file i am. What i did is this: char string; while(!feof(text_file)){ fscanf(text_file,"%s",string); for(i=0;string!=' \0 ';i++) if(string==' \n ' ) lineCounter++;
42
3818
by: Bill Cunningham | last post by:
I'm doing something wrong and all I know to do is turn to clc. I have a text file containing 2 doubles separated by a tab. ..26 0 Is the text. I want to read the two double and printf them out. Here's my file. #include <stdio.h>
0
9632
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9471
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10302
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10071
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8958
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7478
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5501
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4036
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2867
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.