Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.86/35: Рейтинг темы: голосов - 35, средняя оценка - 4.86
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
1

Как ускорить работу с файлами?

31.08.2016, 10:51. Показов 7205. Ответов 56
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Предполагается, что программа будет работать с файлами размера 300-500МБ. Эти обычные функции работают слишком медленно. Может быть стоит использовать чистый С, например?
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
#include <fstream>
#include <iostream>
#include <string>
#include <Windows.h>
using namespace std;
 
void merge(ifstream &f1, ifstream &f2, ofstream &fRes)
{
    string one[3], two[3];
    while (!f1.eof())
    {
        getline(f1, one[0], ':');
        getline(f1, one[1], ':');
        getline(f1, one[2]);
        
        f2.seekg(0);
        while (!f2.eof())
            
        {
            getline(f2, two[0], ':');
            getline(f2, two[1], ':');
            getline(f2, two[2]);
            if (one[1] == two[0] && one[2] == two[1])
                fRes << one[0] << ':' << two[2] << endl;
        }
    }
}
 
int main() 
{
    string file1path, file2path, fileResultPath;
    ifstream file1, file2;
    ofstream fileResult;
 
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
    cout << "Путь к первому файлу > ";
    getline(cin, file1path);
    cout << "Путь ко второму файлу > ";
    getline(cin, file2path);
    cout << "Путь к файлу для записи результата > ";
    getline(cin, fileResultPath);
 
    file1.open(file1path);
    file2.open(file2path);
    fileResult.open(fileResultPath);
 
    if (file1.is_open() && file2.is_open())
    {
        merge(file1, file2, fileResult);
        cout << "Готово!\n";
    }
    else
        cout << "Проблема с открытием файлов!\n";
 
    file1.close();
    file2.close();
    fileResult.close();
 
    system("pause");
    return 0;
}
1
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
31.08.2016, 10:51
Ответы с готовыми решениями:

Как ускорить работу?
Прога ещё не доработана, сейчас интересует именно графический режим, когда нажимается клавиша 1-4...

Подскажите пожалуйста как ускорить работу программы!
Есть задача :&quot;Во входном файле (вы можете читать данные из файла input.txt) записан текст. Словом...

Можно ли как нибудь ускорить работу цикла for?
Подскажите пожалуйста - можно ли как нибудь ускорить работу цикла for? Заранее сильно благодарен!

Как ускорить работу (поиск вхождений подстроки)?
//подсчет kf int NumberKF(string &amp;P, vector&lt;string&gt; &amp; F, const int f){ int kf =0; for(size_t i...

56
nd2
3437 / 2816 / 1249
Регистрация: 29.01.2016
Сообщений: 9,426
31.08.2016, 23:34 21
Author24 — интернет-сервис помощи студентам
Цитата Сообщение от Керра Посмотреть сообщение
Тогда получается что нужно посимвольно?
Не нужно. По ссылке об этом написано.
1
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
31.08.2016, 23:46  [ТС] 22
Может быть дело в том, что уже почти полночь, но я не понимаю с чего он ругается. Я сделала вот так вот:
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <iostream>
#include <string>
#include <Windows.h>
#include <vector>
#include <algorithm>
using namespace std;
 
#define DEBUG
 
struct Part {
    char id2[10], name[20];
    bool operator<(char *r) const;
    bool operator>(char *r) const;
    bool operator==(char *r) const;
};
 
bool Part::operator<(char *r) const {
    return (strcmp(id2, r) < 0);
}
 
bool Part::operator>(char *r) const {
    return (strcmp(id2, r) > 0);
}
 
bool Part::operator==(char *r) const {
    return (strcmp(id2, r) == 0);
}
 
struct Line {
    char id1[10];
    vector<Part> vals;
    bool operator<(char *r) const;
    bool operator>(char *r) const;
    bool operator==(char *r) const;
};
 
bool Line::operator<(char *r) const {
    return (strcmp(id1, r) < 0);
}
 
bool Line::operator>(char *r) const {
    return (strcmp(id1, r) > 0);
}
 
bool Line::operator==(char *r) const {
    return (strcmp(id1, r) == 0);
}
 
 
class LineSorter {
public:
    void operator()(Line &l) {
        sort(l.vals.begin(), l.vals.end());
    }
};
 
