Hello,

I am having trouble with a program I am writing.
The problem is that I need to take information from a text file, read it, and then output the information into another text file.
I keep getting this output:

<ProductSummary>0015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A00015D7A0
</ProductSummary>

I need it to output something like this:

Planner = " ";
CommGrp = " ";
SalesGrp = " ";
PartNum = " ";
AvgPrice = 0.00;
NumSold = 0;
PartTotal = 0.00;

I also need to sort the information, but I think once I get the information written to a text file correctly, I can figure out the rest.

Here is my code:

/*
Write a program which will read in an input file containing 
a list of products and details about each product.  The program 
will sort the products by product group and part number.  The 
program should summarize sales of each product, both quantity 
of units and dollars of sales.  The program will output two 
files, a summary file containing part information and amount 
sold; the second will be the sorted list of part numbers by part 
group.

Requirements:

- Write a C++ program which will read in the input file partdetail.txt (File layout below)
- Create a class which is made up of private variables for each field in the input file
- Write the following public member functions to include in the class

    - A function that outputs to a file called Part Summary which will output:
        - Each Sales Group
        - The total count of parts sold from that sales group
        - The total dollars sold from each sales group
        - the percentage each group is compared to the grand total of parts sold
            - Hint:  You will need a total dollar accumulator or a member function that 
            calculates the grand total of all sales in the class

    - A function that sorts all of the values in the class array
        - Hint:  You will need to declare an array to read in each data file into the 
        class you create.  This member function should then sort the values in the array.
        - The sort criteria is:  
            - Primary sort on Sales Group
            - Secondary sort on Part

- Write a function to output the sorted partdetail file to a file named sortedparts.txt 
- All file output should contain proper formatting (without commas**):  IE, if the field represents dollars, 
then a dollar sign should be present.  If a field represents a %, then the 
% symbol should be present.

**Extra points

*/

#include <iostream>
#include <fstream>
#include <cctype>
#include <cstdlib>
#include <string>

using namespace std;

class ProductSummary
{
public:

    ProductSummary();

    char PS[42];

    friend ostream& operator << (ostream& outxml, const ProductSummary& PS);
    void ReadProductFile(ProductSummary, ifstream& in_file);


    // void calc


private:

    string 
        Planner,
        CommGrp,
        SalesGrp,
        PartNum;

    double AvgPrice;
    int NumSold;
    double PartTotal;


};

ProductSummary::ProductSummary()
{
//This is the format:

Planner = " ";
CommGrp = " ";
SalesGrp = " ";
PartNum = " ";
AvgPrice = 0.00;
NumSold = 0;
PartTotal = 0.00;

}


void ProductSummary::ReadProductFile(ProductSummary, ifstream& in_file)
{

    //placeholders for the position in the string (in file partdetail.txt)
    int current_pos, 
        prev_pos;

    //Names of all of the strings to be read in
    string 
        file_input,
        nextPlanner, 
        nextCommGrp, 
        nextSalesGrp, 
        nextPartNum, 
        nextAvgPrice, 
        nextNumSold, 
        nextPartTotal;

    getline(in_file, file_input);

    current_pos = file_input.find(",");

    prev_pos = current_pos + 1;

        nextPlanner = file_input.substr(0, current_pos);
            prev_pos = current_pos + 1;
            current_pos = file_input.find(",", prev_pos);

        nextCommGrp = file_input.substr(prev_pos, current_pos - prev_pos);
            prev_pos = current_pos + 1;
            current_pos = file_input.find(",", prev_pos);

        nextSalesGrp = file_input.substr(prev_pos, current_pos - prev_pos);
            prev_pos = current_pos + 1;
            current_pos = file_input.find(",", prev_pos);

        nextPartNum = file_input.substr(prev_pos, current_pos - prev_pos);
            prev_pos = current_pos + 1;
            current_pos = file_input.find(",", prev_pos);

        nextAvgPrice = file_input.substr(prev_pos, current_pos - prev_pos);
            prev_pos = current_pos + 1;
            current_pos = file_input.find(",", prev_pos);

        nextNumSold = file_input.substr(prev_pos, current_pos - prev_pos);
            prev_pos = current_pos + 1;

        nextPartTotal = file_input.substr(current_pos + 1, file_input.length() - current_pos);
            current_pos = file_input.find(" ", prev_pos);

    Planner = nextPlanner;
    CommGrp = nextCommGrp;
    SalesGrp = nextSalesGrp;
    PartNum = nextPartNum;
    AvgPrice = atof(nextAvgPrice.c_str());
    NumSold = atoi(nextNumSold.c_str());
    PartTotal = atof(nextPartTotal.c_str());


}

