I need to create a binary file and store inside it 10 numbers, and after that go one by one element of file and replace it with it's opposite number.
#include <iostream>
#include <fstream>
int main() {
std::fstream file("numbers.dat", std::ios::app | std::ios::in|std::ios::out|std::ios::binary);
for (double i = 1; i <= 10; i )
file.write(reinterpret_cast<char*>(&i), sizeof i);
int length_of_file = file.tellg();
int number_of_elements = length_of_file / sizeof(double);
for (int i = 0; i < number_of_elements; i ) {
double num;
file.seekg(0); // change mode to reading
file.seekg(i * sizeof (double));
file.read(reinterpret_cast<char*>(&num), sizeof num);
num = num * -1;
file.seekp(0); // change mode to writing
file.seekp(i * sizeof (double));
file.write(reinterpret_cast<char*>(&num), sizeof num);
}
// after change
file.seekg(0, std::ios::end); // position cursor to the end
length_of_file = file.tellg();
number_of_elements = length_of_file / sizeof(double);
for (int i = 0; i < number_of_elements; i ) {
double num;
file.seekg(i * sizeof (double));
file.read(reinterpret_cast<char*>(&num), sizeof num);
std::cout << num << " ";
}
return 0;
}
OUTPUT: 1 2 3 4 5 6 7 8 9 10 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10
If I don't use std::ios::app
and make an empty file numbers.dat before running program, I would get correct output:
-1 -2 -3 -4 -5 -6 -7 -8 -9 -10
std::ios::app according to cpp reference means seek to the end of stream before each write
Is there any way to create a file with mode that would seek to the beginning of stream before each write?
Is there anyway to solve this without creating an empty file before running program?
- Note: It is not allowed to load file elements into an array or similar container data structure.
CodePudding user response:
Your mode is wrong in two ways. Firstly std::ios::app | std::ios::binary
does not allow you to read from the file, and secondly it means that all writes will be at the end of the file irrespective of the current position.
The -1
file position that you see means the seekg
call has failed, presumably because you tried to read from a file you hadn't opened with std::ios::in
.
You should use std::ios::in | std::ios::out | std::ios::binary
although this requires the file to exist before you open it, or you could use std::ios::in | std::ios::out | std::ios::trunc | std::ios::binary
but this will destroy any existing contents of the file.
BTW the repeated seekg
and seekp
aren't needed. You only need to set the position one time to change modes.