I am trying to use a linked list to read in data, do calcuations and then display it.
I am new to using linked lists, so right now I'm only trying to display them to see if it works.

#include <iostream>
#include <fstream>
#include <iomanip>
#include <list>

using namespace std;

int main() 
{
    char d_type;
    int d_quant;
    double d_price;
    
      struct data
    {
        char type;
        int quant;
        double price;

        data *next;  //ptr to next data set
    };

     data *head;
     head = NULL;

    ifstream widgets("widgets3.txt");

    if (!widgets) 
    {
       cerr << "Cannot open file" << endl;
    }

    for (int i=0; i<2; i++)
    {
     data *newdata;
     data *data_ptr;
         newdata = new data;
         newdata-> type = d_type;
         newdata-> quant = d_quant;
         newdata-> price = d_price;
         newdata-> next = NULL;
         
      if (!head)
         head = newdata;
      else
      {
        data_ptr = head;

        while (data_ptr-> next)
              data_ptr = data_ptr-> next;

        data_ptr->next = newdata;

      } //closes if(!head)


data *Display_ptr;
Display_ptr = head;

while (Display_ptr)
{
   cout << Display_ptr-> type << endl;
   cout << Display_ptr-> quant << endl;
   cout << Display_ptr-> price <<endl;

  Display_ptr = Display_ptr->next;
}
     } //closes for loop
 widgets.close();
     
 system ("PAUSE");
 return 0;   
};

This program works, but it loops the same thing over and over, and it doesn't move on to the next selection. I was thinking of putting it in an array, but when I try I get an error.

Recommended Answers

All 14 Replies

Two things you need to do:

(1) Read the data from the file (put widgets >> d_... statements first thing inside your for loop).
(2) Print the data only after you get all of it (close your for loop immediately after closing if(!head) ).

Two things you need to do:

(1) Read the data from the file (put widgets >> d_... statements first thing inside your for loop).
(2) Print the data only after you get all of it (close your for loop immediately after closing if(!head) ).

Thanks, that helped. I have another question. This is a portion of the file I'm supposed to read from:

R 150 1.00
R 130 2.00
S 145
R 50 2.50
S 75
S 180
R 50 4.00
R 30 5.00
R 40 5.50
P 30%

Is there a way that I can read, if(type=='R'), then read in col3, if (type=='S') read col2 and col3, and if(type=='P') calculate discount for the next 2 S records.

This is what I made so far involving these:

if (d_type=='R')
        {
           widgets >> d_type >> d_quant >> d_price;
           d_price = d_price + (d_price * .3);
           cout << fixed << setprecision(2) << d_price << endl;
        }
        else if (d_type=='P')
        {
             widgets >> d_type >> d_quant;
             cout << "Promo code found for " << d_quant << "%" << endl;
             }
        else if (d_type=='S')
        {
             widgets >> d_type >> d_quant;
             cout << quant << " sold: " << endl;
             }

Nothing gets displayed.

Nothing gets displayed because none of the conditions is met. If you want to check what d_type is, doesn't it make sense to get it
before the check? Try removing the three widgets >> d_type statements you have and put only one of them above your first if.

Nothing gets displayed because none of the conditions is met. If you want to check what d_type is, doesn't it make sense to get it
before the check? Try removing the three widgets >> d_type statements you have and put only one of them above your first if.

I get the idea, but I'm not sure how to put it into code. The only thing I can come up with is

