Chris
Chris

Reputation: 62

Inserting a new line in a file deletes the next two characters C++

I have a file and I wish to separate items in the file by line. The indicator for the end of an item is a semicolon. So when I come across a semicolon, I want to put everything after the semicolon on a newline. And continue until i find the next semicolon and repeat.

char c;
fstream distances;

distances.open(argv[1]);

while(distances >> c) {
    if(c == ';') { 
        distances << endl; 
    }
}

This is the code inside main. It is opening the file correctly. The file says

i;am;testing;this

but after running the program the file reads:

i;
;
sting;
is

I'm not sure why it would delete the two characters following the semicolon. Unless it is using that space for \n character. If anyone could help or suggest a more efficient solution I would appreciate it.

Upvotes: 1

Views: 83

Answers (3)

kfsone
kfsone

Reputation: 24249

The fstream object you have is a representation of the bytes on disk. If 'insert' writes were allowed, the program would have to move every byte in the file after the insert point up by one position, essentially rewriting the file.

The only way to get an implemention of an 'insert' ability is to do it yourself, generally using a new file (you could do it in the same file by reading the rest of the file into memory, going back to the insert position, overwriting the character, and then writing your buffered copy of the file from before).

The reason that the next two characters are being overwritten is as follows:

// file buffer = [i][;][a][m][;][t]...
// position       ^
distances >> c;
// c = [i]
// file buffer = [i][;][a][m][;][t]...
// position          ^
distances >> c;
// c = [;]
// file buffer = [i][;][a][m][;][t]...
// position             ^
distances << endl;

std::endl writes the local line ending sequence and issues a std::flush to force writing. Under Windows, endl produces the sequence file << '\r' << '\n' << std::flush;

The stream position is where the 'a' is, not where the ';' is - by reading that character you advanced the stream position past it, so it writes the '\r' over the 'a' and the '\n' over the 'm'.

// file buffer = [i][;][a][m][;][t]...
// position             ^
  distances << '\r'
// file buffer = [i][;][\r][m][;][t]...
// position                 ^
   distances << '\n'
// file buffer = [i][;][\r][\n][;][t]...
// position                     ^
distances >> c;
// c = ';'
// file buffer = [i][;][\r][\n][;][t]...
// position                        ^

Upvotes: 1

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385194

Despite the illusion presented by text editing software, you can't "insert" into a file. You can only read its contents, modify them in memory, then write them back out again.

Your two characters are being replaced by your newline which, on Windows, actually consists of a Carriage Return followed by a Line Feed.

Upvotes: 3

Sam Varshavchik
Sam Varshavchik

Reputation: 118340

The most likely explanation is that you're using Microsoft Windows, where the newline sequence is two characters: a carriage return and a line feed: \r\n.

On Microsoft Windows a std::endl will write two characters: an \r and an \n.

Upvotes: 1

Related Questions