7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134

Слияние двух отсортированных файлов

24.05.2019, 14:57. Показов 2038. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго все времени суток, господа.
Прошу помощи у того, кого не затруднит.
Пытаюсь реализовать алгоритм слияния 2-х отсортированных фалов.
Но постоянно получаю, мусор в конце слитого файла.
Привожу, на мой взгляд самый оптимальный вариант из мной опробованных:
Но в результате его работы, получаю, что последние два значения каждого из фалов записываются в результирующий файл дважды.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
void FilesMerging(string fileName1, string fileName2, string outName)
{
    ifstream file1;
    ifstream file2;
    file1.open(fileName1);
    file2.open(fileName2);
    if (file1.is_open() && file2.is_open()){
        ofstream fileOut;
        fileOut.open(outName);
        if (fileOut.is_open()){
            bool stepFile1 = true; //флаг, указывающий на то, что надо прочитать следующее значение из 1-го файла
            bool stepFile2 = true; //аналогично но для 2-го файла
            char buff1[20];
            char buff2[20];
            int value1;
            int value2;
            int counter = 0;
            bool stop = false;
            while (!stop){
                //если необходимо прочитать значение из 1-го файла
                if (stepFile1){
                    file1 >> buff1;
                    value1 = atoi(buff1);
                }
                //а если необходимо прочитать значение из 2-го файла
                if (stepFile2){
                    file2 >> buff2;
                    value2 = atoi(buff2);
                }
                //сравниваем и меньшее или равное записываем в новый файл
                if (value1 < value2){
                    stepFile1 = true; //если в 1-м фале было наименьшее значение, то из 1-го файла надо будет прочитать следующее
                    stepFile2 = false; //а из 2-го не надо
                    fileOut << value1; //записывам его
                }
                else{
                    stepFile1 = false;
                    stepFile2 = true;                   
                    fileOut << value2;
                }
 
                if ((counter + 1) % 10 == 0) fileOut << "\n";
                else fileOut << "\t";
                counter++;
                //если необходимо прочитать значение из 1-го фала, а он закончился, или же из 2-го, а он закончился
                if ((stepFile1 && file1.eof()) || (stepFile2 && file2.eof())) {
                    stop = true;//останавливаем цикл сравнения
                }
            }
            
            //Если один из фалов был больше другого, то его надо дописать в конец нового
            if (!file2.eof()){
                while (!file2.eof()){
                    file2 >> buff2;
                    value2 = atoi(buff2);
                    fileOut << value2;
                    if ((counter + 1) % 10 == 0) fileOut << "\n";
                    else fileOut << "\t";
                    counter++;
                }
            }
            if (!file1.eof()){
                while (!file1.eof()){
                    file1 >> buff1;
                    value1 = atoi(buff1);
                    fileOut << value1;
                    if ((counter + 1) % 10 == 0) fileOut << "\n";
                    else fileOut << "\t";
                    counter++;
                }
            }   
            file1.close();
            file2.close();
            fileOut.close();
        } //end if (fileOut.is_open())
    }// end if (file1.is_open() && file2.is_open())
}
Подскажите, где я прокололся с логикой работы

Добавлено через 13 минут
Да, вместо
C++
1
file1.open(fileName1);
Должно быть
C++
1
file1.open(fileName1.c_str());
и т.д.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.05.2019, 14:57
Ответы с готовыми решениями:

Слияние двух отсортированных списков
Напишите функцию List&amp; merge(List&amp; L1, List&amp; L2), добавляю- щую к упорядоченному списку L1 также упорядоченный список L2 и ...

Слияние двух отсортированных массивов в третий
Здравствуйте всем! Только начинаю изучать языки программирования. Помогите найти ошибку. Необходимо создать два массива, слить и...

Слияние двух файлов по алгоритму: цифра вставляется после двух символов
#include &lt;iostream&gt; #include &lt;io.h&gt; #include &lt;stdio.h&gt; #include &lt;windows.h&gt; #include &lt;string.h&gt; #include &lt;conio.h&gt; using...