vector<Line> parse(FILE *f) {
    vector<Line> v;
    char name[20], id1[10], id2[10];
    bool was;
 
    while (!feof(f)) {
        fscanf_s(f, "%s:%s:%s", &name, &id1, &id2);
#ifdef DEBUG
        cout << '[' << name << "] [" << id1 << "] [" << id2 << "]\n";
#endif
        was = false;
        for (vector<Line>::iterator it = v.begin(); it != v.end(); it++)
            if (strcmp(it->id1, id1) == 0) {
                it->vals.push_back(Part());
                strcpy_s(it->vals.back().id2, id2);
                strcpy_s(it->vals.back().name, name);
                was = true;
                break;
            }
        if (!was) {
            v.push_back(Line());
            strcpy_s(v.back().id1, id1);
            v.back().vals.push_back(Part());
            strcpy_s(v.back().vals.back().id2, id2);
            strcpy_s(v.back().vals.back().name, name);
        }
    }
    sort(v.begin(), v.end());
    for_each(v.begin(), v.end(), LineSorter());
#ifdef DEBUG
    system("pause");
#endif
    return v;
}
 
bool find(vector<Line> v, char *id1, char *id2, Line &found) {
    pair<vector<Line>::iterator, vector<Line>::iterator> itPair1 =
        equal_range(v.begin(), v.end(), id1);
    if (itPair1.first != v.end()) {
        pair<vector<Part>::iterator, vector<Part>::iterator> itPair2 =
            equal_range(itPair1.first->vals.begin(), itPair1.first->vals.end(), id2);
        if (itPair2.first != itPair1.first->vals.end()) {
            strcpy_s(found.id1, id1);
            found.vals.clear();
            found.vals.push_back(Part());
            strcpy_s(found.vals.back().id2, id2);
            strcpy_s(found.vals.back().name, itPair2.first->name);
            return true;
        }
    }
    return false;
}
 
void mergeFiles(FILE *f1, FILE *f2, FILE *fRes) {
    /*string one[3], two[3];
    while (!f1.eof() && !f2.eof()) {
        getline(f1, one[0], ';');
        getline(f1, one[1], ';');
        getline(f1, one[2]);
        getline(f2, two[0], ';');
        getline(f2, two[1], ';');
        getline(f2, two[2]);
        if (one[1] == two[0] && one[2] == two[1])
            fRes << one[0] << ';' << two[2] << endl;
    }*/
    vector<Line> v = parse(f1);
    char name[20], id1[10], id2[10];
    Line found;
    while (!feof(f2)) {
        fscanf_s(f2, "%s:%s:%s", &id1, &id2, &name);
        if (find(v, id1, id2, found))
            fprintf(f2, "%s:%s\n", found.vals.back().name, name);
    }
}
 
int main() {
    string file1path, file2path, fileResultPath;
    FILE *file1, *file2, *fileResult;
 
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
    cout << "Путь к первому файлу > ";
    getline(cin, file1path);
    cout << "Путь ко второму файлу > ";
    getline(cin, file2path);
    cout << "Путь к файлу для записи результата > ";
    getline(cin, fileResultPath);
 
    file1 = fopen(file1path.c_str(), "rt");
    file2 = fopen(file2path.c_str(), "rt");
    fileResult = fopen(fileResultPath.c_str(), "wt");
 
    if (file1 != NULL && file2 != NULL) {
        mergeFiles(file1, file2, fileResult);
        fclose(file1);
        fclose(file2);
        fclose(fileResult);
        cout << "Готово!\n";
    }
    else
        cout << "Проблема с открытием файлов!\n";
 
    system("pause");
    return 0;
}
А он ругается вот так вот:
Код
1>------ Сборка начата: проект: Work, Конфигурация: Release Win32 ------
1>  main.cpp
1>D:\Programs\Visual Studio 2013 Express\VC\include\algorithm(2618): error C2893: Сбой при специализации функции-шаблона "unknown-type std::less<void>::operator ()(_Ty1 &&,_Ty2 &&) const"
1>          Со следующими аргументами шаблона:
1>          "_Ty1=char *const &"
1>          "_Ty2=Line &"
1>          D:\Programs\Visual Studio 2013 Express\VC\include\algorithm(2642): см. ссылку на создание экземпляров функции шаблон при компиляции "std::pair<Line *,Line *> std::_Equal_range<Line*,_Ty,__w64 int,_Pr>(_FwdIt,_FwdIt,const _Ty &,_Pr,_Diff *)"
1>          with
1>          [
1>              _Ty=char *
1>  ,            _Pr=std::less<void>
1>  ,            _FwdIt=Line *
1>  ,            _Diff=__w64 int
1>          ]
1>          D:\Programs\Visual Studio 2013 Express\VC\include\algorithm(2655): см. ссылку на создание экземпляров функции шаблон при компиляции "std::pair<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Line>>>,std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Line>>>> std::equal_range<_FwdIt,_Ty,std::less<void>>(_FwdIt,_FwdIt,const _Ty &,_Pr)"
1>          with
1>          [
1>              _FwdIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Line>>>
1>  ,            _Ty=char *
1>  ,            _Pr=std::less<void>
1>          ]
1>          main.cpp(96): см. ссылку на создание экземпляров функции шаблон при компиляции "std::pair<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Line>>>,std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Line>>>> std::equal_range<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Line>>>,char*>(_FwdIt,_FwdIt,const _Ty &)"
1>          with
1>          [
1>              _FwdIt=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<Line>>>
1>  ,            _Ty=char *
1>          ]
========== Сборка: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========
В чем дело?..
0
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
01.09.2016, 00:01 23
Керра, Зачем откапали char*? в первом посте все было чинно, красиво и благородно на std::string.

