I have file named Bird.lst
. I am trying to read its contents and store the data in a map<string, vector<pair<string, string>>>
. The idea is to store the bird's name in the string
and its attribute values in the vector
.
Also, there are some attributes that I don't need (vaccinated
, babies
, sale
). While inserting into the map
, I have to check to not insert these attributes.
Where the attributes didn't got added, but while displaying, the map
contents there are displaying empty spaces. I want to get rid of the empty lines from the map
.
My map
content should be seen as below. please help.
parrot.sh ----> eat yes
fly yes
Bird.lst
parrot.sh
vaccinated yes
eat yes
babies no
fly yes
sale no
pigeon.sh
vaccinated yes
eat yes
fly yes
babies yes
sale yes
duck.sh
vaccinated yes
eat yes
fly no
sale yes
babies no
flammingo.sh
vaccinated yes
eat yes
fly yes
sale no
babies no
eagle.sh
vaccinated yes
eat yes
babies no
fly yes
Code:
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>
#include <utility>
typedef std::pair<std::string,std::string> attribute_pair;
typedef std::vector<attribute_pair> attribute_vector;
typedef std::map<std::string,attribute_vector> bird_map;
int main()
{
std::ifstream file("Bird.lst");
bird_map birds;
std::string key;
while(std::getline(file,key))
{
attribute_vector attributes;
std::string value;
while(std::getline(file,value))
{
// in case it has windows encoding with end-of-line = \r\n
if (!value.empty() &&
value[value.size()-1] == '\r')
{
value.erase(value.size() - 1);
}
// if we found the empty string
if(value.empty())
{
break;
}
// now split the value into an attribute and a flag
attribute_pair attribute;
std::istringstream ss(value);
if(value.find("vaccinated") == std::string::npos && value.find("babies") == std::string::npos && value.find("sale") == std::string::npos)
ss >> attribute.first >> attribute.second;
// save the value into the vector
attributes.push_back(attribute);
}
// save the bird into the map
birds[key] = attributes;
}
// now print the data we collected
for(bird_map::iterator bird = birds.begin();
bird != birds.end();
bird++)
{
std::cout << bird->first << "\n";
for(attribute_vector::iterator attribute = bird->second.begin();
attribute != bird->second.end();
attribute++)
{
std::cout << " " << attribute->first
<< " " << attribute->second
<< "\n";
}
std::cout << "\n";
}
return 0;
}
Output from the above code:
duck.sh
eat yes
fly no
eagle.sh
eat yes
fly yes
flammingo.sh
eat yes
fly yes
parrot.sh
eat yes
fly yes
pigeon.sh
eat yes
fly yes
When you are parsing a value
string into an attribute_pair
, you are looking for specific attributes to ignore, and if you find one then you don't parse the value
, but you are still inserting the empty attribute_pair
into the attributes
vector. That is where the empty lines in your output are coming from.
Change this:
// now split the value into an attribute and a flag
attribute_pair attribute;
std::istringstream ss(value);
if(value.find("vaccinated") == std::string::npos && value.find("babies") == std::string::npos && value.find("sale") == std::string::npos)
ss >> attribute.first >> attribute.second;
// save the value into the vector
attributes.push_back(attribute);
To this instead:
// now split the value into an attribute and a flag
attribute_pair attribute;
std::istringstream ss(value);
ss >> attribute.first >> attribute.second;
if(attribute.first != "vaccinated" && attribute.first != "babies" && attribute.first != "sale") {
// save the value into the vector
attributes.push_back(attribute);
}
That being said, you might consider using a map<string,string>
instead of a vector<pair<string,string>>
, unless you have a requirement to preserve the original order of the attributes of each bird (you are not preserving the order of the birds themselves, since std::map
is sorted).