1

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.

0

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

5 Comments

Thankyou for your valuable inputs.Below is my code with the logic shared by you, where I am iterating based on number of inputs but then I receive runtime error. How to fix the same. ideone.com/XfwMqc
@Falcon you are running into this issue: Why does std::getline() skip input after a formatted extraction? After std::cin >> noOfInput; there is an unread line break left behind in cin's input buffer that causes the next std::getline(std::cin, line); to return an empty string in line. You need to discard that unread line break after reading in noOfInput.
Yes I have gone through that link before, cin.ignore() doesn't work in my case. It still behaves same with or without it.
int noOfInput; std::cin >> noOfInput; ... std::getline(std::cin, line); will not work in your example, line will be empty. You need either int noOfInput; std::cin >> noOfInput; std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); ... std::getline(std::cin, line); Or int noOfInput; std::cin >> noOfInput; ... std::getline(std::cin >> std::ws, line);
After fixing that, I see your for reading loop is also wrong, it needs to use < instead of <=. Also, line.find_first_not_of(" ", ...) could just be line.find(' ', ...) since you are looking for just spaces. The example I gave you looks for both spaces and tabs instead. But either way, I see you are parsing the items correctly, but discountMap.find(item.name) is not finding them, hence the Invalid Item for Promotion errors, because you commented out init() in main() to populate discountMap. Uncommenting that, I don't get any more errors: ideone.com/iMfD8W

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.