Не по теме:

Слишком хорошо живете чтоли? :)

0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.09.2016, 00:19 24
C++
1
2
3
4
5
6
struct Part {
    char id2[10], name[20];
    bool operator<(char *r) const;
    bool operator>(char *r) const;
    bool operator==(char *r) const;
};
Почему оператор относительно char* а не Pair ?
C++
1
    bool Pair::operator<(const Pair& p) const;
C++
1
fscanf_s(f, "%s:%s:%s", &name, &id1, &id2);
Почему не читать сразу в поля структуры? Без лишнего копирования.
vector- ру стоит сразу делать reserve() (или даже сразу resize())

Керра, Поспешили вы портить код используя Си для начала стоило убрать seekg и возможно распоточить
может этого было бы достаточно.

Добавлено через 1 минуту
Цитата Сообщение от Nosey Посмотреть сообщение
Да, про память забыл сказать, после парсинга строки в мапу - строку убиваем, за ненадобностью, или можно использовать [boost|std]::string_view.
Жрем память и ресурсы копированием.
Еще раз задача- ускорить и не получить бед.аллок.

Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от Nosey Посмотреть сообщение
Но тогда неубодно в одну функцию влезть
Для set есть алгоритмы.

2
Nosey
01.09.2016, 00:30
  #25

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
Жрем память и ресурсы копированием.
Еще раз задача- ускорить и не получить бед.аллок.
Объявим челендж? :) эт я люблю :). Не подумайте, даже проигрывать люблю, хотя выигрывать конечно приятней.

0
64 / 68 / 18
Регистрация: 21.10.2015
Сообщений: 228
01.09.2016, 01:35 26
может помочь unsafe
0
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
01.09.2016, 18:14  [ТС] 27
Цитата Сообщение от Avazart Посмотреть сообщение
Почему не читать сразу в поля структуры?
действительно... полночь сказалась...
Цитата Сообщение от Avazart Посмотреть сообщение
Почему оператор относительно char* а не Pair ?
потому что раз там сортировка использует оператор <, и мы ей передаем char*, значит оператор < тоже нужно делать относительно char*, я думаю. непонятно почему это не помогло вчера... но доделывать уже в любом случае буду завтра, посмотрим что получится.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.09.2016, 19:08 28
Лучший ответ Сообщение было отмечено MayaNash как решение

Решение

Цитата Сообщение от Керра Посмотреть сообщение
значит оператор < тоже нужно делать относительно char*, я думаю.
Относительно двух char*-ов.

Добавлено через 5 минут
C++
1
2
3
4
5
6
7
8
9
10
11
struct Part 
{
   char id2[10], name[20];
   bool operator<(const Part& part) const;
   {
      if(strcmp(id2,part.id2)<0)
        return true;
      return strcmp(name,part.name)<0;
   }
   // ...
};
Добавлено через 28 минут
Хотя конечно я вероятно не особо въезжаю в твой код и то что ты хочешь сделать.

У тебя строка файла состоит из трех строковых значений разделенных ":"
По двум идет сравнение - третье - искомое значение.
Отличие между двумя файлами только в порядке следования.

Я вижу задачу приблизительно так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const std::size_t str_size= 20;
 
struct Line
{
    std::pair<std::string,std::string> key;
    std::string value;
 
