C Programming
 
Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
User Name:
Password:
Remember me

The Shed is going Social! Join us on FaceBook and Twitter and chime in on the conversation.

Go Back   Dev Shed ForumsProgramming LanguagesC Programming

Reply
Add This Thread To:
  Del.icio.us   Digg   Google   Spurl   Blink   Furl   Simpy   Y! MyWeb 
Thread Tools Search this Thread Rate Thread Display Modes
 
Unread Dev Shed Forums Sponsor:
  #1  
Old March 12th, 2003, 09:33 PM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,365 7stud User rank is Private First Class (20 - 50 Reputation Level)7stud User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 18 h 20 m 28 sec
Reputation Power: 14
C++ file I/O problem

Hi,

I'm having a slight problem with file I/O. I'm writing a sentence to a file, and then reading it back character by character and displaying the characters immediately after reading them. Therefore, the sentence in the file and the sentence displayed to the screen should be the same. However, the sentence displayed to the screen has two periods. Why?

Code:
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	
	const char* filename = "C:\\TestData\\input.txt";
	//associate an fstream object with my data file:
	fstream fileStream(filename);
	
	//write the sentence to the data file:
	fileStream<<"The man is running.";
	
	//reset the internal pointer to the beginning of the data file:
	fileStream.seekg(0);
	
	char temp;
	while(!fileStream.eof())
	{	
		fileStream.get(temp); //read one character from the data file
		cout<<temp; //display the character
	}
	cout<<endl;
	return 0;
}


data file output>>The man is running.
displayed to screen>>The man is running..

Last edited by 7stud : March 13th, 2003 at 12:08 AM.

Reply With Quote
  #2  
Old March 13th, 2003, 09:44 AM
dwise1_aol's Avatar
dwise1_aol dwise1_aol is offline
Contributing User
Dev Shed God 2nd Plane (6000 - 6499 posts)
 
Join Date: Jan 2003
Location: USA
Posts: 6,256 dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level)dwise1_aol User rank is General 15th Grade (Above 100000 Reputation Level) 
Time spent in forums: 2 Months 2 Weeks 5 Days 20 h 36 m 23 sec
Reputation Power: 1985
I've been doing embedded for several years and precious little file I/O, but I seem to recall that using eof() can be tricky.

eof() reflects the EOF state of the file stream. That EOF state does not get set until the end of the file has been detected by having a read fail. First an attempt to read must fail, then eof() will do what we expect.

In your code segment --
Code:
char temp;
while(!fileStream.eof())
{	
      fileStream.get(temp); //read one character from the data file
      cout<<temp; //display the character
}

-- , when your get(temp) fails at the end of file, you go ahead and output it anyway. Since the value of temp did not get changed, it still contains a '.'.

eof() needs to be tested before you output what you've read. I would rewrite that segment as:
Code:
char temp;
fileStream.get(temp); //read first character from the data file
while(!fileStream.eof())
{	
        cout<<temp; //display the character
        fileStream.get(temp); //read one character from the data file
}


I haven't tested it, but I think that should work.

Reply With Quote
  #3  
Old March 13th, 2003, 03:10 PM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,365 7stud User rank is Private First Class (20 - 50 Reputation Level)7stud User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 18 h 20 m 28 sec
Reputation Power: 14
"eof() reflects the EOF state of the file stream. That EOF state does not get set until the end of the file has been detected by having a read fail."

Thanks for the response. Your code works, however, I think your explanation may be erroneous because my book says: "After the last value has been read from the file, the eof() member will return true, because the current file position will be at the end of the file." It's my understanding that after you read a character, the internal file pointer moves to the next position in the file. So, after I read in the last character, the period in my case, the internal file pointer should be pointing at the end of the file, and therfore eof() will return true and !fileStream.eof() will return false causing the while loop to terminate.

I suspect my problem has to do with there being another character in the stream after the period, and the code you suggested just throws out that last character. My book says that in text mode there isn't necessarily a one for one representation when writing to a file i.e. some characters will be represented by more than one byte in the output file. Could that be what's happening?

Reply With Quote
  #4  
Old March 13th, 2003, 03:25 PM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,365 7stud User rank is Private First Class (20 - 50 Reputation Level)7stud User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 18 h 20 m 28 sec
Reputation Power: 14
Here's a short program that demonstrates the way I am using eof() isn't the problem:

Code:
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	
	const char* filename = "C:\\TestData\\input.txt";
	//associate an fstream object with my data file:
	fstream fileStream(filename);
	
	//write two numbers to the data file:
	fileStream<<100<<" "<<300;
	
	//reset the internal pointer to the beginning of the data file:
	fileStream.seekg(0);
	
	int number;
	while(!fileStream.eof())
	{
		
		fileStream>>number; //read one number from the data file
		 
		cout<<number<<endl;//display the number
	}
	return 0;
}


