Linked List

100 Mary
110 John
111 David
112 Sofia
121 Maria
144 Mia

Lets say given above is the user.txt file and i want make a function to read all these data using a linked list with struct .

Any idea how to create this??
https://www.cplusplus.com/forum/beginner/280683/
Well you already know about reading files and structures.
Enough to at least make a start on the problem.

Can you use https://en.cppreference.com/w/cpp/container/list or is the exercise to roll your own list?
well yeah i know that but my concern is to roll my own list using linked list
https://en.wikipedia.org/wiki/Linked_list

You could make a start by just using std::list while you get the rest of the code working.

So when you replace std::list with mylist, you'll know where the problem is going to be when it doesn't work, and you'll know that you've done it right when it does work.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>
using namespace std;

struct node
{
   string id, name;
   node *next;
};

void print( node *n )
{
   for ( ; n; n = n->next ) cout << n->id << ' ' << n->name << '\n';
}

int main()
{
   ifstream in( "user.txt" );
   node *root = nullptr, *tail = nullptr;
   for ( string id, name; in >> id && getline( in, name ); tail = ( root ? tail->next : root ) = new node{ id, name, nullptr } );
   print( root );
}


100  Mary
110  John
111  David
112  Sofia
121  Maria
144  Mia



when i run the this program it has an error on nullptr how do i correct this?
jabeh wrote:
when i run the this program it has an error on nullptr how do i correct this?


Well, you could use NULL instead of nullptr.

However, if your compiler won't cope with at least C++11 (as @salem c noted) then you are missing out on a lot.
This version doesn't use explicit nullptr:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;

struct node {
	string id, name;
	node *next {};
};

void print(const node* n) {
	for (; n; n = n->next)
		cout << n->id << ' ' << n->name << '\n';
}

int main() {
	ifstream in("user.txt");

	if (!in)
		return (cout << "Cannot open file\n"), 1;

	node *root {}, *tail {};

	for (string id, name; in >> id && getline(in >> ws, name); tail = (root ? tail->next : root) = new node {.id = id, .name = name});

	print(root);
}

 
tail = ( root ? tail->next : root ) = new node{ id, name, nullptr }


I decided so that I can get myself up to par I'm going to spend the next week or so reading beginners questions.

I found the above code really clever, and think I understand it.

Let me see if I can put it in words: if root is false then root equals a new node, else the take the tail's next and make it a new node, regardless the tail becomes next.

Please let me know if you find this sentence correct?
Last edited on
It's to do really with placement of the first node, depending on whether we have an empty list or not.

The right-hand assignment is done first.

If root is non-null then there is an existing list and the (current) tail->next pointer is set to point to a new node. In the one-off case that root is null then the list is currently empty and we have to set root to the new node.

After all these shenanigans the left-hand assignment is done and the tail pointer is set to point to the newly-assigned node.


It has probably been abbreviated beyond utility, I admit. I usually do linked-list assignment with several more easy-to-read if blocks. The assembled code probably looks the same.


To be fair, I think I pinched the idea from @dutch at some point - just can't remember where. It was one of his single-line statements that left me in awe.




If you don't mind the reversed order in a forward list then you can construct more easily by adding at the start instead and ditch the tail pointer.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <fstream>
using namespace std;

struct node
{
   string id, name;
   node *next;
};

void print( node *n )
{
   for ( ; n; n = n->next ) cout << n->id << ' ' << n->name << '\n';
}

int main()
{
   ifstream in( "user.txt" );
   node *root = nullptr;
   for ( string id, name; in >> id && getline( in, name ); root = new node{ id, name, root } );
   print( root );
}

Entries come out in reverse order:
144  Mia
121  Maria
112  Sofia
111  David
110  John
100  Mary

though you can fix that by changing the print() function:
1
2
3
4
5
6
7
8
void print( node *n )
{
   if ( n )
   {
      print( n->next );
      cout << n->id << ' ' << n->name << '\n';
   }
}

to give
100  Mary
110  John
111  David
112  Sofia
121  Maria
144  Mia



Last edited on
Topic archived. No new replies allowed.