    Line():
      key(std::make_pair(std::string(str_size,'\0'),std::string(str_size,'\0')),
      value(std::string(str_size,'\0'))
    {
    }
 
    bool operator<(const Line& line) const;  {   return key < line.key;  }
    bool operator>(const Line& line) const;  {   return key > line.key;  }
    bool operator==(const Line& line) const;{   return key == line.key;  }
};
 
typedef std::vector<Line> Lines;
Потом читаем
C++
1
2
    Lines lines; 
    lines.reserve(1000);
Цикл чтения
C++
1
2
3
4
5
6
7
8
9
10
11
    Line line;  
    fscanf_s(f, "%s:%s:%s", &line.value[0], &line.key.first[0], &line.key.second[0]);
     //  &s[0] или используем s.data()
     /*
          Да и тут стоит как-то уменьшить размеры строк 
          c размера 20 до реального размера(до первого '\0')
          иначе сравнения между  std::string -гами могут быть медленным,
          или в самом сравнении структур Line
          все же использовать strcmp() а не операторы string
    */
    lines.push_back(line);
Cортируем
C++
1
     std::sort(lines.begin(),lines.end());
Читаем также строки с файла 2 только меняем очередность параметров и ищем их
C++
1
2
3
4
    Lines::iterator it= lower_bound(lines.begin(),lines.end(),line_from_file2); 
     // или std::equal_range в зависимости от того есть ли дубликаты
    if(it!=lines.end())
       // ...
Бинарный поиск в STL
0
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 15:46  [ТС] 29
Вот иногда перечитываю свой вчерашний/позавчерашний код, и такое ощущение появляется, что я была сильно нездорова...

Добавлено через 11 секунд
Это тот случай...

Добавлено через 10 секунд
Зачем же я так усложнила?..

Добавлено через 2 минуты
Avazart, сейчас вот я переписала, и получилось почти как у вас, за исключением структуры Line...
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 15:57 30

Не по теме:

Цитата Сообщение от Керра Посмотреть сообщение
что я была сильно нездорова...
Значить пить нужно меньше....
Или больше.... :drink:



Добавлено через 7 минут
Цитата Сообщение от Керра Посмотреть сообщение
за исключением структуры Line...
Я использовал std::pair<std::string,std::string> key; для наглядности,
а вообще операторы сравнения стоит переписать на strcmp из-за чтения scanf, как я писал в комментариях.
0
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 16:02  [ТС] 31
Цитата Сообщение от Avazart Посмотреть сообщение
стоит переписать на strcmp из-за чтения scanf
ясное дело
у меня вот так вот получилось, и теперь все ясно и понятно, только с чтением строк надо что-то сделать - читает всю строку в одну переменную, не понимает что двоеточие это разделитель
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <iostream>
#include <string>
#include <Windows.h>
#include <vector>
#include <algorithm>
using namespace std;
 
#define DEBUG
 
struct Line {
    char id1[10], id2[10], name[20];
    Line(char *id1 = NULL, char *id2 = NULL, char *name = NULL) {
        if (id1 != NULL)
            strcpy(this->id1, id1);
        else
            this->id1[0] = '\0';
        if (id2 != NULL)
            strcpy(this->id2, id2);
        else
            this->id2[0] = '\0';
        if (name != NULL)
            strcpy(this->name, name);
        else
            this->name[0] = '\0';
    }
    Line(const Line &r) {
        *this = r;
    }
    Line& operator=(const Line &r) {
        strcpy(id1, r.id1);
        strcpy(id2, r.id2);
        strcpy(name, r.name);
        return *this;
    }
    bool operator<(const Line &r) const {
        if (strcmp(id1, r.id1) < 0)
            return true;
        else
            return strcmp(id2, r.id2) < 0;
    }
    bool operator>(const Line &r) const {
        if (strcmp(id1, r.id1) > 0)
            return true;
        else
            return strcmp(id2, r.id2) > 0;
    }
    bool operator==(const Line &r) const {
        return strcmp(id1, r.id1) == 0 && strcmp(id2, r.id2) == 0;
    }
};
 
vector<Line> parse(FILE *f) {
    vector<Line> v;
    Line line;
 
    while (!feof(f)) {
        fscanf_s(f, "%s:%s:%s", &line.name, &line.id1, &line.id2);
#ifdef DEBUG
        cout << '[' << line.name << "] [" << line.id1 << "] [" << line.id2 << "]\n";
#endif
        v.push_back(line);
    }
    sort(v.begin(), v.end());
#ifdef DEBUG
    getchar();
#endif
    return v;
}
 
bool find(vector<Line> v, Line &line) {
    pair<vector<Line>::iterator, vector<Line>::iterator> itPair =
        equal_range(v.begin(), v.end(), line);
    if (itPair.first != v.end()) {
        strcpy(line.name, itPair.first->name);
        return true;
    }
    else
        return false;
}
 
void mergeFiles(FILE *f1, FILE *f2, FILE *fRes) {
    char name[20];
    Line line;
    vector<Line> v = parse(f1);
    while (!feof(f2)) {
        fscanf_s(f2, "%s:%s:%s", &line.id1, &line.id2, &name);
        if (find(v, line))
            fprintf(f2, "%s:%s\n", line.name, name);
    }
}
 
int main() {
    string file1path, file2path, fileResultPath;
    FILE *file1, *file2, *fileResult;
 
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
    cout << "Путь к первому файлу > ";
    getline(cin, file1path);
    cout << "Путь ко второму файлу > ";
    getline(cin, file2path);
    cout << "Путь к файлу для записи результата > ";
    getline(cin, fileResultPath);
 
    file1 = fopen(file1path.c_str(), "rt");
    file2 = fopen(file2path.c_str(), "rt");
    fileResult = fopen(fileResultPath.c_str(), "wt");
 
    if (file1 != NULL && file2 != NULL) {
        mergeFiles(file1, file2, fileResult);
        fclose(file1);
        fclose(file2);
        fclose(fileResult);
        cout << "Готово!\n";
    }
    else
        cout << "Проблема с открытием файлов!\n";
 
    system("pause");
    return 0;
}
Добавлено через 3 минуты
я так думаю, со string все же лучше было)))
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 16:19 32
Цитата Сообщение от Керра Посмотреть сообщение
я так думаю, со string все же лучше было)))
Ну как в моем примере - меньше кода получается. просто для сравнения использовать strcmp(s1.c_str(),s2.c_str())

