JKop wrote:
What I'm intending to do is copy all the lines into a new *output* file
stream, except "horse", and then overwrite the original. Would you be able
to provide any tips at all please?
Sure.
You are on the right track. When dealing with text files (except in some
rare circumstances), then the only possible way to modify that file is
be writing a new one and while writing that file apply all the intended
modifications. The only exception is when the replacement takes up the
same amount of bytes as the original, then you can simply seek to the
position and overwrite. But those cases are rare.
The next thing you should think about is:
How do I read. I mean: Which functionality do I use.
In your case you have 2 choices
you could eg.
std::string InWord;
InFile >> InWord;
This will work in your case, since each line contains only a single word.
So the basic loop would look like this
...
while( mammal_file >> InWord ) {
if( InWord != "horse" )
OutFile << InWord << "\n";
}
...
But I often feel that a different approach is simpler. What is
the problem? The problem comes if the file format gets more complicated,
saying you have 3 words on each line and there have to be exactly 3 words
on each line or otherwise the record (the line) is in error. So how to do this?
In cases like this it is often simpler to use getline (as I did in the
previous post). You use getline to read in the whole line as a single string
and then use eg. string functions to seperate that total string into the
words. Or you could use a stringstream to do the same.
So why is that often simpler. Think of the error case. By using getline
you have read the whole record, so if you figure out that that record
is bogous you don't need to do anything special with the input stream. You
just don't do anything with the bogus record and continue reading (and
emit an error message).
But in the read loop using >>?
Well, first of all you need to detect that the line is in error. >> ignores
line breaks because they are considered as white space. So detecting that
the number of words per line is wrong isn't that simple. Even then, lets say
the file format asks for a number, but in the file there is a text string "abc".
will fail for obvious reasons. But what then? In order to continue you still
need to read until the end of that record is read (the line break) for finding
the start of the next record. With the getline-version this is done all automatically.
But there is one (minor) point with getline. getline reads *and* includes the terminator
(in this case '\n'). So often one needs to get rid of that terminator are at least
deal with it. In your specific case, that would eg. be
while( getline( mammal_file, one_line ) ) {
if( one_line != "horse\n" )
OutFile << one_line;
}
Note: In the version using >> I had to write a '\n' on my own to the output stream, because has filtered it away. In the getline version I don't have to do that, because getline
has placed a '\n' in one_line as last character. That is: if there was one in the file.
The last line in the file may or may not contain a terminating '\n'.
So much for the thoughts about how to get at the file content.
Back to your program.
Open the output file and write to it whatever loop you want to choose.
Once you have finished, all that is left is
* delete the original file
you will want to use function remove() from <cstdio> for that
* rename the newly created file to the original file name
you will want to use function rename() from <cstdio> for that
It is a good idea to actually close the streams before the deletion and
renaming takes place.
As for: How to name that temporary file.
Often just a variation of the input file name is used. If the file system
supports file extensions, then it is often the name of the input file with
a different extension. But there is a second solution. As a leftover from
C there is a function called tmpnam, which generates a filename to be guaranteed
to not collide with any other file name in the directory. But look up the documentation
for that function. Often there are some tricky interactions with environment variables.
--
Karl Heinz Buchegger
kb******@gascad.at