Falcon
Falcon

Reputation: 37

Parse a string & assign to the target variable

In the below program i have inputted multiple string inputs like in the example below. Now i want to assign the multiple lines parsed data into different variables of different type.

int main()
{
  int line=3, t;
  string s, bigString;

  for(int i=0 ; i<line ; i++)
  {
    getline(cin,s); 
    bigString += s + "\n";
  }
  cout <<bigString <<endl;
  return 0;
}

Sample Input:

1 toy at 10.65
2 box of books at 12.11
1 pot plant at 6.45

I would like to parse and assign my variables like below,

//For storing array of variables,
int quantity;
Map<string,double>itemAndPrice;

ex1:
quantity = 1
itemAndPrice.first() = toy;
itemAndPrice.second() = 10.65;

ex2:
quantity = 2
itemAndPrice.first() = box of 
books;
itemAndPrice.second() = 12.11;

ex3:
quantity = 1
itemAndPrice.first() = pot plant;
itemAndPrice.second() = 6.45;

As every input is different, how to parse and assign in respective variables in a generic way.

Upvotes: 1

Views: 234

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596236

Why are you concatenating all of the inputs into a single string? And why are you using a Map for holding single items? I would suggest defining a struct to hold the different fields you need, and then have your reading loop parse the individual lines into a vector holding that struct type, eg:

#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>

struct itemInfo
{
    int quantity;
    std::string name;
    double price;
};

int main()
{
    std::string line;
    std::vector<itemInfo> items;

    while (std::getline(std::cin, line))
    { 
        try
        {
            itemInfo item;

            auto start = line.find_first_not_of(" \t");
            auto stop = line.find_first_of(" \t", start + 1);
            item.quantity = std::stoi(line.substr(start, stop - start));

            start = line.find_first_not_of(" \t", stop + 1);
            stop = line.find(" at ", start);
            item.name = line.substr(start, stop - start);

            start = line.find_first_not_of(" \t", stop + 4);
            item.price = std::stod(line.substr(start));

            items.push_back(item);
        }
        catch (const std::logic_error &) { }
    }

    // use items as needed...

    return 0;
}

Online Demo

You could then take this a step further by moving the parsing logic into an overloaded operator>> for the struct, eg:

#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>

struct itemInfo
{
    int quantity;
    std::string name;
    double price;
};

std::istream& operator>>(std::istream &in, itemInfo &item)
{
    try
    {
        std::string line;

        if (std::getline(in, line))
        {
            auto start = line.find_first_not_of(" \t");
            auto stop = line.find_first_of(" \t", start + 1);
            item.quantity = std::stoi(line.substr(start, stop - start));

            start = line.find_first_not_of(" \t", stop + 1);
            stop = line.find(" at ", start);
            item.name = line.substr(start, stop - start);

            start = line.find_first_not_of(" \t", stop + 4);
            item.price = std::stod(line.substr(start));
        }
    }
    catch (const std::logic_error &)
    {
        in.setstate(std::ios_base::failbit); 
    }

    return in;
}

int main()
{
    itemInfo item;
    std::vector<itemInfo> items;

    while (std::cin >> item)
    { 
        items.push_back(item);
    }

    // use items as needed...

    return 0;
}

Online Demo

Upvotes: 1

Related Questions