Reputation: 35
I'm currently trying to write a bit of code to read a file and extract bits of it and save them as variables.
Here's the relevant code:
char address[10];
ifstream tracefile;
tracefile.open ("trace.txt");
tracefile.seekg(2, ios::beg);
tracefile.get(address, 10, ' ');
cout << address;
The contents of the file: (just the first line)
R 0x00000000
The issue I'm having is that address misses the final '0' because it puts a /0 character there, and I'm not sure how to get around that? So it outputs:
0x0000000
I'm also having issues with
tracefile.seekg(2, ios::cur);
It doesn't seem to work, hence why I've changed it to ios::beg just to try and get something work, although obviously that won't be useable once I try to read multiple lines after one another.
Any help would be appreciated.
Upvotes: 1
Views: 1813
Reputation: 63839
ifstream::get()
will attempt to produce a null-terminated C string, which you haven't provided enough space for.
You can either:
char address[11];
(or bigger) to hold a null-terminated string longer than 9 characters.ifstream::read()
instead to read the 10 bytes without a null-terminator.Edit:
If you want a buffer that can dynamically account for the length of the line, use std::getline
with a std::string
.
std::string buffer;
tracefile.seekg(2, ios::beg);
std::getline( tracefile, buffer );
Edit 2
If you only want to read to the next whitespace, use:
std::string buffer;
tracefile.seekg(2, ios::beg);
tracefile >> buffer;
Upvotes: 4
Reputation: 153977
There are several issues with your code. The first is that
seekg( 2, ios::beg )
is undefined behavior unless the stream
is opened in binary mode (which yours isn't). It will work
under Unix, and depending on the contents of the file, it
might work under Windows (but it could also send you to the
wrong place). On some other systems, it might systematically
fail, or do just about anything else. You cannot reliably seek
to arbitrary positions in a text stream.
The second is that if you want to read exactly 10 characters,
the function you need is istream::read
, and not
istream::get
. On the other hand, if you want to read up to
the next white space, using >>
into a string will work best.
If you want to limit the number of characters extracted to a
maximum, set the width before calling >>
:
std::string address;
// ...
tracefile >> std::setw( 10 ) >> address;
This avoids all issues of '\0'
, etc.
Finally, of course, you need error checking. You should probably check whether the open succeeded before doing anything else, and you should definitely check whether the read succeeded before using the results. (As you've written the code, if the open fails for any reason, you have undefined behavior.)
If you're reading multiple lines, of course, the best solution
is usually to use std::getline
to read each line into a
string, and then parse that string (possibly using
std::istringstream
). This prevents the main stream from
entering error state if there is a format error in the line, and
it provides automatic resynchronization in such cases.
Upvotes: 1
Reputation: 76438
Make the buffer bigger, so that you can read the entire input text into it, including the terminating '\0'
. Or use std::string
, which doesn't have a pre-determined size.
Upvotes: 0