Hi,
I just got started with Linked lists and i am trying to read from a txt file to linked list. This is my first attempt. I have no idea how to achieve this. Any help will be greatly appreciated. Cheers.
There are two things I’d like you to consider:
1 make an append function to append vals to lists
and
2 the use of new instead of malloc
1) Making an append function will allow you to split up some of the work and allow you to see where you are having problems better, because things achieving different goals will be in different places. Also, using a class or struct in C++ introduces that concept of abstraction and encapsulation, both extremely important and helpful concepts that I suggest you look up if you haven’t learned them yet.
2) Using new is just easier. The only time maybe to use malloc in C++ code is for performance probably.
You seem to have some confusion about where to store the data. You allocate an array of 100 items in main and you also allocate space on the heap for each item with malloc in read_file(). Since this is a linked list, you should put them all on the heap.
Have you heard the phrase "garbage in / garbage out?" It means if you start with junk in your input, you'll always have junk in the output. In this program, you want to be 100% certain that you're reading and writing student_tag records correctly before you start dealing with the list.
I strongly urge you to start by writing read() and write() methods in student_tag to read and write one student:
student_tag *read_file() //readfile function
{
int count;
double total = 0;
string filename = "test.txt";
ifstream inFile;
inFile.open(filename.c_str());
if (inFile.fail()) // if file doesnt open successfully
{
cout << "The File was not opened successfully\n";
cout << "Please check that the file currently exists\n";
returnnullptr;
}
int i = 0;
student_tag *tail=nullptr;
hptr = nullptr;
student_tag *nptr = new student_tag;
while (nptr->read(inFile)) // until the end of the file
{
if (tail) {
tail->next = nptr;
} else {
hptr = nptr;
}
tail = nptr;
nptr = new student_tag; // create space for the next one
}
// You created space for the one that failed to read. Delete it
delete nptr;
inFile.close(); //close file
return hptr;
}
See how nicely this divides the code? Now read_file() is almost entirely about adding items to the list while student_tag::read() is all about reading an item from a stream.
Name: Andy
ID: Smithe
Course Name: 123456
Units: 0
If I knew what your input file looks like this might be different. Post the input file, if large 3 or 4 records will work, so that everyone will know what you are working with and can use the same information when testing.
You can add variables to read a complete record and print it out.
This is a quick to get the reading of the file correct then you can adjust the regular read function to match Then move on to creating the linked list.
When I finally figured out how to read the file your code started to make some sense.
You should delete the array you define in "main" and not pass it in the function call and remove it from the prototype and function definition. The program is about linked lists not arrays.
I finally realized that "hptr" is the "head". You can use "hptr" if you want, but put a comment after it to say it is the head. It makes understanding what it is easier.
Next you set "hptr" to NULL when defined. "nullptr", from C++11 on, would be the better choice, but you never give "hptr" a proper value, so your linked list has nowhere to start. Refer to dhayden's earlier code for some tips.
The line: inFile.open(filename.c_str());. Are you saying that the compiler is not using the C++11 standards or is it that you are being taught the old way of doing this? From C++11 on you can use ifstream inFile(filename);. Using a std::string works just fine. Also you can do this in one line instead of two.
In the read function taking out the array will make your code much easier to work with.
That's what i am not sure about. how do i read from file into a linked list? if it is in a function what do i return? I just can't seem to understand how data insertion into linked list works from a file.
Ok i figured out how to store data into the linked list from file. its really really messy but i have this assignment due tomorrow and i need it to work. So now i am storing everything in the read function. i wanted to use the function @dhayden wrote but i have no idea how to implement it. I can print the linked list in the read function but the assignment asks to have a separate display function. i am not sure how to display it now. Can someone have a look? Thanks so much guys. i really appreciate all your help.
You're display function looks good, but the read function is still not right. Since you're making a good effort, I'm going to give it to you. Look this over carefully and make sure you understand it.
There's still one thing missing: the average. You could either:
- add code to read() to compute the average once you've read the record, or
- remove avg from course_tag completely and compute the average in display() when you need it.
In general, it's bad to have redundant data and the avg is redundant. The problem is that you might change one of the grades and then forget to update avg. So I'd opt for the second method: remove avg from course_tag and compute the average in display
That could be because of while (inFile.peek() != EOF) // until the end of the file. May not always work. Plus I found an extra space at the end of the input input file.
Removing the space mace it work correctly and find the (eof) marker at the proper time.
As Andy pointed out, the problem is that your code assumes that the data ends immediately after the last record. A single space or new line will throw it off.
That's actually one reason that I suggested the read() and write() methods. Read() could return success when it read the entire record. That way an error anywhere along the way, even in the middle of a record, would be caught.
Here is a version with this logic added to the existing structure. After attempting to read a record, I check to see if the stream failed and exit if so.
BTW this demonstrates something that many programs don't understand: sometimes it makes sense to put the loop exit condition in the middle of the loop.