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

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

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

Студворк — интернет-сервис помощи студентам
Предполагается, что программа будет работать с файлами размера 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
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
31.08.2016, 10:51
Ответы с готовыми решениями:

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

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

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

56
nd2
3438 / 2817 / 1249
Регистрация: 29.01.2016
Сообщений: 9,427
31.08.2016, 23:34
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Керра Посмотреть сообщение
Тогда получается что нужно посимвольно?
Не нужно. По ссылке об этом написано.
1
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
31.08.2016, 23:46  [ТС]
Может быть дело в том, что уже почти полночь, но я не понимаю с чего он ругается. Я сделала вот так вот:
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;
}
А он ругается вот так вот:
Code
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
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
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
01.09.2016, 00:01
Керра, Зачем откапали char*? в первом посте все было чинно, красиво и благородно на std::string.

Не по теме:

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

0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.09.2016, 00:19
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
01.09.2016, 00:30

Не по теме:

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

0
 Аватар для iDReeM
64 / 68 / 18
Регистрация: 21.10.2015
Сообщений: 228
01.09.2016, 01:35
может помочь unsafe
0
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
01.09.2016, 18:14  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Почему не читать сразу в поля структуры?
действительно... полночь сказалась...
Цитата Сообщение от Avazart Посмотреть сообщение
Почему оператор относительно char* а не Pair ?
потому что раз там сортировка использует оператор <, и мы ей передаем char*, значит оператор < тоже нужно делать относительно char*, я думаю. непонятно почему это не помогло вчера... но доделывать уже в любом случае буду завтра, посмотрим что получится.
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
01.09.2016, 19:08
Лучший ответ Сообщение было отмечено 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
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 15:46  [ТС]
Вот иногда перечитываю свой вчерашний/позавчерашний код, и такое ощущение появляется, что я была сильно нездорова...

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

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

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

Не по теме:

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



Добавлено через 7 минут
Цитата Сообщение от Керра Посмотреть сообщение
за исключением структуры Line...
Я использовал std::pair<std::string,std::string> key; для наглядности,
а вообще операторы сравнения стоит переписать на strcmp из-за чтения scanf, как я писал в комментариях.
0
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 16:02  [ТС]
Цитата Сообщение от 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
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 16:19
Цитата Сообщение от Керра Посмотреть сообщение
я так думаю, со 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
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 16:20  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
передавать по ссылке
точно
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 16:29
И опять же резервирование:
Цитата Сообщение от Avazart Посмотреть сообщение
lines.reserve(1000);
1
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 16:31  [ТС]
да, об этом уже вспомнила, спасибо)
0
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 16:33  [ТС]
Вроде все хорошо, только Игоря он почему-то не находит
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
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 17: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
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 18:41  [ТС]
Цитата Сообщение от Avazart Посмотреть сообщение
Думаю операторы сравнения реализованы не верно
мозги за лето атрофировались

Добавлено через 9 минут
спасибо большое, теперь работает
0
Эксперт С++
 Аватар для Avazart
8488 / 6155 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
02.09.2016, 19:43
А скорость увеличилась? Остается добавить потоки?
1
 Аватар для MayaNash
1296 / 470 / 151
Регистрация: 24.08.2011
Сообщений: 2,249
02.09.2016, 20:03  [ТС]
скорость конечно увеличилась, пока что еще ускорить не просят
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
02.09.2016, 20:03
Помогаю со студенческими работами здесь

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru