LinuxQuestions.org
Support LQ: Use code LQ3 and save $3 on Domain Registration
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 03-19-2014, 05:23 PM   #1
casualfred
Member
 
Registered: Aug 2012
Location: USA
Distribution: Slackware 14.1
Posts: 67

Rep: Reputation: 13
C++ reads in ASCII 255 at the end of files?


I am basically just trying to read in a file and output it to the terminal in C++, but I have noticed a strange character at the end of the output every time. I am using Slackware 14.1, gcc v4.8.2, and this occurs on files with both unix and dos line endings.
Code:
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>

using namespace std;

int main()
{
   ifstream thefile;
   char fileName[50], ch;

   cout << endl << "Enter filename: ";
   cin.getline(fileName, 49);
   thefile.open(fileName);
   if (thefile.fail())
   {
      cout << "file not opened" << endl;
      return 0;
   }

   cout << endl;

   while (! thefile.eof())
   {
      ch = thefile.get();
      cout << ch;
      if (ch == -1) // ASCII 255 or it wraps around to -1
         cout << endl << "EOF";
   }

   return 0;
}
And it outputs:
Code:
Enter filename: expr.d1

45 + 60
45 - 60
(23 + 45)
12
(12)
((12))
((12 + 12 + 12))

EOF
where my file "expr.d1" is:
Code:
45 + 60
45 - 60
(23 + 45)
12
(12)
((12))
((12 + 12 + 12))
So, I'm trying to figure out why it is outputting "", ASCII 255 at the end of the file. I have done some research, but I feel like I just don't know what's going on.

Thanks in advance for your help!
 
Old 03-19-2014, 06:15 PM   #2
gengisdave
Member
 
Registered: Dec 2013
Location: Turin, Italy
Distribution: slackware
Posts: 269

Rep: Reputation: 53
ascii 255 is the non breaking space, the html &nbsp;, does your file have an empty ending line or some other character before eof (first tought is about a copy-paste from a web page)?

Last edited by gengisdave; 03-19-2014 at 06:16 PM. Reason: typo
 
Old 03-19-2014, 06:27 PM   #3
michaelk
Moderator
 
Registered: Aug 2002
Posts: 11,853

Rep: Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738Reputation: 738
Code:
  while (! thefile.eof())
   {
      ch = thefile.get();
      cout << ch;
      if (ch == -1) // ASCII 255 or it wraps around to -1
         cout << endl << "EOF";
   }
Lets look at the loop. If the file pointer is at the last character in the file the while is still true, get() will read the next character which is EOF so cout<<ch will print the character representation which is that strange thing you see. (ch==-1) evaluates true so EOF is printed.
 
1 members found this post helpful.
Old 03-19-2014, 06:29 PM   #4
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: CentOS
Posts: 1,408

Rep: Reputation: 594Reputation: 594Reputation: 594Reputation: 594Reputation: 594Reputation: 594
EOF does not get set when you read the last character in the file. It is the next read that sets EOF, but you are printing the returned value (-1) from that unsuccessful read.

Why does EOF work that way? Because it is entirely possible for the file to grow between the time you read the last character and your next read.

Oops, echo in here.

Last edited by rknichols; 03-19-2014 at 06:31 PM.
 
1 members found this post helpful.
Old 03-19-2014, 06:55 PM   #5
casualfred
Member
 
Registered: Aug 2012
Location: USA
Distribution: Slackware 14.1
Posts: 67

Original Poster
Rep: Reputation: 13
Thanks for the replies! So would a do-while loop work better in my case do you think?

Edit: I went ahead and tried it, but it didn't seem to help. I don't recall ever having this problem before when trying to read in files... I'm not sure what I am doing wrong.

Last edited by casualfred; 03-19-2014 at 07:01 PM. Reason: I tried out what I asked.
 
Old 03-19-2014, 10:35 PM   #6
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: CentOS
Posts: 1,408

Rep: Reputation: 594Reputation: 594Reputation: 594Reputation: 594Reputation: 594Reputation: 594
Anything that prints ch as a character prior to testing for EOF is going to exhibit that problem. Of the myriad ways to code that loop, here is one:
Code:
while (! thefile.eof())
   {
      ch = thefile.get();
      if (ch == -1) // ASCII 255 or it wraps around to -1
         cout << endl << "EOF";
      else
         cout << ch; 
   }
And no, I'm not claiming that is the best way to code that.
 
Old 03-19-2014, 11:25 PM   #7
casualfred
Member
 
