The program is all working now, but I'm worried because on the last linked lists assignment I got a C because I did not do the link correctly. My prof said that I did not create the links up correctly just used a stack to get descending in the last assignment. I want to make sure I did not do that this time.

Here's the code, can someone just tell me if I did it correctly.
Thanks!

#include "applicant.cpp"
#include <iostream>
#include <fstream>
#include <iomanip>

using namespace std;

struct Employeelink
{
 int id;
 int yearsWorked;
 char skillLevel;
 Applicant item;
 Employeelink *next, *before;
 
};

class Promosion
{
      protected:
         float value;
         Employeelink *start;
         Employeelink *lastone;
      public:
         Promosion(void); 
         void linkup(Employeelink, Applicant);
         int best(void);       
};

Promosion::Promosion()
{
   start = NULL;
   lastone = NULL;                  
}

void
Promosion::linkup(Employeelink applicant, Applicant app)
{
   Employeelink *another, *last, *here;
   another = new Employeelink;
   
   another->id = applicant.id;
   another->skillLevel = applicant.skillLevel;
   another->yearsWorked = applicant.yearsWorked;
   another->item = app;
   another->next = lastone;
   lastone = another;

   if(start == NULL)
   {
     start = another;
     start->before = NULL;
   }
}

int
Promosion::best()
{
  float best[18];
  int i = 0;
  float largest = 0;
  float totalBest;
  char bestSkill[18];
  int bestID[18];
  int bestYears[18];
  int bYears;
  int bID;
  char bSkill;
  //boolean once = false;
  
  
  Employeelink *point = lastone;
  while(point != NULL)
  {
    best[i] = point->item.return_value();
    bestSkill[i] = point->item.return_skill();
    bestID[i] = point->item.return_id();
    bestYears[i] = point->item.return_years();
    //cout << point->item.return_value() << endl;
    point = point->next;
    i++;
  }
  for(int x = 0; x < i; x++)
  {
      if(best[x] > largest)
      {
         largest = best[x];
         bYears = bestYears[x];
         bID = bestID[x];
         bSkill = bestSkill[x];
      }
  }
  cout << "ID: " << bID << " Sill Level: " << bSkill << " Years worked: " << bYears << " Value: " << largest << endl;
}

int
main()
{
 int x = 0;
 ifstream partin;
 Employeelink emp, temp;
 Promosion applicant;
 
 partin.open("applicnt.dat");  
 if(partin.fail())
 {
    cout << "Error: Unable to open file!" << endl;  
    partin.clear();
 }
 
 while(partin >> emp.id >> emp.skillLevel >> emp.yearsWorked)
 {
    Applicant app;
    app.store_id(emp.id);
    app.store_skill(emp.skillLevel);
    //cout << app.return_skill() << endl;
    app.store_years(emp.yearsWorked);

    applicant.linkup(emp, app);    
 }
 
 applicant.best();
             
 system("pause");
 return EXIT_SUCCESS;
}

Dani AI

Generated

Short answer: the list is not fully linked. The code sets each new node's next but does not update the existing head's before pointer (and the new node's before is left uninitialized). That leaves the doubly-linked structure broken after the first insertion, which matches 's observation.

A minimal, safe fix when inserting at the head (your lastone acts as the head) is to set both pointers and update the old head's before. For example:

void Promosion::linkup(const Employeelink& src, const Applicant& app)
{
    Employeelink *another = new Employeelink;
    another->id = src.id;
    another->skillLevel = src.skillLevel;
    another->yearsWorked = src.yearsWorked;
    another->item = app;

    // insert at head
    another->next = lastone;
    another->before = NULL;
    if (lastone != NULL)
        lastone->before = another;   // fix: point old head back to new node
    lastone = another;
    if (start == NULL)              // tail stays the same for first node
        start = another;
}

Other important points not covered in the thread:

  • best() can be simplified: traverse once and track the max value and its associated fields. Avoid fixed-size local arrays and uninitialized variables; handle empty lists explicitly.
  • Pass large objects by const reference (as shown) and avoid #include "applicant.cpp" — compile the .cpp separately and #include a header instead.
  • Add a destructor (or use smart pointers) to delete all nodes to avoid leaks.
  • Consider renaming start/lastone to tail/head for clarity so future readers don’t get confused.

If the assignment allows it, std::list implements a well-tested doubly-linked list — a good reference is std::list - cppreference. These changes will make the links correct and the traversal logic reliable.

Recommended Answers

All 2 Replies

I think that I may not have linked up correctly on this one, but I'm not sure.

I would agree that it does not look like it is quite linked up right.

Where is the Applicant class defined? (I see Applicant app but not the class, does this compile?)

I'm not sure, but it appears that you are repeating some (or all) of the data from the Applicant inside the Employeelink (which contains an Applicant). This is normally an indication of a faulty design.

The class Promosion appears to contain a (doubly) linked list of Employeelink instances.

The method Promosion::linkup(Employeelink applicant, Applicant app) appears to want to add a new Employeelink to the list. The method should always set both the next and before members of the Employeelink. The before is only set if the records we added was the first. And the next always points to where lastone was pointing, but then lastone is set to point to the new record.

I wish I could draw pictures in here...they seem to work the best to describe how this should work, but I'll try to do it in text.

Initially, the list is empty. (start = null, lastone = null)

When you add the first record (we'll call it A for now)

start -> A, lastone -> A, A.before -> null, A.next -> null

Now when you add B, you would normally add it at the head or the tail of the list (unless its an ordered list, but I don't see any support for that). This example adds it to the tail of the list.

start -> A, lastone -> B, A.before -> null, A.next -> B, B.before -> A, B.next -> null

When you add C, it just extends:
start -> A, lastone -> C, A.before -> null, A.next -> B, B.before -> A, B.next -> C, C.before -> B, C.next -> null

You don't normally have to re-assign all of the values in the method that adds the new object, just the ones that have changed.


Once you fix the add method to do something like the above, the best member will need to be changed too. To visit all of the members in the linked list, you either begin at start and follow next links or begin at lastone and follow before links.

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.