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
|
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <utility>
#include <algorithm>
struct line_data
{
std::pair<int, int> xy_coords; // x and y coordinates
std::string text; // original text of the line
line_data(int x, int y, std::string txt) : xy_coords(x, y), text(std::move(txt)) {}
};
std::vector<line_data> get_selected_lines( std::istream& file, int min_x_coord, int max_x_coord,
std::size_t MAX_RECS )
{
std::vector<line_data> filtered_lines; // vector to hold selected lines
filtered_lines.reserve( MAX_RECS ) ; // reserve space for MAX_RECS records
std::cout << "vector capacity is: " << filtered_lines.capacity() << '\n' ;
int total_recs_read = 0;
int filtered_recs = 0 ;
std::istringstream stm; // don't want to rely on the optimiser eliding the
// construction/destruction of the string stream
// during each iteration of the loop
std::string line;
while (std::getline(file, line)) // for each line in the input file
{
++total_recs_read ;
stm.clear(); // clear a possible error state
stm.str(line);
int x_coord, y_coord;
char separator;
if (stm >> x_coord >> separator >> y_coord && // co-ordinates were successfully read
x_coord >= min_x_coord && x_coord <= max_x_coord) // and x coordinate is within range
{
// add this line to the vector
filtered_lines.emplace_back(x_coord, y_coord, std::move(line));
++filtered_recs ;
}
if( total_recs_read % 1'000'000 == 0 )
{
std::cout << "total_recs_read = " << total_recs_read << '\n'
<< " filtered_recs = " << filtered_recs << '\n' ;
}
}
return filtered_lines;
}
void create_temp_file( std::string input_file_name, std::string temp_file_name,
int min_x_coord, int max_x_coord, int MAX_RECS = 6'000'000 )
{
std::ifstream in_file(input_file_name);
std::vector<line_data> selected_lines = get_selected_lines( in_file, min_x_coord, max_x_coord, MAX_RECS );
// predicate to sort the vector, on x coordinate first, then on y coordinate
staric const auto cmp_coords = [](const line_data& a, const line_data& b)
{ return a.xy_coords < b.xy_coords; };
std::sort(std::begin(selected_lines), std::end(selected_lines), cmp_coords); // sort the vector
// Output file opened to save sorted data.
std::ofstream out_file(temp_file_name);
for (const line_data& ldata : selected_lines) // for each item in the sorted vector
out_file << ldata.text << '\n'; // write the original line to the output file
}
int main()
{
const char* const input_file_name = "IllyriadMapFileEdit02.txt" ;
const char* const temp_file_01 = "IllyriadMapFile_part_01.txt" ;
const char* const temp_file_02 = "IllyriadMapFile_part_02.txt" ;
const char* const output_file_name = "IllyriadMapFileEdit03.txt" ;
// write sorted records for x coordinates -1000 to 0 into temp_file_01
create_temp_file( input_file_name, temp_file_01, -1000, 0 ) ;
// write sorted records for x coordinates 1 to 1000 into temp_file_02
create_temp_file( input_file_name, temp_file_02, -1, 1000 ) ;
// concatenate the two temp files to get our sorted file for x coordinates from -1000 to 1000
std::ofstream out_file(output_file_name) ;
out_file << std::ifstream(temp_file_01).rdbuf() ;
out_file << std::ifstream(temp_file_02).rdbuf() ;
}
|