/*ostream& operator << (ostream& outxml, const ProductSummary& PS)
{

    outxml << PS.Planner;

    return outxml;


}*/


/*
void Something2, ReadFile??
{
This is where the calculations go.
}

void Something3, ReadFile??
{
This might be where the first and second SORTS go.  Maybe separate sections?
}

Don't forget!
Something4 = atoi(Something.c_str());
turns string into integer
*/

int main()
{

    ProductSummary PS[42];
    //typedef ProductSummary* PSPtr;
    //PSPtr pPS;

    ofstream txtout;
    ifstream in_file;
    int i, final_count;

    txtout.open("sortedparts.txt");
    if (txtout.fail())
        exit(1);


    in_file.open("partdetail.txt");
    if (in_file.fail())
        exit(2);

    i = 0;

    while (!in_file.eof())
    {
    PS[i].ReadProductFile(PS[i], in_file);
    //PS[i].calc?(PS[i])

    i++;
    }

    /*
    pPS = new ProductSummary[42];
    in_file.close();

    in_file.open("partdetail.txt");
    if (in_file.fail())
        exit(2);

    i = 0;

    while (!in_file.eof())
    {
        pPS[i].ReadProductFile(pPS[i], in_file);
        //calc?
        i++;
    }

    */

    final_count = i;
    in_file.close();

    txtout << "<ProductSummary>";
    for (i = 0; i < final_count; i++)
    txtout << PS;
    //txtout << "Did it work?";
    txtout << '\n'
        << "</ProductSummary>";

    txtout.close();



return 0;
}

It should compile cleanly, but I am confused as to where to go from here.

If someone were to assist me, I would really appreciate it! Even advice would help!

Thank you so much!

void ProductSummary::ReadProductFile(ProductSummary, ifstream& in_file)

Delete the first parameter to that function, its not necessary to pass it. Also in that function use stringstream class to parse the line into its individual words instead of using the string's find() method. stringsteam is a whole lot easier

#include <sstream>

...
..

void ProductSummary::ReadProductFile(ifstream& in_file)
{


    //Names of all of the strings to be read in
    string 
        file_input,
        nextPlanner, 
        nextCommGrp, 
        nextSalesGrp, 
        nextPartNum, 
        nextAvgPrice, 
        nextNumSold, 
        nextPartTotal;

    getline(in_file, file_input);
    streamstring str(file_input);
    getline(str, nextPlanner, ',');
    getline(str, nextCompGrp, ',');
    getline(str, nextSalesGrp, ',');
    getline(str, nextPartNum, ',');
    getline(str, nextAvgPrice, ',');
    getline(str, nextNumSold, ',');
    getline(str, nextPartTotal, ',');
    Planner = nextPlanner;
    CommGrp = nextCommGrp;
    SalesGrp = nextSalesGrp;
    PartNum = nextPartNum;
    AvgPrice = atof(nextAvgPrice.c_str());
    NumSold = atoi(nextNumSold.c_str());
    PartTotal = atof(nextPartTotal.c_str());


}

You need to narrow down precisely where the problems is. Several possiblities.

  • Input from the file is not successfully going into the objects.
  • Objects are not being outputted correctly.
  • All sorts of subsets of the above.
  • You have a whole bunch of "PS" variabes in there. One of them is a class data member defined as an array of 42 characters. One of them is an array of 42 ProductSummary objects. One them is a PARAMETER of a class member function. The other is a paramater to the friend << operator. Etc. Too many different things with the same name. Can you keep them straight? I can't.

My approach would be to make sure the output functionality works first. That means don't try to read from the file. Hard code a constructor to give the object easy to check values.