output to file>> 100 300
output to screen>>
100
300

Last edited by 7stud : March 13th, 2003 at 03:28 PM.

Reply With Quote
  #5  
Old March 13th, 2003, 05:44 PM
3dfxMM 3dfxMM is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2002
Posts: 272 3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 6 Days 17 h 57 m 24 sec
Reputation Power: 17
Unfortunately, your example is an apples and oranges kind of thing. Reading into a number is different than getting a char at a time. Your original code does attempt to read from the file after it gets the period. This last read fails, leaving temp alone so there is still a period in it. I do not know why, but this is what is happening.

Reply With Quote
  #6  
Old March 13th, 2003, 05:48 PM
Gmorphus Gmorphus is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Sep 2001
Location: ISRAEL
Posts: 35 Gmorphus User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 12
Send a message via ICQ to Gmorphus
when I use eof I do as dwise1_aol described and i think that is the right explnation.
I the program you demonstrated you used number which works a but differently. I'm not sure exactly how but it reads characters until the next white space (blank, tab, new-line, eof etc.)
so it isn't the case with reading char.
__________________
"Gravitation can NOT be responsible for people falling in Love"
(one of the most significant characters in the history, can you guess?)

Gmorph.

Reply With Quote
  #7  
Old March 13th, 2003, 11:32 PM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,365 7stud User rank is Private First Class (20 - 50 Reputation Level)7stud User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 18 h 20 m 28 sec
Reputation Power: 14
Thanks for taking the time to respond.

Could it be there's a \0 at the end of the string literal I write to the file that is causing that? I thought that was only for arrays.

Reply With Quote
  #8  
Old March 14th, 2003, 12:28 AM
3dfxMM 3dfxMM is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Aug 2002
Posts: 272 3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level)3dfxMM User rank is Sergeant (500 - 2000 Reputation Level) 
Time spent in forums: 6 Days 17 h 57 m 24 sec
Reputation Power: 17
The null terminator is not written to the stream. The period is the last byte in the file. I think that the explanation given earlier is correct. eof is not set until a read past the last character is attempted. This read will fail, but in your code you don't check for that before outputting temp to the screen.

Reply With Quote
  #9  
Old March 14th, 2003, 01:26 AM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,365 7stud User rank is Private First Class (20 - 50 Reputation Level)7stud User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 18 h 20 m 28 sec
Reputation Power: 14
"I think that the explanation given earlier is correct."

Yes, but I was troubled by not being able to reconcile the differences in eof when dealing with numbers and char types. However, I think I came up with a sample program that demonstrates that what dwise1_aol said about eof() is true for both numbers and char types.

Code:
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	
	char* filename = "C:\\TestData\\input.txt";
	//associate an fstream object with my data file:
	fstream fileStream(filename);
	
	//write the numbers to file ENDING W/ A SPACE:
	fileStream<<100<<" "<<300<<" ";
	
	//reset the internal pointer to the beginning of the data file:
	fileStream.seekg(0);
	
	int number;
	while(!fileStream.eof())
	{
		
		fileStream>>number; //read one number from the data file
		 
		cout<<number<<endl; //display the number
	}
	
	return 0;
}

output to data file>>100 300
output to screen>>
100
300
300

What was confusing to me was proposition that numbers and char types are different when it comes to eof(), and I didn't believe that could be the case. The rules for when a read from the stream is accomplished for numbers and char types are different, but I didn't believe eof could be interpreted differently, and I believe my sample programs show that eof is treated the same. My conclusion is: if there isn't a delimiter, like a space, following the last number in a file, the read that gets that number from the stream also reads eof. If a space is tacked on the end, the read stops at the space delimiter, and then it takes one more read to get eof, just like with the char type.

Thanks everybody.

Last edited by 7stud : March 14th, 2003 at 02:43 AM.

Reply With Quote
  #10  
Old March 14th, 2003, 02:43 AM
Gmorphus Gmorphus is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Sep 2001
Location: ISRAEL
Posts: 35 Gmorphus User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 12
Send a message via ICQ to Gmorphus
i have to disagree.
in the last case you showed you actually added more chars.
but in the first case with the sentence you didn't add anything.

i think that doesn't exaplin the problem....

Reply With Quote
  #11  
Old March 14th, 2003, 03:03 AM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,365 7stud User rank is Private First Class (20 - 50 Reputation Level)7stud User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 18 h 20 m 28 sec
Reputation Power: 14
I'm not sure I understand. With a char type, a read stops after every character, and after reading the last character in the sentence, one more read is required to read eof.

