Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
 
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
31.08.2016, 10:51     Как ускорить работу с файлами? #1
Предполагается, что программа будет работать с файлами размера 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;
}
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
nd2
1025 / 764 / 257
Регистрация: 29.01.2016
Сообщений: 2,387
31.08.2016, 23:34     Как ускорить работу с файлами? #21
Цитата Сообщение от Керра Посмотреть сообщение
Тогда получается что нужно посимвольно?
Не нужно. По ссылке об этом написано.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
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 ==========
В чем дело?..
Nosey
 Аватар для Nosey
1184 / 351 / 102
Регистрация: 22.10.2014
Сообщений: 786
Завершенные тесты: 2
01.09.2016, 00:01     Как ускорить работу с файлами? #23
Керра, Зачем откапали char*? в первом посте все было чинно, красиво и благородно на std::string.

Не по теме:

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

Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
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 есть алгоритмы.

Nosey
01.09.2016, 00:30
  #25

Не по теме:

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

iDReeM
 Аватар для iDReeM
37 / 37 / 7
Регистрация: 21.10.2015
Сообщений: 159
Завершенные тесты: 2
01.09.2016, 01:35     Как ускорить работу с файлами? #26
может помочь unsafe
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
01.09.2016, 18:14  [ТС]     Как ускорить работу с файлами? #27
Цитата Сообщение от Avazart Посмотреть сообщение
Почему не читать сразу в поля структуры?
действительно... полночь сказалась...
Цитата Сообщение от Avazart Посмотреть сообщение
Почему оператор относительно char* а не Pair ?
потому что раз там сортировка использует оператор <, и мы ей передаем char*, значит оператор < тоже нужно делать относительно char*, я думаю. непонятно почему это не помогло вчера... но доделывать уже в любом случае буду завтра, посмотрим что получится.
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
01.09.2016, 19:08     Как ускорить работу с файлами? #28
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Керра Посмотреть сообщение
значит оператор < тоже нужно делать относительно 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
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
02.09.2016, 15:46  [ТС]     Как ускорить работу с файлами? #29
Вот иногда перечитываю свой вчерашний/позавчерашний код, и такое ощущение появляется, что я была сильно нездорова...

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

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

Добавлено через 2 минуты
Avazart, сейчас вот я переписала, и получилось почти как у вас, за исключением структуры Line...
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
02.09.2016, 15:57     Как ускорить работу с файлами? #30

Не по теме:

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



Добавлено через 7 минут
Цитата Сообщение от Керра Посмотреть сообщение
за исключением структуры Line...
Я использовал std::pair<std::string,std::string> key; для наглядности,
а вообще операторы сравнения стоит переписать на strcmp из-за чтения scanf, как я писал в комментариях.
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
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 все же лучше было)))
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
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 а параметром) в ф-ции.
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
02.09.2016, 16:20  [ТС]     Как ускорить работу с файлами? #33
Цитата Сообщение от Avazart Посмотреть сообщение
передавать по ссылке
точно
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
02.09.2016, 16:29     Как ускорить работу с файлами? #34
И опять же резервирование:
Цитата Сообщение от Avazart Посмотреть сообщение
lines.reserve(1000);
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
02.09.2016, 16:31  [ТС]     Как ускорить работу с файлами? #35
да, об этом уже вспомнила, спасибо)
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
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 байт, 3 просмотров)
Тип файла: txt input2.txt (42 байт, 2 просмотров)
Тип файла: txt result.txt (37 байт, 3 просмотров)
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
02.09.2016, 17:37     Как ускорить работу с файлами? #37
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от Керра Посмотреть сообщение
Вроде все хорошо, только Игоря он почему-то не находит
Думаю операторы сравнения реализованы не верно, проверьте:
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/download/book...C/13/scanf.htm
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
02.09.2016, 18:41  [ТС]     Как ускорить работу с файлами? #38
Цитата Сообщение от Avazart Посмотреть сообщение
Думаю операторы сравнения реализованы не верно
мозги за лето атрофировались

Добавлено через 9 минут
спасибо большое, теперь работает
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
02.09.2016, 19:43     Как ускорить работу с файлами? #39
А скорость увеличилась? Остается добавить потоки?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
02.09.2016, 20:03     Как ускорить работу с файлами?
Еще ссылки по теме:

C++ Можно ли как нибудь ускорить работу цикла for?
Задача про рюкзак - ускорить работу программы C++
C++ Ускорить работу программы

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

Или воспользуйтесь поиском по форуму:
Керра
Модератор
 Аватар для Керра
1270 / 438 / 45
Регистрация: 24.08.2011
Сообщений: 2,123
02.09.2016, 20:03  [ТС]     Как ускорить работу с файлами? #40
скорость конечно увеличилась, пока что еще ускорить не просят
Yandex
Объявления
02.09.2016, 20:03     Как ускорить работу с файлами?
Ответ Создать тему
Опции темы

Текущее время: 05:44. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru