 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Philip Maguire Guest
|
Posted: Fri Mar 05, 2004 10:34 am Post subject: Reading data from a .dat file with a standard format |
|
|
I am relatively new to C++ and am teaching myself. I have read a few
books on the subject and searched through this forum but nothing seems
to cover the problem I have encountered when trying to read data from
a .dat file with the following format:
//Start of File
//Description of File
Data I want to read in (all of type char[2])
//End of File
I have the following questions:
1. I know that the data I want to read in will always start on the 3rd
line of the .dat file. I know there is a function istream.seekg()
which will allow me to offset where the program starts to read in data
from the file by a set number of characters is there a similar
function to offset by the number of /n delimiters? If not what is the
best way to get my program to ignore the first two lines in the .dat
file? I have tried using the fact that the unwanted lines begin with
"/" using istream.getline(s, "length of string") and then strcmp to
try and compare the first character of s with "/" but this seems to
throw up problems when I compile with const character pointers. Can I
solve this using dynamic memory?
2. Once I have got the program to start reading in data in the correct
place how do I stop it when it gets to the start of the line "//End of
File". I considered using istream.get() in my while loop and having an
if loop such as:
if(!strcmp(fin.get(), "/")
{
break;
}
where fin is my istream object for the file I am reading. This,
however, doesn't seem to work.
Help. This seems like it should be so trivial......
Regards,
Philip Maguire
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Dhruv Matani Guest
|
Posted: Fri Mar 05, 2004 2:36 pm Post subject: Re: Reading data from a .dat file with a standard format |
|
|
On Fri, 05 Mar 2004 05:34:50 -0500, Philip Maguire wrote:
| Quote: | Help. This seems like it should be so trivial......
|
Yes, but it is usually these trivial looking problems that require more
thinking!
Here is a possible solution:
#include <cstdio>
#include <exception>
#include <ostream>
#include <vector>
#include <iostream>
using namespace std;
FILE *gpf;
struct Data {
char d[2];
};
std::ostream& operator<< (std::ostream& out, const Data& dref)
{
out<
return out;
}
char lookahead()
{ return fgetc(gpf); }
void unlook (char ch)
{ ungetc (ch, gpf); }
struct Error : public std::exception { };
Data Next()
{
static int End = 0;
char ch = lookahead();
if (ch == '/')
++End;
char tp = lookahead();
if (tp == '/')
++End;
if (End == 2)
throw Error();
char t1 = lookahead();
if (t1 == '/' && tp == '/')
throw Error();
else
unlook (t1);
End = 0;
Data ret;
ret.d[0] = ch;
ret.d[1] = tp;
return ret;
}
void Fill_Vector (std::vector
{
int count = 2;
while (count)
{
if (lookahead() == 'n')
--count;
}
try
{
while (true)
res.push_back (Next());
}
catch (Error)
{ }
}
int main()
{
gpf = fopen ("data.txt", "r");
if (!gpf)
{
fprintf (stderr, "Error Opening Input File");
return 1;
}
std::vector<Data> data;
Fill_Vector(data);
std::vector<Data>::iterator i = data.begin();
while (i != data.end())
std::cout<<*i++;
}
I guess this should work.
--
Regards,
-Dhruv.
Proud to be a Vegetarian.
http://www.vegetarianstarterkit.com/
http://www.vegkids.com/vegkids/index.html
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ben Hutchings Guest
|
Posted: Fri Mar 05, 2004 11:54 pm Post subject: Re: Reading data from a .dat file with a standard format |
|
|
Philip Maguire wrote:
| Quote: | I am relatively new to C++ and am teaching myself. I have read a few
books on the subject and searched through this forum but nothing seems
to cover the problem I have encountered when trying to read data from
a .dat file with the following format:
|
Do you realise that ".dat" is a meaningless extension? (What else
does a file contain, if not data?)
| Quote: | //Start of File
//Description of File
Data I want to read in (all of type char[2])
//End of File
I have the following questions:
1. I know that the data I want to read in will always start on the 3rd
line of the .dat file. I know there is a function istream.seekg()
which will allow me to offset where the program starts to read in data
from the file by a set number of characters is there a similar
function to offset by the number of /n delimiters? If not what is the
best way to get my program to ignore the first two lines in the .dat
file?
snip |
You can use std::istream::ignore:
for (int i = 0; i != 2; ++i)
fin.ignore(std::numeric_limits<int>::max, 'n');
Look in your documentation/textbook for an explanation of this
function.
However, you might want to check what's on the first two lines in
order to detect an invalid file. In that case, use std::getline() -
see the code in my answer to question 2.
| Quote: | 2. Once I have got the program to start reading in data in the correct
place how do I stop it when it gets to the start of the line "//End of
File". I considered using istream.get() in my while loop and having an
if loop such as:
if(!strcmp(fin.get(), "/")
{
break;
}
where fin is my istream object for the file I am reading. This,
however, doesn't seem to work.
Help. This seems like it should be so trivial......
|
You would probably be better off using std::getline() instead of
std::istream::getline():
std::string line;
while (std::getline(fin, line) && line != "//End of File")
{
// Process the line
}
if (std::cin.fail())
{
// Handle the error
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
John Potter Guest
|
Posted: Fri Mar 05, 2004 11:58 pm Post subject: Re: Reading data from a .dat file with a standard format |
|
|
On 5 Mar 2004 05:34:50 -0500, [email]Philmaguire50 (AT) hotmail (DOT) com[/email] (Philip Maguire)
wrote:
| Quote: | I am relatively new to C++ and am teaching myself. I have read a few
books on the subject and searched through this forum but nothing seems
to cover the problem I have encountered when trying to read data from
a .dat file with the following format:
//Start of File
//Description of File
Data I want to read in (all of type char[2])
//End of File
|
The real data is ill-defined. Is it two characters per line or what?
Since you indicate there is a line at the end, there must be lines
in the data. You must process the line ends whether you like it or
not.
| Quote: | I have the following questions:
1. I know that the data I want to read in will always start on the 3rd
line of the .dat file. I know there is a function istream.seekg()
which will allow me to offset where the program starts to read in data
from the file by a set number of characters is there a similar
function to offset by the number of /n delimiters?
|
No.
| Quote: | If not what is the
best way to get my program to ignore the first two lines in the .dat
file?
|
Use ignore. :)
fin.ignore(INT_MAX, 'n').ignore(INT_MAX, 'n');
| Quote: | 2. Once I have got the program to start reading in data in the correct
place how do I stop it when it gets to the start of the line "//End of
File".
|
How do you know when you are at the start of a line?
Considering the lack of information about the data part other than there
must be lines, I would suggest string.
string line;
while (getline(fin, line) && line.substr(0, 2) != "//")
for (string::size_type pos(0); pos != line.size(); pos += 2)
process(&line[pos]);
That assumes no blank lines or other complications. I think that this
provides the tools to solve your real porblem.
John
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
James Kanze Guest
|
Posted: Sat Mar 06, 2004 10:18 am Post subject: Re: Reading data from a .dat file with a standard format |
|
|
John Potter <jpotter (AT) falcon (DOT) lhup.edu> writes:
| Quote: | On 5 Mar 2004 05:34:50 -0500, [email]Philmaguire50 (AT) hotmail (DOT) com[/email] (Philip Maguire)
wrote:
I am relatively new to C++ and am teaching myself. I have read a
few books on the subject and searched through this forum but
nothing seems to cover the problem I have encountered when trying
to read data from a .dat file with the following format:
//Start of File
//Description of File
Data I want to read in (all of type char[2])
//End of File
The real data is ill-defined.
|
Not ill-defined : totally undefined:-). Is it really character data, or
is it maybe some binary values?
This leads to a more general question: how do you handle a file which
contains a mixture of binary and textual, line oriented data? The
problem came up recently in the French speaking newsgroups, and I'll
admit that I was unable to come up with anything reasonably portable or
elegant. The problem was a file consisting of three lines containing
information about the format, in pure ASCII format, followed by raw
binary data. If you open the file in binary mode, getline() might not
work: potentially, you might even loose your line separators entirely.
But of course, if you open it without the binary, there is a very good
chance of your binary data being corrupted. (The non-portable solution
is, of course, to know how the newlines are represented at the file
level, to open the file in binary, and to write your own version of
getline which understands the binary new lines.)
[...]
| Quote: | Considering the lack of information about the data part other than
there must be lines, I would suggest string.
string line;
while (getline(fin, line) && line.substr(0, 2) != "//")
for (string::size_type pos(0); pos != line.size(); pos += 2)
process(&line[pos]);
That assumes no blank lines or other complications. I think that this
provides the tools to solve your real porblem.
|
One possible alternative would be to use a filtering streambuf which
reads ahead, and returns EOF when it sees a match for "//.*n<EOF>" in
its look-ahead buffer. (When all you have is a hammer, everything looks
like a nail. Filtering streambuf's are my hammer:-).)
--
James Kanze mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France +33 1 41 89 80 93
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Nicholas Jordan Guest
|
Posted: Sun Mar 07, 2004 10:26 am Post subject: Re: Reading data from a .dat file with a standard format |
|
|
James Kanze <kanze (AT) gabi-soft (DOT) fr> wrote
| Quote: | John Potter <jpotter (AT) falcon (DOT) lhup.edu> writes:
|> On 5 Mar 2004 05:34:50 -0500, [email]Philmaguire50 (AT) hotmail (DOT) com[/email] (Philip Maguire)
|> wrote:
|> > I am relatively new to C++ and am teaching myself. I have read a
|> > few books on the subject and searched through this forum but
|> > nothing seems to cover the problem I have encountered when trying
|> > to read data from a .dat file with the following format:
|> > //Start of File
|> > //Description of File
|> > Data I want to read in (all of type char[2])
|> > //End of File
|> The real data is ill-defined.
Not ill-defined : totally undefined:-). Is it really character data, or
is it maybe some binary values?
This leads to a more general question: how do you handle a file which
contains a mixture of binary and textual, line oriented data? The
problem came up recently in the French speaking newsgroups, and I'll
admit that I was unable to come up with anything reasonably portable or
elegant. The problem was a file consisting of three lines containing
information about the format, in pure ASCII format, followed by raw
binary data. If you open the file in binary mode, getline() might not
work: potentially, you might even loose your line separators entirely.
But of course, if you open it without the binary, there is a very good
chance of your binary data being corrupted. (The non-portable solution
is, of course, to know how the newlines are represented at the file
level, to open the file in binary, and to write your own version of
getline which understands the binary new lines.)
[...]
|> Considering the lack of information about the data part other than
|> there must be lines, I would suggest string.
|> string line;
|> while (getline(fin, line) && line.substr(0, 2) != "//")
|> for (string::size_type pos(0); pos != line.size(); pos += 2)
|> process(&line[pos]);
|> That assumes no blank lines or other complications. I think that this
|> provides the tools to solve your real porblem.
One possible alternative would be to use a filtering streambuf which
reads ahead, and returns EOF when it sees a match for "//.*n<EOF>" in
its look-ahead buffer. (When all you have is a hammer, everything looks
like a nail. Filtering streambuf's are my hammer:-).)
|
Philip: [from Nicholas Jordan]
I have been working on a not totally dissimilar problem myself -
similar problem description, same responses. Going about it the same
way and absolutely loving 5 AM Teflon on Ice sessions of reinventing
the wheel ... I am stuck right at the moment because of not knowing
textbook use of pointers; I cannot get enough information out of the
box and onto the screen that I can make reasonable speculations as to
what is going on.
ill-defined ? Do you mean you wish to defer to runtime the content of
the datafile ? That doesn't sound right. I should assume you mean you
do not have the ultimate design of the system figured out. This is
known engineering, called back of the envelope design or (when others
are listening) "Prototyping"
see:http://www-106.ibm.com/developerworks/library/us-paper/?dwzone=usability
There is nothing wrong with this as long as it is followed up by
methods called Top-Down design - but do you even know what it is you
want to do or are you unsure of the problem you have encountered ?
..dat ? I am relatively new to C++ and am teaching myself, but I read
this in C++ Primer Plus from Sams, just about when he leaves off. If
this is high-school shop programming, then how come the old-school
CZars....it gets deep to me quick an I have given a lot of thought to
the matter generally ~ but I used to know this elephant trainer who
could push around 20,000 pound elephants with a sharp stick.
Who says elephants can't dance ? See the page at:
http://www.docdubya.com/belvedere/statement/DROSS.html
and tell me if you think we can work together on this
coding/testing/design issue.
It's hard to find people like:
http://home.nc.rr.com/emulroy/mylinks.htm
And I have been wrestling with STL::Vector / SGI::hash_map ~ giving up
and reverting to writing the files directly myself using .....
And at that point, my problem description closely parallels yours.
internet alias: Nicholas Jordan
Nick's Law: The only dumb question is one you should have asked and
didn't.
user: E183EEB1E at
hotmail dot com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|