Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 130
1

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

24.05.2019, 14:57. Просмотров 419. Ответов 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
24.05.2019, 14:57
Ответы с готовыми решениями:

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

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

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

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

12
4598 / 3093 / 1294
Регистрация: 07.05.2019
Сообщений: 9,566
Записей в блоге: 1
24.05.2019, 15:17 2
Цитата Сообщение от 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
Сообщений: 130
24.05.2019, 15:37  [ТС] 3
Цитата Сообщение от 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
4598 / 3093 / 1294
Регистрация: 07.05.2019
Сообщений: 9,566
Записей в блоге: 1
24.05.2019, 15:49 4
[/QUOTE]
Цитата Сообщение от Pb-BASS Посмотреть сообщение
К сожалению и это не помогло
Здесь надо if (file2.eof()) break;, зачем сравнивать число, которое не начиталось?

Добавлено через 1 минуту
Для проверки просто начитай один файл и выведи eof() после каждого числа, посмотри, что там с последним
1
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 130
24.05.2019, 16:54  [ТС] 5
Цитата Сообщение от 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
4598 / 3093 / 1294
Регистрация: 07.05.2019
Сообщений: 9,566
Записей в блоге: 1
24.05.2019, 16:57 6
Цитата Сообщение от Pb-BASS Посмотреть сообщение
Но вроде как еще перед break необходимо последнее число (то что было большим в сравнении перед этим) записать в новый файл, а затем перейти уже к дозаписи остатка?
Зачем? Оно либо уже записано, либо запишется в остатке
0
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 130
24.05.2019, 17:15  [ТС] 7
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Зачем?
Не могу отловить все ситуации. Если убрать этой вставки пр определенных условиях (при каком-то сочетании последних значений) не дописываются значения.
0
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 130
25.05.2019, 20:47  [ТС] 8
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Зачем? Оно либо уже записано, либо запишется в остатке
А если такая ситуация: файлы одинаковой длины и два их последних значения проверяются при последней итерации. Они оба уже считаны в буфер, и следовательно, достигнут конец обоих фалов (дозаписи не будет в конце цикла проверок). Одно значение после это последней проверки идет в файл, а второе теряется.
0
4598 / 3093 / 1294
Регистрация: 07.05.2019
Сообщений: 9,566
Записей в блоге: 1
25.05.2019, 21:12 9
Цитата Сообщение от Pb-BASS Посмотреть сообщение
А если такая ситуация: файлы одинаковой длины и два их последних значения проверяются при последней итерации. Они оба уже считаны в буфер, и следовательно, достигнут конец обоих фалов (дозаписи не будет в конце цикла проверок). Одно значение после это последней проверки идет в файл, а второе теряется.
Само по себе здесь ничего не теряется. Если теряется, то это ты так сделал. Не делай, чтоб терялось и всё.
1
7 / 7 / 2
Регистрация: 21.02.2019
Сообщений: 130
25.05.2019, 21:35  [ТС] 10
Я попробовал такой вариант: не выходя из главного цикла , где проверка происходит, как только закончился один из фалов, дописать в результат второго файла. Но это почему-то то же плодит копии.
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
Грамотный. Безпорно.
16793 / 9692 / 1869
Регистрация: 27.09.2012
Сообщений: 24,052
Записей в блоге: 2
25.05.2019, 22:31 11
Просто оставлю здесь, вдруг пригодится.
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
Сообщений: 130
25.05.2019, 22:35  [ТС] 12
Цитата Сообщение от Croessmah Посмотреть сообщение
Просто оставлю здесь, вдруг пригодится.
Интересный вариант. Надо будет его рассмотреть поближе.
А в моем случае, я понял, что на возникновение копий значений влияют наличие знаков табуляций и переноса каретки в конце файла.
0
Грамотный. Безпорно.
16793 / 9692 / 1869
Регистрация: 27.09.2012
Сообщений: 24,052
Записей в блоге: 2
25.05.2019, 22:50 13
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
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
25.05.2019, 22:50

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

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

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

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

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.