Добавлено через 2 минуты
Цитата Сообщение от Керра Посмотреть сообщение
только с чтением строк надо что-то сделать - читает всю строку в одну переменную, не понимает что двоеточие это разделитель
Честно говоря я не помню как c scanf управлятся, предположу что нужно
C++
1
fscanf_s(f, "%s:%s:%s\n", &line.name, &line.id1, &line.id2);
или
C++
1
fscanf_s(f, "%s:%s:%s\r\n", &line.name, &line.id1, &line.id2);
А ты там уже проверяй.

Добавлено через 4 минуты
Кроме того вектор лучше передавать по ссылке (и возвращать тоже- не через return а параметром) в ф-ции.
1
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 16:20  [ТС] 33
Цитата Сообщение от Avazart Посмотреть сообщение
передавать по ссылке
точно
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 16:29 34
И опять же резервирование:
Цитата Сообщение от Avazart Посмотреть сообщение
lines.reserve(1000);
1
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 16:31  [ТС] 35
да, об этом уже вспомнила, спасибо)
0
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 16:33  [ТС] 36
Вроде все хорошо, только Игоря он почему-то не находит
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <iostream>
#include <string>
#include <Windows.h>
#include <vector>
#include <algorithm>
using namespace std;
 
//#define DEBUG
 
struct Line {
    string id1, id2, name;
    Line(string id1 = "", string id2 = "", string name = "") {
        this->id1 = id1;
        this->id2 = id2;
        this->name = name;
    }
    Line(const Line &r) {
        *this = r;
    }
    Line& operator=(const Line &r) {
        id1 = r.id1;
        id2 = r.id2;
        name = r.name;
        return *this;
    }
    bool operator<(const Line &r) const {
        if (id1 < r.id1)
            return true;
        else
            return id2 < r.id2;
    }
    bool operator>(const Line &r) const {
        if (id1 > r.id1)
            return true;
        else
            return id2 > r.id2;
    }
    bool operator==(const Line &r) const {
        return id1 == r.id1 && id2 == r.id2;
    }
};
 
void parse(ifstream &f, vector<Line> &v) {
    Line line;
 
    while (!f.eof()) {
        getline(f, line.name, ':');
        getline(f, line.id1, ':');
        getline(f, line.id2);
#ifdef DEBUG
        cout << '[' << line.name << "] [" << line.id1 << "] [" << line.id2 << "]\n";
#endif
        v.push_back(line);
    }
    sort(v.begin(), v.end());
}
 
