Re: get corruption at end of string
On May 23, 5:54 pm, "Angus" <nos...@gmail.com> wrote:
I am using ifstream to load the contents of a text file into a char*
variable. I am allocating using new with the file size as amount to
allocate. My problem is that the variable contains a load of misc
extraneous data at the end of the variable.
Here is the code.
A meta-comment: this would be a lot easier and clearer if you'd
use std::string.
int main(int argc, char* argv[])
{
std::ifstream myfile;
std::string line;
long begin,end;
char szFile[256];
char* memblock;
I'd initialize this to something, at least NULL. Or just
define it later, when you can initialize it correctly.
In general, it is bad policy to define variables before you can
correctly initialize them. In the case of pointers, it's
particularly serious.
std::ifstream::pos_type size;
std::cout << "Enter filename to open: ";
std::cin.getline(szFile, 256);
std::cout << "You selected file: " << szFile << std::endl;
myfile.open( szFile );
if (myfile.is_open())
{
begin = myfile.tellg();
myfile.seekg (0, std::ios::end);
Note that this seek may set eofbit, which will in turn cause all
further operations to fail. (I don't think it's supposed to,
but I believe that it does, or at least did, in some
implementations. I'd throw in a call to clear(), here, just to
be sure.)
end = myfile.tellg();
size = end-begin;
Note that this is not guaranteed to give you anything
significant. In the case of Unix, it probably will result in
the file size. In the case of Windows, it will almost surely be
more than is necessary. And on other systems, it might have no
relationship what so ever to the real file size.
memblock = new char [size];
myfile.seekg (0, std::ios::beg);
myfile.read (memblock, size);
Did the read succeed? How many characters did you really read?
istream::read() is a funny function, since it can "fail" even
when it partially succeeds. Basically, it will "fail" unless it
can read size characters (which will almost certainly be the
case if you're not on Unix). Basically, you need to call
gcount(), to know how many characters it actually read---only if
gcount() returns 0 did the read completely fail.
myfile.close();
std::cout << memblock << std::endl;
Since memblock isn't '\0' terminated, it's not a legal argument
to << here.
Personally, I'd write this entire block:
std::istringstream s ;
s << myfile.rdbuf() ;
std::cout << s.str() << std::endl ;
If for some reason I really needed a C style array, and didn't
have to worry about portability beyond Unix and Windows, I'd do
something along the lines of:
// Calculate size as above. It will be exact
// under Unix, and >= the real size under Windows,
// typically a little greater, but not too much.
std::vector< char > buffer( size + 1 ) ;
myfile.read( &buffer[ 0 ], size ) ;
size = myfile.gcount() ;
if ( ! myfile && size == 0 ) {
// Error...
} else {
buffer[ size ] = '\0' ;
// use &buffer[ 0 ] as C style string...
}
delete [] memblock;
}
return 0;
}
if I myfile.read just size then why do I get all the unallocated characte=
rs
at the end of the memblock variable?
Because you don't terminate the C style string. And because you
don't check how many characters you've actually read, to know
where to terminate it.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34