Дан бинарный файл, заполненый действительными числами. Нужно без другого файла переставить положительные числа в начало, а все остальные в конец

Сказали, что код неправильный, помогите исправить

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <conio.h>
#include <string>
#include <fstream>
using namespace std;
int main() {
    FILE* f1;
    int  i = 0;
    double arr[10] = {-24.4, 12.5, 34.6, -1.5, -4.7, -13.5, -2.6, 12.5, 3.9, -0.5};
    if ((f1 = fopen("1.dat", "rb")) == 0)
    {
        perror("Can't open file!");
    }
    fscanf(f1, "%lf%lf%lf%lf%lf%lf%lf%lf%lf%lf", &arr[0], &arr[1], &arr[2], &arr[3], &arr[4], &arr[5], &arr[6], &arr[7], &arr[8], &arr[9], &arr[10]);
    fclose(f1);
    for (int i = 0; 1 < 10; i++)
    {
        if (arr[i] > 0)
        {
            for (int j = 0; j < i; j++)
            {
                if (arr[j] < 0)
                {
                    int x = arr[i];
                    arr[i] = arr[j];
                    arr[j] = x;
                }
            }
        }
    }
    f1 = fopen("1.dat", "wb+");
    fwrite(&arr[10], sizeof(float), 10, f1);
    fclose(f1);
}

Ответы (1 шт):

Автор решения: Harry

Как я понимаю, от вас хотят что-то типа этого — без затягивания всего файла в память... Просто иначе никакие seek/tell не нужны в принципе...

#include <iostream>
#include <iomanip>
#include <random>
#include <fstream>

using namespace std;

int main()
{
    { // Первая часть Марлезонского балета - создание файла
        default_random_engine u{random_device{}()};
        size_t size = uniform_int_distribution<>{100,20000}(u);
        ofstream out("data",ios::binary);
        for(size_t i = 0; i < size; ++i)
        {
            double d = uniform_real_distribution<>{-1e6,1e6}(u);
            out.write(reinterpret_cast<char*>(&d),sizeof(d));
        }
    }
    { // Вторая часть Марлезонского балета - вывод файла
        ifstream in("data",ios::binary);
        cout << setprecision(10);
        for(double d; in.read(reinterpret_cast<char*>(&d),sizeof(d));)
            cout << d << " ";
        cout << "\n----------\n\n";
    }
    { // Третья часть Марлезонского балета - обработка файла
        fstream f("data",ios::binary|ios::in|ios::out);
        auto b = f.tellg();
        f.seekg(-int(sizeof(double)),ios::end);
        auto e = f.tellg();

        do {
            double db, de;
            f.seekg(b);
            while(b < e && f.read(reinterpret_cast<char*>(&db),sizeof(double)) && db > 0.0)
                b = f.tellg();
            while(b < e)
            {
                f.seekg(e);
                if (!f.read(reinterpret_cast<char*>(&de),sizeof(double))) break;
                if (de > 0.0) break;
                e -= sizeof(double);
            }
            if (b < e)
            {
                f.seekp(b);
                f.write(reinterpret_cast<char*>(&de),sizeof(double));
                b += sizeof(double);
                f.seekp(e);
                f.write(reinterpret_cast<char*>(&db),sizeof(double));
                e -= sizeof(double);
            }
        } while(b < e);
    }
    { // Четвертая часть Марлезонского балета - вывод файла
        ifstream in("data",ios::binary);
        cout << setprecision(10);
        for(double d; in.read(reinterpret_cast<char*>(&d),sizeof(d));)
            cout << d << " ";
        cout << "\n----------\n\n";
    }
}

Если можно весь файл всосать в память - еще проще:

{ // Третья часть Марлезонского балета - обработка файла
    fstream f("data",ios::binary|ios::in|ios::out);
    f.seekg(0,ios::end);
    auto e = f.tellg();
    vector<double> v(e/sizeof(double));
    f.seekg(0,ios::beg);
    f.read(reinterpret_cast<char*>(v.data()),e);
    partition(v.begin(),v.end(),[](double d){ return d > 0; });
    f.seekp(0,ios::beg);
    f.write(reinterpret_cast<char*>(v.data()),e);
}
→ Ссылка