bool find(vector<Line> v, Line &line) {
    pair<vector<Line>::iterator, vector<Line>::iterator> itPair =
        equal_range(v.begin(), v.end(), line);
    if (itPair.first != v.end()) {
        line.name = itPair.first->name;
        return true;
    }
    else
        return false;
}
 
void mergeFiles(ifstream &f1, ifstream &f2, ofstream &fRes) {
    string name;
    Line line;
    vector<Line> v;
    v.reserve(100000);
    parse(f1, v);
    while (!f2.eof()) {
        getline(f2, line.id1, ':');
        getline(f2, line.id2, ':');
        getline(f2, name);
        if (find(v, line))
            fRes << line.name << ':' << name << endl;
    }
}
 
int main() {
    string file1path, file2path, fileResultPath;
    ifstream file1, file2;
    ofstream fileResult;
 
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
    cout << "Путь к первому файлу > ";
    getline(cin, file1path);
    cout << "Путь ко второму файлу > ";
    getline(cin, file2path);
    cout << "Путь к файлу для записи результата > ";
    getline(cin, fileResultPath);
 
    file1.open(file1path.c_str());
    file2.open(file2path.c_str());
    fileResult.open(fileResultPath.c_str());
 
    if (file1.is_open() && file2.is_open()) {
        mergeFiles(file1, file2, fileResult);
        file1.close();
        file2.close();
        fileResult.close();
        cout << "Готово!\n";
    }
    else
        cout << "Проблема с открытием файлов!\n";
 
    system("pause");
    return 0;
}
Вложения
Тип файла: txt input1.txt (52 байт, 4 просмотров)
Тип файла: txt input2.txt (42 байт, 3 просмотров)
Тип файла: txt result.txt (37 байт, 4 просмотров)
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 17:37 37
Лучший ответ Сообщение было отмечено MayaNash как решение

Решение

Цитата Сообщение от Керра Посмотреть сообщение
Вроде все хорошо, только Игоря он почему-то не находит
Думаю операторы сравнения реализованы не верно, проверьте:
C++
1
2
3
4
5
6
7
bool operator<(const Line &r) const 
{
        if (id1 < r.id1)
            return true;
        else
            return id2 < r.id2;
 }
Может :
C++
1
2
3
4
5
6
7
bool operator<(const Line &r) const 
{
    if (id1 == r.id1)
       return id2 < r.id2;
    return  id1<r.id1;
    /* Или все же использовать std::pair<> */
}
Вот пример с fscanf()

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
#include <iostream>
#include <string>
#include <windows.h>
 
int main()
{
    SetConsoleCP(1251);
    SetConsoleOutputCP(1251);
 
    std::string filePath= "input1.txt";
 
    FILE* file = fopen(filePath.c_str(), "rt");
    if(file)
    {
        while(!feof(file))
        {
            char id1[20]={'\0'};
            char id2[20]={'\0'};
            char name[20]={'\0'};
            if(fscanf(file,"%[^;];%[^;];%s\r\n", &id1,&id2,&name)/*==3*/)
               std::cout<<"["<<id1<<"] ["<<id2<<"] ["<<name<<"]"<<std::endl;
        }
        fclose(file);
    }
 
    getchar();
    return 0;
}
http://lord-n.narod.ru/downloa... /scanf.htm
1
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 18:41  [ТС] 38
Цитата Сообщение от Avazart Посмотреть сообщение
Думаю операторы сравнения реализованы не верно
мозги за лето атрофировались

Добавлено через 9 минут
спасибо большое, теперь работает
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 19:43 39
А скорость увеличилась? Остается добавить потоки?
1
1296 / 469 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 20:03  [ТС] 40
скорость конечно увеличилась, пока что еще ускорить не просят
0
02.09.2016, 20:03
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.09.2016, 20:03
Помогаю со студенческими работами здесь

Переделать работу с текстовыми файлами под работу с двоичными файлами
Здравствуйте. В этой программе идёт работа с текстовыми файлами, а нужно с двоичными. Можно ли...

Динамический массив, много циклов и простые числа. Как ускорить работу программы ?
Всем привет. Задание следующее: Кто нибудь вводит с клавиатуры число n и k, должен создастся...

Ускорить работу программы
Лексикографический порядок чисел (Время: 1 сек. Память: 16 Мб Сложность: 31%) Натуральные числа...

Ускорить работу функций
Здравствуйте. Не подскажете как можно ускорить работу функций в цикле? А то линия получается...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru