#c #string #file #dictionary #c 98
Вопрос:
У меня есть файл с именем Bird.lst
. Я пытаюсь прочитать его содержимое и сохранить данные в a map<string, vector<pair<string, string>>>
. Идея состоит в том, чтобы сохранить имя птицы в string
и ее значения атрибутов в vector
.
Кроме того, есть некоторые атрибуты, которые мне не нужны ( vaccinated
, babies
, sale
). При вставке в map
, я должен проверить, чтобы не вставлять эти атрибуты.
Там, где атрибуты не были добавлены, но при отображении map
содержимого отображаются пустые места. Я хочу избавиться от пустых строк из map
.
Мой map
контент следует рассматривать, как показано ниже. пожалуйста, помогите.
parrot.sh ----> eat yes
fly yes
Птица.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
Код:
#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 = rn
if (!value.empty() amp;amp;
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 amp;amp; value.find("babies") == std::string::npos amp;amp; 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;
}
Вывод из приведенного выше кода:
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
Комментарии:
1. @Sopel то, что вас пугает, может быть лучшей попыткой новичка. Лучше не используйте такие сильные слова, есть более приятные способы передать то же самое сообщение
2. делает
value.find("vaccinated") == std::string::npos amp;amp; value.find("babies") == std::string::npos amp;amp; value.find("sale") == std::string::npos
ли он то, что вы хотите, чтобы он делал? атрибуты заполняются только в том случае , если строка не содержит ни одного изvaccinated
,babies
иsale
. Даже если структура атрибутов не заполняется из строки, она все равно добавляется на карту (что приводит к появлению пустых строк в выводе).3. @AlanBirtles я пытаюсь избежать вставки этих значений в карту
vaccinated
babies
иsale
использования этой строки кодаvalue.find("vaccinated") == std::string::npos amp;amp; value.find("babies") == std::string::npos amp;amp; value.find("sale") == std::string::npos
4. когда вы сталкиваетесь с пустой записью, вы
break
выходите из внутреннего цикла, но затем все равно добавляете все еще пустуюattribute
запись на карту5. @AmithKotian Использование a
map
проще использовать при доступе к парам ключ/значение, например:birds["parrot.sh"]["eat"]
vsbirds["parrot.sh"][some_index].second
Ответ №1:
Когда вы анализируете value
строку в an attribute_pair
, вы ищете конкретные атрибуты, которые следует игнорировать, и если вы их найдете , то вы не анализируете value
, но все равно вставляете пустое attribute_pair
в attributes
вектор. Вот откуда берутся пустые строки в ваших выходных данных.
Измените это:
// now split the value into an attribute and a flag
attribute_pair attribute;
std::istringstream ss(value);
if(value.find("vaccinated") == std::string::npos amp;amp; value.find("babies") == std::string::npos amp;amp; value.find("sale") == std::string::npos)
ss >> attribute.first >> attribute.second;
// save the value into the vector
attributes.push_back(attribute);
К этому вместо:
// 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" amp;amp; attribute.first != "babies" amp;amp; attribute.first != "sale") {
// save the value into the vector
attributes.push_back(attribute);
}
Тем не менее, вы можете рассмотреть возможность использования a map<string,string>
вместо a vector<pair<string,string>>
, если только у вас нет требования сохранить исходный порядок атрибутов каждой птицы (вы не сохраняете порядок самих птиц, так std::map
как он отсортирован).
Ответ №2:
Перед вставкой в карту<ключ, значение> здесь значение-вектор<ключ, значение><пара<строка, строка><строка, строка>> <строка, строка>>> добавить добавление проверьте, не пуста ли строка вектора значения.
#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 = rn
if (!value.empty() amp;amp;
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 amp;amp; value.find("babies") == std::string::npos amp;amp; value.find("sale") == std::string::npos)
ss >> attribute.first >> attribute.second;
if(!attribute.first.empty()) //check the attribute value is empty or not before inserting into attributes vector
// 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;
}