Question

I am trying to learn C++ and came across this problem statement

CHALLENGE DESCRIPTION:

Our marketing department has just negotiated a deal with several local merchants that will allow us to offer exclusive discounts on various products to our top customers every day. The catch is that we can only offer each product to one customer and we may only offer one product to each customer.

Each day we will get the list of products that are eligible for these special discounts. We then have to decide which products to offer to which of our customers. Fortunately, our team of highly skilled statisticians has developed an amazing mathematical model for determining how likely a given customer is to buy an offered product by calculating what we call the "suitability score" (SS). The top-secret algorithm to calculate the SS between a customer and a product is this:

1. If the number of letters in the product's name is even then the SS is the number of vowels (a, e, i, o, u, y) in the customer's name multiplied by 1.5.
2. If the number of letters in the product's name is odd then the SS is the number of consonants in the customer's name.
3. If the number of letters in the product's name shares any common factors (besides 1) with the number of letters in the customer's name then the SS is multiplied by 1.5.

Your task is to implement a program that assigns each customer a product to be offered in a way that maximizes the combined total SS across all of the chosen offers. Note that there may be a different number of products and customers. You may include code from external libraries as long as you cite the source.

INPUT SAMPLE:

Your program should accept as its only argument a path to a file. Each line in this file is one test case. Each test case will be a comma delimited set of customer names followed by a semicolon and then a comma delimited set of product names. Assume the input file is ASCII encoded. For example (NOTE: The example below has 3 test cases):

Jack Abraham,John Evans,Ted Dziuba;iPad 2 - 4-pack,Girl Scouts Thin Mints,Nerf Crossbow

Jeffery Lebowski,Walter Sobchak,Theodore Donald Kerabatsos,Peter Gibbons,Michael Bolton,Samir Nagheenanajar;Half & Half,Colt M1911A1,16lb bowling ball,Red Swingline Stapler,Printer paper,Vibe Magazine Subscriptions - 40 pack

Jareau Wade,Rob Eroh,Mahmoud Abdelkader,Wenyi Cai,Justin Van Winkle,Gabriel Sinkin,Aaron Adelson;Batman No. 1,Football - Official Size,Bass Amplifying Headphones,Elephant food - 1024 lbs,Three Wolf One Moon T-shirt,Dom Perignon 2000 Vintage

OUTPUT SAMPLE:

For each line of input, print out the maximum total score to two decimal places. For the example input above, the output should look like this:

21.00
83.50
71.25

THE ERROR

In my program i have created a 2D vector of strings

`std::vector<std::vector<std::string>`

I wish to store the names on each line from the input file as strings of the second dimension

lets say the name of the 2D-vector is a and i have a string "Dexobox Valektra" which needs to be pushed in location a[0][0] if the vectors could be treated as array.

What I tried using to push_back is a[i].push_back(token) which compiles but results in segmentation fault during runtime.

How do I fix this? is there a different way to push into 2nd Dimension of the vector?

I am using a routine for separating the names with comma delimiter and push_back into the vector

here is the code snippet:

void comma_seprate(std::string s, std::vector < std::vector<std::string> >& a , int i)
{
std::istringstream ss(s);
std::string token;
int j = 0;
while(std::getline(ss, token, ','))
{
    a[i].push_back(token); //this is  the line causing segmentation fault at runtime
    std::cout << token << std::endl;
    j++;
    }
}

Here is the complete code :

#include <iostream>
#include <string>
#include <cstdlib>
#include <fstream>
#include <vector>
#include <sstream>

#define DEBUG

void comma_seprate(std::string s, std::vector < std::vector<std::string> >& a , int i)
{
    std::istringstream ss(s);
    std::string token;
    int j = 0;
    while(std::getline(ss, token, ','))
    {
        a[i].push_back(token);
        std::cout << token << std::endl;
        j++;
    }
}

void split_string( std::string s, std::vector<std::string>& v, std::vector<std::string>& u )
{
    std::string delimiter = ";";
    v.push_back (s.substr(0, s.find(delimiter)));
    u.push_back (s.substr(s.find(delimiter)+1,s.size()));
}

int main ( int argc, char** argv )
{
    //variable for file name
    std::string filename;   
    //error handling for invalid argument size      
    if ( argc > 2 || argc < 2 )
    {
        std::cerr <<"filename missing! Usage: " << argv[0] << " <input_filename>"<< std::endl;
        return EXIT_FAILURE;
    }
//=========================================================================     
    //Using C style debugging : Any other way to do this in c++?
    #ifdef DEBUG
    std::cout << "filename :"<<filename << "\t  num_arguments: " << argc << std::endl;
    #endif
//=========================================================================     
    //opening the file for reading
    std::ifstream in(argv[1]);
    std::vector<std::string> line_vec;
    std::string temp_line;
    int line_count = 0;
    while(std::getline(in,temp_line))
    {
        line_count++;
        //Ignores any empty lines in the input file
        if(temp_line.empty())   
            continue;
        line_vec.push_back(temp_line);
    }

    //=========================================================================     
    #ifdef DEBUG
            std::cout <<"\nPrinting out contents of the line_vec" <<std::endl;
            for (int i=0; i<line_vec.size();i++){
                std::cout << line_vec[i] << std::endl;
            }
            std::cout << "The size of the line_vector is : " << line_vec.size() << std::endl;
    #endif
    //=========================================================================

    //Now splitting line by semicolon for customer names and product name seperation
    std::vector<std::string> customer_list;
    std::vector<std::string> product_list;
    for (int i=0; i<line_vec.size();i++)
    {
        split_string(line_vec[i], customer_list, product_list);
    }

    #ifdef DEBUG
            std::cout <<"=======================================================================" <<std::endl;
            std::cout <<"\nPrinting out contents of the customer_list " <<std::endl;
            std::cout <<"=======================================================================" <<std::endl;
            for (int i=0; i<customer_list.size();i++){
                std::cout << customer_list[i] << "\n\n" << std::endl;
            }
            std::cout << "The size of the customer_list vector is : " << customer_list.size() << std::endl;
            std::cout <<"=======================================================================" <<std::endl;
            std::cout <<"\nPrinting out contents of the product_list " <<std::endl;
            std::cout <<"=======================================================================" <<std::endl;
            for (int i=0; i<product_list.size();i++){
                std::cout << product_list[i] << "\n\n" << std::endl;
            }
            std::cout << "The size of the line_vector vector is : " << product_list.size() << std::endl;
    #endif

    //comma seprating the sting to get a list of customer names and product names
    std::vector < std::vector < std::string > > customer_name;
    std::vector < std::vector < std::string > > product_name;

    for(int i =0; i< customer_list.size(); i++)
    {
        comma_seprate(customer_list[i],customer_name,i);
        //comma_seprate(product_list[i],product_name,i);    
    }
}
Était-ce utile?

La solution

It means that a[i] has nothing in it and it overruns.

You have a vector of vectors

std::vector < std::vector<std::string> >& a

so you are pushing back elements inside the second vector

std::vector < std::vector<std::string> >& a
           // ^^^^^^^^^^^^^^^^^^^^^^^^ Inside this one here

but the other vector it still empty

 std::vector < std::vector<std::string> >& a
//^^^^^^^^^^^  that one is empty

so it is normal that if you do a[i] crashes... because a its empty.

What you could do, is create the inner vector first.

while(std::getline(ss, token, ','))
{
   std::vector<std::string> inner_vector;
   inner_vector.push_back(token);
   a.push_back(inner_vector); //this is  the line causing segmentation fault at runtime
   std::cout << token << std::endl;
   j++;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top