Registered: Aug 2012
Location: USA
Distribution: Slackware 14.1
Posts: 67

Original Poster
Rep: Reputation: 13
Alright, thanks rknichols. So, I could just filter the output like that. I think this is an answer to my question, so I'll mark it as solved.

But, let me be sure I understand what is happening here. There is an EOF flag C++ associates with an opened file. C++ sets that flag when it attempts a read, but finds there is nothing else to read. The failed read will always return this strange character.

Thanks for the great information and for taking the time to explain this stuff!
 
Old 03-20-2014, 04:02 AM   #8
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 1,676

Rep: Reputation: 487Reputation: 487Reputation: 487Reputation: 487Reputation: 487
(It's quite common mistake, almost everyone has it once... getchar/getc/fgetc/... return unsigned char or -1, so the value should be stored in 'int' not 'char')
 
1 members found this post helpful.
Old 03-20-2014, 03:22 PM   #9
sundialsvcs
Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 5,330

Rep: Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100
Do it this way:

Code:
while not ( eof ) {
  get()
  if not ( eof ) {
    ... do something ...
  end-if
end-while
Or this way:

Code:
get()
while not ( eof ) {
  ... do something ...
  get()
end-while
Usually, eof indications are produced by attempts to "get" something. They don't look-ahead to see if eof is about to be reached. (The only language that I recall which attempted to do otherwise was Standard Pascal, and it was ugly.)

Your code is basically producing garbage at the last because it has just read past the end of the file. Although the eof indicator will have been tripped thereby, you're not checking for that after the get which ran-dry.
 
Old 03-20-2014, 06:23 PM   #10
casualfred
Member
 
Registered: Aug 2012
Location: USA
Distribution: Slackware 14.1
Posts: 67

Original Poster
Rep: Reputation: 13
Thanks sundialsvcs - yeah that's pretty much what I came up with in the end:
Code:
char ch;
ch = thefile.get();
while (! thefile.eof())
{
   cout << ch;
   ch = thefile.get;
}
But I've found a situation where your first example would work better also.

I think I understand what's going on now - thanks again everyone for the helpful guidance!
 
Old 03-20-2014, 11:43 PM   #11
sundialsvcs
Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 5,330

Rep: Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100Reputation: 1100
Heh... I like the second one better, myself, and normally do it that way.
 
Old 03-21-2014, 10:12 AM   #12
rknichols
Senior Member
 
Registered: Aug 2009
Distribution: CentOS
Posts: 1,408

Rep: Reputation: 594Reputation: 594Reputation: 594Reputation: 594Reputation: 594Reputation: 594
My own preference is for
Code:
while (get(), ! eof) {
    ... do something ...
}
 
Old 03-22-2014, 11:09 AM   #13
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,522

Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332
You can always evaluate the file stream object after you have performed a call to get(). C++ ios stream objects (including fstream) implement an operator bool() method that returns the state of the stream.

Something like:
Code:
char ch;

while ((ch = file.get()) && file)
{
    std::cout << ch;
}
std::cout << "EOF" << std::endl;
You could also consider reading one line at a time from the data file.
Code:
char line[80];
while (file.getline(line, sizeof(line)) && file)
{
    std::cout << line << std::endl;
}
std::cout << "EOF" << std::endl
Edit... another option:
Code:
std::string line;
while (std::getline(file, line) && file)
{
    std::cout << line << std::endl;
}
std::cout << "EOF" << std::endl;

Last edited by dwhitney67; 03-22-2014 at 11:12 AM.
 
1 members found this post helpful.
Old 03-25-2014, 06:38 PM   #14
casualfred
Member
 
Registered: Aug 2012
Location: USA
Distribution: Slackware 14.1
Posts: 67

Original Poster
Rep: Reputation: 13
Interesting. Thanks dwhitney67!
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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 Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
What is this -> SRC=0.0.0.0 DST=255.255.255.255 LEN=328 TOS=0x00 PREC=0x00 TTL=128 ID carves Linux - Networking 5 08-17-2008 09:26 PM
Are Broadcasts to 255.255.255.255 Routed MQMan Linux - Networking 6 11-23-2005 02:16 PM
Logs full of hits to 255.255.255.255; how to stop logging? mac_phil Mandriva 2 02-23-2004 10:25 AM
UDP broadcast 255.255.255.255 java8964 Linux - Networking 0 10-29-2003 02:05 PM
configuring RH 7 for a subnet mask of 255.255.255.224 CDPL Linux - Networking 2 04-20-2002 09:06 AM


All times are GMT -5. The time now is 08:15 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration