1

I'm currently working on an assignment, and I think I have successfully made a linked list of the elements in a periodic table read from a file (amount of elements will vary).

But I'm now trying to create a pointer to an array of pointers to Element (Element **ptr = new Element *[n] is found in main file and is passed into read_table). I'm not sure of how I should do this though. Is what I'm doing correct? Or should it be ptr[i] -> *head.pElement?

Element struct has been created in another file and table will be a prototype in that file.

struct Node {
    Element *pElement;
    Node *next;
};

int table(Element **ptr) { // Was originally Element **&ptr, but that might have been supposed to be for my prototype
    Node *head = new Node; // starts off the linked list
    Node *temp = new Node; // temp node to make switch for head node
    Element e; 

    int counter = 0; // counter to keep track of num of elements

    // open input file
    ifstream infile;
    infile.open(file_path_will_be_placed_here);

    // loop to read file and create linked list
    while(infile >> e.atomicNumber) {
        infile >> e.name;
        infile >> e.abbreviation;
        infile >> e.mass;

        head -> pElement = new Element; // the node's pElement points to a new Element
        *head -> pElement = e; // sets node's pElement to the read data stored in e
        *temp -> next = head; // might have to point to &head
        head = temp; // head points to where temp does
        temp = new Node; // temp points to new node

        counter++; // increment counter every time for every element
    }

    for(int i = 0; i < counter; i++) {
                // confused !@!@?
            ptr[i] -> head.pElement;
    }
8
  • 1
    "Element **&ptr" wheehaaa?? what's that supposed to be? And, no, i don't think your while loop creates a sound linked list. Better seperate this from the function table(). Commented Oct 21, 2018 at 3:40
  • Umm... wait... A pointer to pointer to Element reference?... Very good candidate for a conversion with the duck... See: How to debug small programs Commented Oct 21, 2018 at 3:43
  • 1
    @DavidC.Rankin Or a reference to a pointer to a pointer to Element? ;) More was asking about its purpose, though. Commented Oct 21, 2018 at 3:45
  • @Swordfish Yes. Table is supposed to return the number of elements read from the file and, via a reference parameter, a pointer to an array of pointers to the elements read. The reading in of the table is supposed to be in the table function. Ohh I think that was pose to be in my function prototype, not the function header, Commented Oct 21, 2018 at 3:46
  • @Amai Why do you think you need a linked list then? Please step through your code with a debugger. Commented Oct 21, 2018 at 3:47

1 Answer 1

2
while(infile >> e.atomicNumber) {
    infile >> e.name;
    infile >> e.abbreviation;
    infile >> e.mass;

First of all, you want all extractions from infile to succeed to keep the loop running:

while (infile >> e.atomicNumber >> e.name >> e.abbreviation >> infile >> e.mass) {

Then let's have a look at your "List":

    head->pElement = new Element;  // ok
    *head->pElement = e;           // ok
    *temp->next = head;
    head = temp;                   // now you have a head with a pElement pointing to garbage
                                   // and a next pointing to the node with pElement pointing
                                   // to the Element you just read, the next of that Node
                                   // points to garbage, though *)                                     
    temp = new Node;               

    counter++;
}

*) so when you try to go through the list you will have to ignore the pElement of head but also won't know when you reached the lists end cause you never set next-pointer to nullptr so it could be destinguished from a pointer to a next node.

int table(Element **&ptr) // should return std::size_t
{
    ifstream infile{ "test.txt" };
    int num_elements{}; // should be std::size_t
    Element e;
    Node *head{};
    Node *current{};
    while (infile >> e.atomicNumber >> e.name >> e.abbreviation >> e.mass) {

        if (!head) {
            head = new Node;
            head->next = nullptr;
            head->pElement = new Element;
            *head->pElement = e;
            current = head;
        }
        else {
            current->next = new Node;
            current = current->next;
            current->next = nullptr;
            current->pElement = new Element;
            *current->pElement = e;
        }
        ++num_elements;
    }

    Element **array = new Element*[num_elements];

    current = head;
    Node *temp;
    for (int i = 0; i < num_elements && current; ++i) {
        array[i] = current->pElement;
        temp = current;
        current = current->next;
        delete temp;
    }

    ptr = array;
    return num_elements;
}

int main()
{
    Element **elements;
    int num_elements = table(elements);

    // do something with elements

    for(int i{}; i < num_elements; ++i)
        delete elements[i];
    delete [] elements;
}


The Realtm Solution:

#include <vector>
#include <string>
#include <iterator>
#include <fstream>

struct Element {
    int atomicNumber;
    std::string name;
    std::string abbreviation;
    double mass;
};

std::istream& operator>>(std::istream& is, Element &element)
{
    Element e;
    if (!(is >> e.atomicNumber >> e.name >> e.abbreviation >> e.mass))
        return is;
    element = e;
    return is;
}

std::vector<Element> read_elements()
{
    std::ifstream infile{ "test.txt" };
    std::vector<Element> elements{ std::istream_iterator<Element>{ infile },
                                   std::istream_iterator<Element>{} };
    return elements;
}
Sign up to request clarification or add additional context in comments.

23 Comments

The problem is I never learned any of the vector things and the std:: 's. But on the topic of the initial starter node. Would it be fine if i just set *head -> next = NULL;? I just assumed I wouldn't need to because I would be using the counter to place the elements in an array of pointers to the elements,
The problem with the not set pElement of the head stays the same.
Ohhh I see what u mean. I put in the *temp -> next = head. So it would always have an empty node. Can I ask what you mean by "if (!head)", does it mean "if head is not defined"?
By doing " Node *head{}; " aren't you pretty much setting it as nullptr by default until you define it as something? Sorry bout this, new to C++ so I'm still trying to get used to this.
Yes, type foo{} is zero-initialization which is nullptr for pointers. "until you define it as something?" that is the definition. Everything that follows are assignments.
|

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.