12
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
24.05.2019, 15:17
Цитата Сообщение от Pb-BASS Посмотреть сообщение
Но постоянно получаю, мусор в конце слитого файла.
Привожу, на мой взгляд самый оптимальный вариант из мной опробованных:
Но в результате его работы, получаю, что последние два значения каждого из фалов записываются в результирующий файл дважды.
По-моему, ты eof неправильно проверяешь. Если ты сделал file1 >> buff1;, а строки в файле нет, то буфер не изменится.
Здесь надо, наверное
C++
1
2
3
4
5
6
        if (stepFile1){
                    file1 >> buff1;
if (file1.eof())
    break;
                    value1 = atoi(buff1);
                }
1
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
24.05.2019, 15:37  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
По-моему, ты eof неправильно проверяешь.
Мысль я уловил, но ведь если я сделаю
C++
1
 if (file1.eof()) break;
, то цикл прекратится не дойдя до проверки значений value1 и value2

Добавлено через 4 минуты
Но исходя из это иде, переписал while следующим образом
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
            while (!stop){
                //если необходимо прочитать значение из 1-го файла
                if (stepFile1){
                    file1 >> buff1;
                    if (file1.eof()) stop = true;
                    value1 = atoi(buff1);
                }
                //а если необходимо прочитать значение из 2-го файла
                if (stepFile2){
                    file2 >> buff2;
                    if (file2.eof()) stop = true;
                    value2 = atoi(buff2);
                }
                //сравниваем и меньшее или равное записываем в новый файл
                if (value1 < value2){
                    stepFile1 = true; //если в 1-м фале было наименьшее значение, то из 1-го файла надо будет прочитать следующее
                    stepFile2 = false; //а из 2-го не надо
                    fileOut << value1; //записывам его
                    if ((counter + 1) % 10 == 0) fileOut << "\n";
                    else fileOut << "\t";
                    counter++;
                    if (stop) {
                        fileOut << value2;
                        if ((counter + 1) % 10 == 0) fileOut << "\n";
                        else fileOut << "\t";
                        counter++;
                    }
                }
                else{
                    stepFile1 = false;
                    stepFile2 = true;                   
                    fileOut << value2;
                    if ((counter + 1) % 10 == 0) fileOut << "\n";
                    else fileOut << "\t";
                    counter++;
                    if (stop) {
                        fileOut << value1;
                        if ((counter + 1) % 10 == 0) fileOut << "\n";
                        else fileOut << "\t";
                        counter++;
                    }
                }
К сожалению и это не помогло
0
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
24.05.2019, 15:49
[/QUOTE]
Цитата Сообщение от Pb-BASS Посмотреть сообщение
К сожалению и это не помогло
Здесь надо if (file2.eof()) break;, зачем сравнивать число, которое не начиталось?

Добавлено через 1 минуту
Для проверки просто начитай один файл и выведи eof() после каждого числа, посмотри, что там с последним
1
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
24.05.2019, 16:54  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
зачем сравнивать число, которое не начиталось?
Да, точно.
Но вроде как еще перед break необходимо последнее число (то что было большим в сравнении перед этим) записать в новый файл, а затем перейти уже к дозаписи остатка?

Если не сложно, можешь глянуть вот на эту версию:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
        ifstream file1;
    ifstream file2;
    file1.open(fileName1.c_str());
    file2.open(fileName2.c_str());
    if (file1.is_open() && file2.is_open()){
        ofstream fileOut;
        fileOut.open(outName.c_str());
        if (fileOut.is_open()){
            bool stepFile1 = true; //флаг, указывающий на то, что надо прочитать следующее значение из 1-го файла
            bool stepFile2 = true; //аналогично но для 2-го файла
            char buff1[20];
            char buff2[20];
            int value1;
            int value2;
            int counter = 0;
            bool stop = false;
            while (true){
                //если необходимо прочитать значение из 1-го файла
                if (stepFile1){
                    file1 >> buff1;
                    if (file1.eof()){ 
                        fileOut << value2;
                        if ((counter + 1) % 10 == 0) fileOut << "\n";
                        else fileOut << "\t";                       
                        break;
                    }
                    value1 = atoi(buff1);
                }
                //а если необходимо прочитать значение из 2-го файла
                if (stepFile2){
                    file2 >> buff2;
                    if (file2.eof()) {  
                        fileOut << value1;  
                        if ((counter + 1) % 10 == 0) fileOut << "\n";
                        else fileOut << "\t";       
                        break;
                    }
                    value2 = atoi(buff2);
                }
                //сравниваем и меньшее или равное записываем в новый файл
                if (value1 < value2){
                    stepFile1 = true; //если в 1-м фале было наименьшее значение, то из 1-го файла надо будет прочитать следующее
                    stepFile2 = false; //а из 2-го не надо
                    fileOut << value1; //записывам его
                }
                else{
                    stepFile1 = false;
                    stepFile2 = true;                   
                    fileOut << value2;
                }
                if ((counter + 1) % 10 == 0) fileOut << "\n";
                else fileOut << "\t";
                counter++;
            }
            
            //Если один из фалов был больше другого, то его надо дописать в конец нового
            if (!file2.eof()){
                while (true){
                    file2 >> buff2;
                    if (file2.eof()) break;                 
                    value2 = atoi(buff2);
                    fileOut << value2;
                    
                    if ((counter + 1) % 10 == 0) fileOut << "\n";
                    else fileOut << "\t";
                    counter++;
                }
            }
            if (!file1.eof()){
                while (true){
                    file1 >> buff1;
                    if (file1.eof()) break;
                    value1 = atoi(buff1);
                    fileOut << value1;
                    
                    if ((counter + 1) % 10 == 0) fileOut << "\n";
                    else fileOut << "\t";
                    counter++;
                }
            }   
            file1.close();
            file2.close();
            fileOut.close();
        } //end if (fileOut.is_open())
    }// end if (file1.is_open() && file2.is_open())
0
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
24.05.2019, 16:57
Цитата Сообщение от Pb-BASS Посмотреть сообщение
Но вроде как еще перед break необходимо последнее число (то что было большим в сравнении перед этим) записать в новый файл, а затем перейти уже к дозаписи остатка?
Зачем? Оно либо уже записано, либо запишется в остатке
0
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
24.05.2019, 17:15  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Зачем?
Не могу отловить все ситуации. Если убрать этой вставки пр определенных условиях (при каком-то сочетании последних значений) не дописываются значения.
0
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
25.05.2019, 20:47  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Зачем? Оно либо уже записано, либо запишется в остатке
А если такая ситуация: файлы одинаковой длины и два их последних значения проверяются при последней итерации. Они оба уже считаны в буфер, и следовательно, достигнут конец обоих фалов (дозаписи не будет в конце цикла проверок). Одно значение после это последней проверки идет в файл, а второе теряется.
0
6771 / 4565 / 1843
Регистрация: 07.05.2019
Сообщений: 13,726
25.05.2019, 21:12
Цитата Сообщение от Pb-BASS Посмотреть сообщение
А если такая ситуация: файлы одинаковой длины и два их последних значения проверяются при последней итерации. Они оба уже считаны в буфер, и следовательно, достигнут конец обоих фалов (дозаписи не будет в конце цикла проверок). Одно значение после это последней проверки идет в файл, а второе теряется.
Само по себе здесь ничего не теряется. Если теряется, то это ты так сделал. Не делай, чтоб терялось и всё.
1
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
25.05.2019, 21:35  [ТС]
Я попробовал такой вариант: не выходя из главного цикла , где проверка происходит, как только закончился один из фалов, дописать в результат второго файла. Но это почему-то то же плодит копии.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
ifstream file1;
    ifstream file2;
    file1.open(fileName1.c_str());
    file2.open(fileName2.c_str());
    if (file1.is_open() && file2.is_open()){
        ofstream fileOut;
        fileOut.open(outName.c_str());
        if (fileOut.is_open()){
            bool stepFile1 = true; //флаг, указывающий на то, что надо прочитать следующее значение из 1-го файла
            bool stepFile2 = true; //аналогично но для 2-го файла
            int value1;
            int value2;
            int counter = 0;
            bool stop = false;
            while (true){
                char buff[20];
                //если необходимо прочитать значение из 1-го файла
                if (stepFile1){                 
                    if (file1.eof()){   
                        fileOut << value2;
                        if ((counter + 1) % 10 == 0) fileOut << "\n";
                        else fileOut << "\t";   
                        counter++;
                        while(!file2.eof()){
                            file2 >> buff;
                            value2 = atoi(buff);
                            fileOut << value2;
                            if ((counter + 1) % 10 == 0) fileOut << "\n";
                            else fileOut << "\t";
                            counter++;  
                        }
                        break;
                    }
                    file1 >> buff;
                    value1 = atoi(buff);
                }
                //а если необходимо прочитать значение из 2-го файла
                if (stepFile2){                 
                    if (file2.eof()){   
                        fileOut << value1;
                        if ((counter + 1) % 10 == 0) fileOut << "\n";
                        else fileOut << "\t";   
                        counter++;
                        while(!file1.eof()){
                            file1 >> buff;
                            value1 = atoi(buff);
                            fileOut << value1;
                            if ((counter + 1) % 10 == 0) fileOut << "\n";
                            else fileOut << "\t";
                            counter++;  
                        }
                        break;
                    }
                    file2 >> buff;
                    value2 = atoi(buff);
                }
                //сравниваем и меньшее или равное записываем в новый файл
                if (value1 < value2){
                    stepFile1 = true; //если в 1-м фале было наименьшее значение, то из 1-го файла надо будет прочитать следующее
                    stepFile2 = false; //а из 2-го не надо
                    fileOut << value1; //записывам его
                }
                else{
                    stepFile1 = false;
                    stepFile2 = true;                   
                    fileOut << value2;
                }
                if ((counter + 1) % 10 == 0) fileOut << "\n";
                else fileOut << "\t";
                counter++;
            }
            file1.close();
            file2.close();
            fileOut.close();
        } //end if (fileOut.is_open())
    }// end if (file1.is_open() && file2.is_open())
Добавлено через 15 минут
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Не делай, чтоб терялось и всё.
Ну таки что бы не терялось, я не вижу другого способа, как сразу его записать в новый файл.
0
Неэпический
 Аватар для Croessmah
18128 / 10712 / 2064
Регистрация: 27.09.2012
Сообщений: 27,002
Записей в блоге: 1
25.05.2019, 22:31
Просто оставлю здесь, вдруг пригодится.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <fstream>
#include <iostream>
#include <algorithm>
#include <iterator>
 
 
int main()
{
    std::ifstream in1("input1.txt");
    std::ifstream in2("input2.txt");
    std::ofstream out("output.txt");
    if (!(in1.is_open() && in2.is_open() && out.is_open())) {
        std::cerr << "error\n";
        return 1;
    }
    std::merge(
        std::istream_iterator<int>(in1), {},
        std::istream_iterator<int>(in2), {},
        std::ostream_iterator<int>(out, " ")
    );
}
1
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 134
25.05.2019, 22:35  [ТС]
Цитата Сообщение от Croessmah Посмотреть сообщение
Просто оставлю здесь, вдруг пригодится.
Интересный вариант. Надо будет его рассмотреть поближе.
А в моем случае, я понял, что на возникновение копий значений влияют наличие знаков табуляций и переноса каретки в конце файла.
0
Неэпический
 Аватар для Croessmah
18128 / 10712 / 2064
Регистрация: 27.09.2012
Сообщений: 27,002
Записей в блоге: 1
25.05.2019, 22:50
Pb-BASS, вот еще, только не проверял
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <fstream>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <iomanip>
 
int main()
{
    std::ifstream in1("input1.txt");
    std::ifstream in2("input2.txt");
    std::ofstream out("output.txt");
    if (!(in1.is_open() && in2.is_open() && out.is_open())) {
        std::cerr << "error\n";
        return 1;
    }
    
 
    std::ifstream * front = &in1;
    std::ifstream * back = &in2;
 
    int front_value;
    int back_value;
    if (!(*back >> back_value)) {
        out << std::ws(*front).rdbuf();
        return 0;
    }
    while (*front >> front_value) {
        if (back_value < front_value) {
            std::swap(front, back);
            std::swap(front_value, back_value);
        }
        out << front_value << " ";  
    }  
    out << back_value << " " << std::ws(*back).rdbuf();
}
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
25.05.2019, 22:50
Помогаю со студенческими работами здесь

Слияние отсортированных массивов.
задача: есть двумерный целочисленный массив n на n в котором каждая строка отсортирована по возрастанию. надо слить его в одномерный...

Сравнение двух отсортированных массивов
Есть задача: Даны два массива a1≤a2≤⋯≤an и b1≤b2≤⋯≤bm. Нужно посчитать кол-во пар элементов этих массивов, для которых ...

Слияние 2х векторов из 2х файлов
Помогите написать программу Пожалуйста .Программа создает два вектора a и b из двух файлов. Функция слияния добавляет в вектор a из...

Чересстрочное слияние файлов
в проге через консоль Производный класс обеспечивает черезстрочное слияние двух текстовых файлов, количество строк которых может...

Файл: Слияние файлов
Есть два текста, в которых записано последовательности положительных целых чисел по возрастанию. записать в Третий текст последовательность...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

Новые блоги и статьи
Unity 4D
GameUnited 13.06.2025
Четырехмерное пространство. . . Звучит как что-то из научной фантастики, правда? Однако для меня, как разработчика со стажем в игровой индустрии, четвертое измерение давно перестало быть абстракцией из. . .
SSE (Server-Sent Events) в ASP.NET Core и .NET 10
UnmanagedCoder 13.06.2025
Кажется, Microsoft снова подкинула нам интересную фичу в новой версии фреймворка. Работая с превью . NET 10, я наткнулся на нативную поддержку Server-Sent Events (SSE) в ASP. NET Core Minimal APIs. Эта. . .
С днём независимости России!
Hrethgir 13.06.2025
Решил побеседовать, с утра праздничного дня, с LM о завоеваниях. То что она написала о народе, представителем которого я являюсь сам сначала возмутило меня, но дальше только смешило. Это чисто. . .
Лето вокруг.
kumehtar 13.06.2025
Лето вокруг. Наполненное бурями и ураганами событий. На фоне магии Жизни, священной и вечной, неумелой рукой человека рисуется панорама душевного непокоя. Странные серые краски проникают и. . .
Популярные LM модели ориентированы на увеличение затрат ресурсов пользователями сгенерированного кода (грязь -заслуги чистоплюев).
Hrethgir 12.06.2025
Вообще обратил внимание, что они генерируют код (впрочем так-же ориентированы разработчики чипов даже), чтобы пользователь их использующий уходил в тот или иной убыток. Это достаточно опытные модели,. . .
Топ10 библиотек C для квантовых вычислений
bytestream 12.06.2025
Квантовые вычисления - это та область, где теория встречается с практикой на границе наших знаний о физике. Пока большая часть шума вокруг квантовых компьютеров крутится вокруг языков высокого уровня. . .
Dispose и Finalize в C#
stackOverflow 12.06.2025
Работая с C# больше десяти лет, я снова и снова наблюдаю одну и ту же историю: разработчики наивно полагаются на сборщик мусора, как на волшебную палочку, которая решит все проблемы с памятью. Да,. . .
Повышаем производительность игры на Unity 6 с GPU Resident Drawer
GameUnited 11.06.2025
Недавно копался в новых фичах Unity 6 и наткнулся на GPU Resident Drawer - штуку, которая заставила меня присвистнуть от удивления. По сути, это внутренний механизм рендеринга, который автоматически. . .
Множества в Python
py-thonny 11.06.2025
В Python существует множество структур данных, но иногда я сталкиваюсь с задачами, где ни списки, ни словари не дают оптимального решения. Часто это происходит, когда мне нужно быстро проверять. . .
Работа с ccache/sccache в рамках C++
Loafer 11.06.2025
Утилиты ccache и sccache занимаются тем, что кешируют промежуточные результаты компиляции, таким образом ускоряя последующие компиляции проекта. Это означает, что если проект будет компилироваться. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru