I have C code like below.
It works well but my output like this :
192.168.1.163 => 4 times
192.168.1.165 => 7 times
192.168.1.20 => 62 times
How can I make desc order like :
192.168.1.20 => 62 times
192.168.1.165 => 7 times
192.168.1.163 => 4 times
std::map<std::string, int> stringCount; //str is ip and int is logged count
while(std::getline(readIp, ipLine))//go line by line
{
std::istringstream ss(ipLine);
ipLine.erase(std::remove(ipLine.begin(), ipLine.end(), '"'), ipLine.end()); //removed "
stringCount[ipLine] ; //increment the count
}
readIp.close();
std::cout<<"Total number of ip's are logged on the system :"<<stringCount.size()<<std::endl;
std::ofstream outputFile("times.txt");
for(std::pair<std::string, int> pairElement: stringCount)
{
std::cout<<pairElement.first<<" => "<<pairElement.second<<" times "<<std::endl;
outputFile<<pairElement.first<<" => "<<pairElement.second<<" times \n";
}
CodePudding user response:
Since it is not possible to sort a std::map
by its values you can use something like a std::vector
as shown below. The program below writes the ip addresses in decreasing order of count values as you want.
#include <iostream>
#include <map>
#include <sstream>
#include <fstream>
#include <vector>
#include <algorithm>
//create a function that will be used as comparator
bool sortInDecreasingOrder(std::pair<std::string, int> const &a, std::pair<std::string, int> const &b)
{
return a.second > b.second;
}
int main() {
//this map maps each word in the file to their respective count
std::map<std::string, int> stringCount;
std::string word, line;
int count = 0;//this count the total number of words
std::ifstream inputFile("log.txt");
if(inputFile)
{
while(std::getline(inputFile, line))//go line by line
{
std::istringstream ss(line);
//increment the count
stringCount[line] ;
}
}
else
{
std::cout<<"File cannot be opened"<<std::endl;
}
inputFile.close();
std::cout<<"Total number of unique ip's are:"<<stringCount.size()<<std::endl;
//since we cannot sort a std::map by its second value we can create a vector and sort that vector
std::vector<std::pair<std::string, int>> vec(stringCount.begin(), stringCount.end());
//now you can sort this vector
std::sort(vec.begin(), vec.end(), sortInDecreasingOrder);
//lets create a output file and write into it the unique ips
std::ofstream outputFile("code.txt");
for(std::pair<std::string, int> pairElement: vec)//note this time we go through vector vec instead of map
{
std::cout<<pairElement.first<<" => "<<pairElement.second<<" times "<<std::endl;
outputFile<<pairElement.first<<" => "<<pairElement.second<<" times \n";
}
outputFile.close();
return 0;
}
The output of the program can be seen here.