With the 2nd sample program, there are two numbers separated by a delimiter, the space, and there was no duplication in the output. So, I believed the question presented was: why wasn't one more read required to read in eof in that case?

I believe the third sample program--the one that has a space tacked on at the end of the last number in the file--shows that when reading numbers, the read ends only when you hit a number delimiter. So, the program hit the space delimiter after reading the last number and that caused eof not to be read in, so it took one more read to read eof, and therefore the same duplication seen in the first program occurred. Note that the first program also hit a delimiter--the end of 1 byte-- before it could read in eof, and that is what caused the duplication there. In the second sample program, the last read did not encounter a delimiter, so it read in eof too on the last read which caused the loop to fail and no duplication.

Therefore, I believe eof is treated consistently: when reading the last piece of data in your file if you hit a delimiter before reading eof, one more read is required to read in eof.

Last edited by 7stud : March 14th, 2003 at 03:28 AM.

Reply With Quote
  #12  
Old March 14th, 2003, 03:41 AM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,365 7stud User rank is Private First Class (20 - 50 Reputation Level)7stud User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 18 h 20 m 28 sec
Reputation Power: 14
Well, if anyone cares, I figured out how to make the first program with the sentence work using a method that was a little cleaner than dwise1_aol's method: I used peek() in the loop control. peek() reads the character in the stream the internal file pointer is pointing to, but the character is left in the stream i.e the file pointer doesn't move. That allowed me to take a look at what's located at the current position before reading it, and skip the loop if I was going to read in EOF(which I guess is a defined character of some sort).

Code:
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
	
	char* filename = "C:\\TestData\\input.txt";
	//associate an fstream object with my data file:
	fstream fileStream(filename);
	
	//write the sentence to the data file:
	fileStream<<"The man is running.";
	
	//reset the internal pointer to the beginning of the data file:
	fileStream.seekg(0);
	
	char text;
	while(fileStream.peek() != EOF)
	{
		
		fileStream.get(text); //read one character from the data file
		 
		cout<<text; //display the character
	}
	cout<<endl;
	
	return 0;
}

Last edited by 7stud : March 14th, 2003 at 03:52 AM.

Reply With Quote
  #13  
Old March 14th, 2003, 04:14 AM
Gmorphus Gmorphus is offline
Contributing User
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Sep 2001
Location: ISRAEL
Posts: 35 Gmorphus User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 12
Send a message via ICQ to Gmorphus
first of all thank for the knowledge of Peek.
But it isn't right to do it using Peek(). the reason is Efficiency!

when using Peek you actually reading from the file twice for each char - reading from a file is relatively slow.

hence, you should use the solution described earlier (reading the first char befor the loop).

using the quick watch of VC++ (Shift+F9) you can that immediatly after trying to read the char next to the point you gat the eof set.

it isn't "ugly" to do read the first char before the loop - it is the way it is done.

all in all, i think you should use the API function (CreateFile, ReadFile, WriteFile etc.)

Reply With Quote
  #14  
Old March 14th, 2003, 05:19 AM
7stud 7stud is offline
Contributing User
Dev Shed Beginner (1000 - 1499 posts)
 
Join Date: Feb 2001
Posts: 1,365 7stud User rank is Private First Class (20 - 50 Reputation Level)7stud User rank is Private First Class (20 - 50 Reputation Level) 
Time spent in forums: 18 h 20 m 28 sec
Reputation Power: 14
"when using Peek you actually reading from the file twice for each char - reading from a file is relatively slow.

hence, you should use the solution described earlier (reading the first char befor the loop)."

Ok. Thanks for the tip!

Reply With Quote
  #15  
Old March 14th, 2003, 10:51 AM
grunt grunt is offline
Junior Member
Dev Shed Newbie (0 - 499 posts)
 
Join Date: Mar 2003
Posts: 6 grunt User rank is Just a Lowly Private (1 - 20 Reputation Level) 
Time spent in forums: < 1 sec
Reputation Power: 0
I wonder what compiler you are using? I seem to recall a similar issue due to a bug in borlands compiler (5.0 I think). The next version addressed the issue.

Reply With Quote
Reply

Viewing: Dev Shed ForumsProgramming LanguagesC Programming > C++ I/O problem

Developer Shed Advertisers and Affiliates



Thread Tools  Search this Thread 
Search this Thread:

Advanced Search
Display Modes  Rate This Thread 
Rate This Thread:


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

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
View Your Warnings | New Posts | Latest News | Latest Threads | Shoutbox
Forum Jump

Forums: » Register « |  User CP |  Games |  Calendar |  Members |  FAQs |  Sitemap |  Support | 
  
 


Powered by: vBulletin Version 3.0.5
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.

© 2003-2013 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap