Reputation: 342
I am working on my C++ (File Handling) Project but got stuck on a point
SNO, Name, NoOfPeopleLiked
1, The Shawshank Redemption, 77
2, The Godfather, 20
3, Into The Wild, 35
4, The Dark Knight, 55
5, 12 Angry Men, 44
6, Schindler's List, 33
7, The Lord of the Rings: The Return of the King, 25
8, Pulp Fiction, 23
9, The Good, the Bad and the Ugly, 32
10, The Lord of the Rings: The Fellowship of the Ring, 56
I have to display the top 5 movies with respect to NoOfPeopleLiked
Just like that:
1, The Shawshank Redemption, 77
2, The Lord of the Rings: The Fellowship of the Ring, 56
3, The Dark Knight, 55
4, 12 Angry Men, 44
5, Into The Wild, 36
so I have to do sorting and this is what I have done so far
void topFive()
{
Movies v[20]; //class object array
fstream top; //for reading
top.open("movies.txt");
for (int h = 0; h < 10; h++) // reading from txt file
{
top >> v[h].serial >> v[h].movieName >> v[h].liked;
}
// run loops two times: one for walking throught the array
// and the other for comparison
for (int step = 0; step < 5; ++step)
{
for (int i = 0; i < 5 ; ++i)
{
// To sort in descending order, change > to < in this line.
if (v[i].liked > v[i + 1].liked)
{
// swap if greater is at the rear position
int temp = v[i].liked;
v[i].liked = v[i + 1].liked;
v[i + 1].liked = temp;
}
}
}
// to print the array
for (int i = 0; i < 5; ++i)
{
cout << v[i].serial << ", " << v[i].movieName << ", " << v[i].liked << endl;
}
}
To be Honest I did not know how to do it perfectly I am stucked with this problem for about 6-7 hours and still can't make any logic. I hope you guyz can help me and guide me better. Thanks in advance :)
Upvotes: 3
Views: 8286
Reputation: 16767
I've implemented next solution using std::regex module. Plus some strings operations. And of cause sorting!
In my code input file is called 0302.txt
, please rename it to what you need before running code.
#include <vector>
#include <string>
#include <regex>
#include <fstream>
#include <tuple>
#include <iostream>
#include <stdexcept>
#include <algorithm>
int main() {
try {
auto StrTrim = [](std::string & str){
str.erase(0, str.find_first_not_of("\t\n\v\f\r ")); // left trim
str.erase(str.find_last_not_of("\t\n\v\f\r ") + 1); // right trim
};
std::ifstream ifile("0302.txt");
std::string line;
std::vector<std::string> lines;
// Read all lines of file.
while (std::getline(ifile, line)) {
StrTrim(line);
if (line.empty())
continue;
lines.push_back(line);
}
if (!lines.empty())
lines.erase(lines.begin(), lines.begin() + 1); // remove first header line
lines.erase(lines.begin(), lines.begin() + 1); // remove first header line
std::vector<std::tuple<size_t, std::string, size_t>> data;
std::regex re(R"((\d+)\s*,\s*(.+)?\s*,\s*(\d+))");
for (auto const & line: lines) {
std::smatch matches;
if (std::regex_match(line, matches, re)) {
if (matches.size() != 4)
throw std::runtime_error("Matched line with not 3 elements: '" + line + "'!");
data.push_back(std::make_tuple(size_t(std::stoi(matches[1])), matches[2], size_t(std::stoi(matches[3]))));
} else
throw std::runtime_error("Unmatched line: '" + line + "'!");
}
std::sort(data.begin(), data.end(), [](auto const & l, auto const & r){
return std::get<2>(l) > std::get<2>(r);
});
for (size_t i = 0; i < 5; ++i) {
if (i >= data.size())
break;
std::cout << (i + 1) << "|" << std::get<0>(data[i]) << ", " << std::get<1>(data[i]) << ", " << std::get<2>(data[i]) << std::endl;
}
return 0;
} catch (std::exception const & ex) {
std::cout << "Exception: " << ex.what() << std::endl;
return -1;
}
}
Input file 0302.txt
:
SNO, Name, NoOfPeopleLiked
1, The Shawshank Redemption, 77
2, The Godfather, 20
3, Into The Wild, 35
4, The Dark Knight, 55
5, 12 Angry Men, 44
6, Schindler's List, 33
7, The Lord of the Rings: The Return of the King, 25
8, Pulp Fiction, 23
9, The Good, the Bad and the Ugly, 32
10, The Lord of the Rings: The Fellowship of the Ring, 56
Console output:
1|1, The Shawshank Redemption, 77
2|10, The Lord of the Rings: The Fellowship of the Ring, 56
3|4, The Dark Knight, 55
4|5, 12 Angry Men, 44
5|3, Into The Wild, 35
Upvotes: 1
Reputation: 8564
You can just insert the strings from the file inside a vector and sort with a custom comparator function. This comparator function can extract the rank from the input string (assuming the rank is after the last comma, assuming the input schema is uniform) and use it in comparison. Code:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <sstream>
#include <fstream>
using namespace std;
int get_rank(std::string input) {
std::stringstream ss(input);
std::string s;
// keep extracting strings, last one would be your 'int' rank
for(; ss >> s; );
return std::atoi(s.c_str());
}
int main() {
std::ifstream infile("movies.txt");
std::vector<std::string> v;
std::string line;
std::getline(infile, line);
for( ; getline( infile, line ); )
v.push_back(line);
std::sort(v.begin(), v.end(), [](std::string s1, std::string s2) -> bool { return get_rank(s1) > get_rank(s2); });
for(int i = 0;i < 5;i++)
cout << i + 1 << "," << v[i].substr(v[i].find(",") + 1) << endl;
return 0;
}
Upvotes: 2