I'm highly suspicious of line 236. You appear to be printing an ARRAY of ProductSummary here instead of one. Your << operator takes a SINGLE ProductSummary, not an array. I'll take your word that it compiles. Seems like you should be looping through the array and printing one at a time. I'll also note that the << operator function is commented out.

I haven't tried to compile it. Seems like it shouldn't compile. Even if it does, I can't imagine how a default << operator could possibly write it the way you want it written in line 236.

So write the << operator, then change line 236 to loop through one element at a time. See if that solves anything.

Okay, looked at your code again. Line 236. You ARE looping through. That means you intended to write one element at a time, as I suggested. However, you are not writing one at a time. You want this.

for (i = 0; i < final_count; i++)
    txtout << PS[i]; // brackets like everywhere else in your code

I tried adding the bracket [i] already, and it comes up with an error for some reason.

.exe not found or not built by the last incremental link; performing full link
FinalCode1_vs.obj : error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class ProductSummary const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVProductSummary@@@Z) referenced in function _main
c:\users\vito\documents\visual studio 2010\Projects\CISFinalExam_vs\Debug\CISFinalExam_vs.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I'm not quite sure why...

I really appreciate you guys helping. I've been working on this for many hours now, and I feel like I have been running around in circles.

@Ancient Dragon
I also tried the sstream, and it didn't seem like my program recognized the syntax. There were many errors that had populated when I tried to compile, including the "stringstream's" and the "str's" in that code.

Did you include the <sstream> header file as I posted with my example?

Yep. And it had those errors :(

I'm not quite sure why...

You can't use an operator function that's commented out. You need to uncomment it, write it, or not use the << operator. Changing it to what you have may make it compile, but it sure isn't going to run correctly. Looks like the compiler thinks you want to print the address of the array, so I guess that's why it compiled, but gave jibberish.

commented: Oops! +14

streamstring

I think you got a little dyslexic in the code there AD. To the OP, you want "stringstream".

[EDIT]
Line number is line 22 in Ancient Dragon's code
[/EDIT]

EDIT: I will retry the stringstream. Yes, it was transposed :)

I commented out the friend, but that didn't affect anything.
Maybe on a simpler level, how would I get one of my private variables (required as per the directions) to show up in the text file individually, instead of trying to get the array of everything? Even with minor tweaks, I cannot get the first array to write in the text file, but if there was maybe a way to do the variables separately?

I'm terrible with the explanation with the c++ language, but I do understand what you guys are saying.

Here are the errors shown when I tried it:

>
c:\users\vito\documents\visual studio 2010\projects\testfinal1\testfinal1\test1.cpp(245): error C2660: 'ProductSummary::ReadProductFile' : function does not take 2 arguments
c:\users\vito\documents\visual studio 2010\projects\testfinal1\testfinal1\test1.cpp(263): error C2660: 'ProductSummary::ReadProductFile' : function does not take 2 arguments
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Okay, I fixed that line and it compiled just fine. But I still get the same problem as before with the jibberish in the text file.

Fix the "streamstring". See if those errors go away when you do that.

I commented out the friend, but that didn't affect anything.

You need UN-COMMENT out what's commented out. That means you need to uncomment out that entire function. The compiler can't find it when it's commented out.

As I mentioned in the first post, start experimenting without any files, and no arrays. They unnecessarily complicate things. You need the << operator in order to print debugging messages anyway, so do that first. If you've never written a << operator, I'd suggest setting this aside and taking a quick tutorial. I'll reiterate that the easiest way to do that is to simply hardcode the constructor, which you've already done, but do it with some different values temporarily. main is then three lines of code.

ProductSummary x;
cout << x;
return 0;

Make sure that prints right, then go do the rest of it.

Ah.. I think I figured it out. I am noticing that the only way to do this is by making sure it is a public variable. So.. I created linking variables to my private ones, but I don't know if this is cheating the restrictions I'm given?

Example:

Public:
string getPlanner;

Private:
string Planner;

...
Planner = getPlanner;

Getters and setters are functions. Your variables should be private and the getters and setters public. Duplicate variables are counterproductive. You say that the only way to do "this" is to make a public variable. What's "this"? the << operator? The << operator needs to be a friend, so private variables shouldn't be a problem. That's the whole point of MAKING it a friend and that's why you'll almost never see a non-friend << operator in a class.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.