for (int i=0; i<24; i++)
    {
      widgets >> d_type >> d_quant >> d_price;
      if (d_type=='R')
         widgets >> d_type >> d_quant >> d_price;
      else
          widgets >> d_type >> d_quant;
      
           
        if (d_type=='R')
        {
           markup_price = d_price + (d_price * .3);
           cout << d_quant << " " << "Widgets for " << fixed << setprecision(2) << d_price << endl;
        }
        else if (d_type=='P')
        {
             cout << "Promo code found for " << d_quant << "%" << endl;
             }
             
        else if (d_type=='S')
        {
             cout << d_quant << " widgets sold" << endl;
     }

which doesn't really make sense to me, but it was the only thing I could come up with. The output is wrong as well.

Ok, I'll write it in pseudocode:

for (i = 0 to 24)
{
    get type from file

    if (type is R)
    {
        get quantity and price from file

        do stuff...
    }

    else if (type is S)
    {
        get quantity from file

        do stuff...
    }

    else if (type is P)
    {
        get quantity from file

        do stuff...
    }
}

Can you translate the above to C++?

Or use switch statement not forgetting the breaks.

Ok, I'll write it in pseudocode:

for (i = 0 to 24)
{
    get type from file

    if (type is R)
    {
        get quantity and price from file

        do stuff...
    }

    else if (type is S)
    {
        get quantity from file

        do stuff...
    }

    else if (type is P)
    {
        get quantity from file

        do stuff...
    }
}

Can you translate the above to C++?

Yes, I did that. It definitely helped! Thanks a lot. Now I need to get to the actual program, where I'm supposed to traverse through a list of data, and depending on the type of letter it is in front, it has to do a certain part.

This is some of the data from the file:

R 150 1.00
R 130 2.00
S 145
R 50 2.50
S 75
S 180
R 50 4.00

If it is an R, read in the data.
If it is an S, the quantity sells for that amount from the first R till there is none anymore. So, R reads in 150 for $1.00, then R for 130 for 2.00, then S which sells 145 for $1.00, R for 50 for 2.50, then S where 5 is from the 5 remaining from $1 and then 45 from 130 for $2.00 That is the logic.


I am not exactly sure how to do that. The logic of traversing confuses me a bit.

This is my code:

#include <iostream>
#include <fstream>
#include <iomanip>
#include <list>

using namespace std;

int main() 
{
    char d_type;
    int d_quant;
    double d_price;
    double markup_price;
    double total;
    
      struct node
    {
        char type;
        int quant;
        double price;

        node *next;  //ptr to next data set
    };

     node *head;
     node *trail; //traverse the list

     head = new node;
     head->next = 0;
     node *newnode;
     node *node_ptr;

         head = new node;
         head-> type = d_type;
         head-> quant = d_quant;
         head-> price = d_price;
         head-> next = NULL;
         trail = head; //points to the first node
         
         //if empty, set head to new node
      if (!head)
      {
         while (trail->next !=0)
         trail = trail->next;
      }
  trail->next = new node;  // Creates a node at the end of the list
  trail = trail->next;     // Points to that node
  trail->next = 0;         // Prevents it from going any further
  trail->type = d_type;
  trail->quant = d_quant;
  trail->price = d_price;

/*
      else
      {
        node_ptr = head;

        while (node_ptr-> next !=NULL)
              node_ptr = node_ptr-> next;

        node_ptr->next = newnode;

      } //closes if(!head)
      */
    ifstream widgets("widgets3.txt");

    if (!widgets) 
    {
       cerr << "Cannot open file" << endl;
    }

        for (int i=0;i<24;i++)
    {

       widgets >> d_type;

        if (d_type=='R')
        {
           widgets >> d_quant >> d_price;
           markup_price = d_price + (d_price * .3);
           cout << d_quant << " " << "Widgets for " << fixed << setprecision(2) << d_price << endl;
        }
        else if (d_type=='P')
        {
             widgets >> d_quant;
             cout << "Promo code found for " << d_quant << "%" << endl;
             }
             
        else if (d_type=='S')
        {
             widgets >> d_quant;  
             cout << d_quant << " widgets sold" << endl;
        }

      
     } //closes for loop     
 widgets.close();
     
 system ("PAUSE");
 return 0;   
};

I would use two node pointers for this. One always pointing to the first element of my list
and one always pointing to the last one. Much like the head and trail pointers you have.

When I encountered an 'R', I would create a new node
and push it to the end of my list, using the trail pointer.

When I encountered an 'S', I would do something like this:

loop while S_quantity != 0
{
    if head_quantity > S_quantity
    {
        // sell stuff and update head and S
    }
    else if head_quantity <= S_quantity
    {
        // sell stuff and update head and S
    }

    if head_quantity == 0, pop head
}

I would use two node pointers for this. One always pointing to the first element of my list
and one always pointing to the last one. Much like the head and trail pointers you have.

When I encountered an 'R', I would create a new node
and push it to the end of my list, using the trail pointer.

When I encountered an 'S', I would do something like this:

loop while S_quantity != 0
{
    if head_quantity > S_quantity
    {
        // sell stuff and update head and S
    }
    else if head_quantity <= S_quantity
    {
        // sell stuff and update head and S
    }

    if head_quantity == 0, pop head
}

I have been reading and trying to make this work. I have tried the 'R' part, and this is what I came up with:

if (d_type=='R')
        {
           widgets >> d_quant >> d_price;                        
           trail->next = new node;  // Creates a node at the end of the list
           trail = trail->next;     // Points to that node
           trail->quant = d_quant;
           trail->price = d_price;
           markup_price = d_price + (d_price * .3);
           cout << trail->quant << " " << "Widgets for " << fixed << setprecision(2) << d_price << endl;
        }

This seems correct, but I am just making sure that I didn't miss anything.

Looks good to me too. Just don't forget to add a trail->next = 0; statement at the end, to show that trail is the last node of your list.

Also, there's a bug in the pseudocode for 'S' I posted above. The first
line should be -> loop while S_quantity != 0 [B]&& head != 0[/B] (because you don't want to try to operate on an empty list, of course!)

Looks good to me too. Just don't forget to add a trail->next = 0; statement at the end, to show that trail is the last node of your list.

Also, there's a bug in the pseudocode for 'S' I posted above. The first
line should be -> loop while S_quantity != 0 [B]&& head != 0[/B] (because you don't want to try to operate on an empty list, of course!)

Thanks. I am having trouble with the 'S' portion of it.

else if (d_type=='S')
        {
             widgets >> d_quant;
             markup_price = head->price + (head->price * .3);
             head->next = new node;
             head = head->next;
             head->quant = d_quant;
             head->price = d_price;
             head->next = NULL;
             
             while (d_quant!=0 && head != 0)
             {
                   if (head->quant > d_quant)
                   {
                      total = head->price * d_quant;
                      cout << head->quant << " at " << markup_price << " each" << '\t' << "  Sales: $" << fixed << setprecision(2) << total << endl;
                      head->quant = head->quant - d_quant;
                   }
                   else if (head->quant <= d_quant)
                   {
                     units_remain = d_quant - head->quant;
                     head->next;
                     head->quant = head->quant - units_remain;                     
                     total = head->price * d_quant;
                     cout << head->quant << " at " << markup_price << " each" << '\t' << "  Sales: $" << fixed << setprecision(2) << total << endl;
                     head->quant = 0;
                   }
                   else if (head->quant==0);

I don't seem to have the head pointer to go to the start of the list, and I am getting confused, the more I look at the code.

Mmmm... You shouldn't add anything to your list when you encounter an 'S'.
Your list should only consist of 'R'-type nodes. When you encounter an 'S',
you should just modify the head node (which should be an 'R' node, since
you only add 'R's to your list) and perhaps remove it (if its quantity drops
to zero). Also, note that the check you do to remove the head should be
independent from the checks you do to update the head quantity. That is,

it should be...

if (head->quant > d_quant) { /*...*/ }
else if (head->quant <= d_quant) { /*...*/ }

if (head->quant == 0) { /*...*/ }

instead of...

if (head->quant > d_quant) { /*...*/ }
else if (head->quant <= d_quant) { /*...*/ }
else if (head->quant == 0) { /*...*/ }

Finally, when you decrease head->quant , you should also decrease d_quant by
the same amount, or else this -> while ([B]d_quant!=0[/B] && head != 0) won't work.

I am getting confused the more I look at the code.

Then don't look at the code. Get a pencil and a piece of paper and
write your algorithm in english. After you make sure it does what it's
supposed to do, converting it to C++ code shouldn't be a problem.

So, I came back to working on this problem and I still have trouble with the 'S' portion.

I am getting the idea of it, but I am having trouble of how to make the list move onto the next node. I know that the node is supposed to follow the 'R' case, which would be trail, but that's as far as I can think of. This is what I came up with:

while (d_quant!=0 && head != 0)
           {
             if (head->quant > d_quant)
             {
              markup_price = head->price + (head->price * .3);
              total = markup_price * d_quant;
              head->quant -= d_quant;
              cout << d_quant << " at " << markup_price << " each" << '\t' << "  Sales: $" << fixed << setprecision(2) << total << endl;
              d_quant=0;
             }
             else if (head->quant <= d_quant)
             {
              int units_remain = d_quant - head->quant;
              head->quant -= units_remain;
              total = markup_price * d_quant;
              cout << head->quant << " at " << markup_price << " each" << '\t' << "  Sales: $" << fixed << setprecision(2) << total << endl;
              d_quant=0;
              head->quant=0;
             }
             if (head->quant==0)
             {
               head=trail->next;
             }
          }
       }

I am having trouble of how to make the list move onto the next node.

You mean you have trouble popping the head?

This should do it:

create a temporary node pointing to head;
set head to point to the node next to it;
use delete on the temporary node above;

Don't you think you're getting a bit too much help here?
Are we going to share the grade you'll get on this? :D

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.