Хранение данных в map<строка, вектор<std::пара>>> c 98

#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"] vs birds["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;
}