Why I am having a weird mistake while trying to read a file from the end to the middle, using fin2.seekg(-2 * sizeof(int), ios::cur); ? no string

Thanks for paying attention to my question.
Recently, I’ve started working with c++ files and now I’m having a couple of questions about reading the file from the end to the middle.

My task is to read my two files from the end to the middle and from the beginning to the middle with no arrays and string library used. After that, if the sum is positive, write that to the third file.
I would appreciate if you could read my code and explain my mistake.

Here’s my code down below:

void calculatingSum(const char* fname, const char* fname2, const char* fname3) {
  

    int size1 = returnSize(fname);
    int size2 = returnSize(fname2);
    int number = 0;

    ifstream fin1;
    ifstream fin2;
    ofstream fout3;

    fout3.open(fname3,ios::binary);
    if (size2 > size1) {
        fin1.open(fname,ios::binary);
        fin2.open(fname2, ios::binary);

    }
    else
    {
        swap(size1, size2);
        fin1.open(fname2, ios::binary);
        fin2.open(fname, ios::binary);
    }
    int posMedian1 = size1 / sizeof(int)/2;
    if (size1 % 2 == 1) {
        posMedian1 += 2;
    }

    int posMedian2 = size2 / sizeof(int) / 2;
    if (size2 % 2 == 1) {
        posMedian2 += 2;
    }
    fin1.seekg(-1* sizeof(int), ios::end);
    fin2.seekg(-1 *sizeof(int),ios::end);
    int a, b;
    bool flag = false;
    while (fin2.tellg() >= posMedian2) {
        fin2.read((char*)&a, sizeof(number));
        fin2.seekg(-2 * sizeof(int), ios::cur);
        if (fin1.tellg() >= posMedian1) {
            fin1.read((char*)&b, sizeof(number));
            fin1.seekg(-2 * sizeof(int), ios::cur);
            
          
        }
        else {
            if (flag == false) {
                flag = true;
                fin1.seekg(0);

            }
            if (fin1.tellg() == posMedian1)
                break;
            fin1.read((char*)&b, sizeof(number));

        }int c = a + b;
        cout << "c" << c << endl;
        if (c > 0)
            fout3.write((char*)&c, sizeof(number)); 

        
        fin1.seekg(0);
        fin2.seekg(0);
        int d, e;
        while (fin2.tellg() <= posMedian2) {
            fin2.read((char*)&d, sizeof(number));
             fin2.seekg(2* sizeof(int), ios::cur);
          
            if (fin1.tellg() <= posMedian1) {
                fin1.read((char*)&e, sizeof(number));
                 fin1.seekg(2* sizeof(int), ios::cur);
              
            }
            else {
                if (flag == false) {
                    flag = true;
                    fin1.seekg(0,ios::end);

                }
                if (fin1.tellg() == posMedian1)
                    break;
                fin1.read((char*)&e, sizeof(number));

            }int f = e + d;
            cout << "f" << f << endl;
            if (f > 0)
                fout3.write((char*)&f, sizeof(number));
        }

    }
   
    fin1.close();
    fin2.close();
 }

the main purpose of fin2.seekg(-2 * sizeof(int), ios::cur); it’s to read the element from the end,every time looking for the previous element, but i’m getting mistakes,when i’m trying to do this..
the image of an error list

>Solution :

Instead of

fin2.seekg(-2 * sizeof(int), ios::cur);

do

fin2.seekg(-2 * static_cast<ifstream::off_type>(sizeof(int)), ios::cur);

where off_type is the offset type of the stream. Otherwise, -2 will be cast to size_t, which is the type of sizeof, and which is unsigned – so the negative value -2 will become a very large value instead.

This implicit conversion from int to size_t can be demostrated like this:

#include <fstream>
#include <iostream>

int main() {
    size_t x = sizeof(int);

    std::cout << -2 * x << '\n';            // not what you'd expect

    // ... but this does the right thing:
    std::cout << -2 * static_cast<std::ifstream::off_type>(x) << '\n';
}

Possible output:

18446744073709551608
-8

Since you do this operation a lot, a helper function would simplify it a bit:

template<class T>
T& seekg(T& stream, long steps, size_t obj_size) {
    stream.seekg(steps * static_cast<typename T::off_type>(obj_size),
                 std::ios::cur);
    return stream;
}

Seeking would then simply be:

seekg(fin2, -2, sizeof(int));

Leave a Reply