how to avoid same input id value in c++ - c++

how to avoid double id in linked listed, example, i have id, name, gol, so firtst, i input id= 12, name=jon gol=A, when i input again. id=12, its show message "Id cant be same". input again can you help
this is my code for insert linked list first node,
#include <iostream>
#include <string>
#include <conio.h>
struct node {
int id;
char name[20], gol;
node *next;
};
node *head = nullptr;
node *tail = nullptr;
void tambah_awal_list() {
int id;
char name[20];
char gol;
node *baru = new node;
baru->id=head->id;
std::cout << "Id : ";
std::cin >> baru->id;
if (head->id == baru->id){
std::cout << "Id cant be same"<<std::endl;
}
std::cout << "Name : ";
std::cin >> baru->name;
std::cout << "Blood type (A/B/O) : ";
std::cin >> baru->gol;
if(head == nullptr) {
head = baru;
head->next = nullptr;
tail = head;
} else {
baru->next = head;
head = baru;
}
}
what should i change?

It depends on the spec and performance requirements.
If id could be decided by code instead of user input, then you just need to have an global counter increment every time a node is created.
You have to handle it carefully under multi-threading cases or very large number when number of nodes is out of range of int.
// Global variable or class member
int g_nextID = 0;
int generateID(){return ++g_nextID;}
void generate(){
node* n = new node();
n->id = generateID();
// ...
}
Use std::unordered_set<int> which takes O(1) time and O(N) space.
// A global variable or class member
std::unordered_set<int> g_used;
node *head = nullptr;
node *tail = nullptr;
void generate(){
// Inside the function
int id;
// Get user input into id
// ...
// Checking if used
if(g_used.find(id) == g_used.end()){
// Create the node
// ...
g_used.insert(id); // Save it
}else{
// Error handling.
}
}
void removeNode(int id){
// Remove it from list
// ...
// Remove it from set
g_used.erase(id);
}
Lookup the nodes, but it takes O(N) times.

Related

linked list from the text file by words

i wanted to read the text file by words and then apply each word for the linked list
but when i apply the whole content will goes to the first node of linked list
any idea what do i have to modify in the code
updated
i wander how can i iterate the word over the linked list i know i need another loop inside the while but i do not how do to it
it is build with C++
the file is working it showing by words but what i do not understand is how to take the words to be linked to each other
code:
#include <bits/stdc++.h>
#include <iostream>
#include<string>
using namespace std;
class LinkedList{
// Struct inside the class LinkedList
// This is one node which is not needed by the caller. It is just
// for internal work.
struct Node {
string x;
Node *next;
};
// public member
public:
// constructor
LinkedList(){
head = NULL; // set head to NULL
}
// destructor
~LinkedList(){
Node *next = head;
while(next) { // iterate over all elements
Node *deleteMe = next;
next = next->next; // save pointer to the next element
delete deleteMe; // delete the current entry
}
}
// This prepends a new value at the beginning of the list
void addValue(string val){
Node *n = new Node(); // create new Node
n->x = val; // set value
n->next = head; // make the node point to the next node.
// If the list is empty, this is NULL, so the end of the list --> OK
head = n; // last but not least, make the head point at the new node.
}
// returns the first element in the list and deletes the Node.
// caution, no error-checking here!
string popValue(){
Node *n = head;
string ret = n->x;
head = head->next;
delete n;
return ret;
}
// private member
private:
Node *head; // this is the private member variable. It is just a pointer to the first Node
};
int main() { //linkedlist
LinkedList list;
//string usama="usama";
//list.addValue(usama);
//list.addValue("h");
//list.addValue("u");
//cout << list.popValue() << endl;
//cout << list.popValue() << endl;
//cout << list.popValue() << endl;
// because there is no error checking in popValue(), the following
// is undefined behavior. Probably the program will crash, because
// there are no more values in the list.
// cout << list.popValue() << endl;
//file
// filestream variable file
fstream file;
string word, t, q, filename;
// filename of the file
filename = "file.txt";
// opening file
file.open(filename.c_str());
// extracting words from the file
while (file >> word)
{
list.addValue(word);
cout<<list.popValue()<<endl;
// displaying content
//cout << word << endl;
}
return 0;
}
i know maybe something wrong with the while loop but i am stuck at it
You have several problems. The first is popValue() does not handle the case where head == nullptr. This will likely cause a segfault when you attempt string ret = n->x; You can add a check on head and initialize ret to avoid this issue (the empty ret will be used to terminate the iteration later)
string popValue(){
Node *n = head;
string ret {};
if (!head) /* validate head not nullptr */
return ret;
ret = n->x;
head = head->next;
delete n;
return ret;
}
Next, as addressed in the comment, you use 1 loop to addValue and popValue. That defeats the purpose of your list because every node you add is deleted when you popValue() leaving your list empty at the end of the loop. Use 2 loops, e.g.:
// extracting words from the file
while (file >> word)
list.addValue(word);
while ((t = list.popValue()).length())
cout << t << '\n';
(note: (t = list.popValue()).length() terminates the iteration when an empty-string is reached -- better to have popValue() return a node instead of string.
A short working example taking the filename to read as the first argument would be:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class LinkedList {
struct Node {
string x;
Node *next;
};
public:
LinkedList(){
head = NULL; // set head to NULL
}
~LinkedList(){
Node *next = head;
while(next) { // iterate over all elements
Node *deleteMe = next;
next = next->next; // save pointer to the next element
delete deleteMe; // delete the current entry
}
}
void addValue(string val){
Node *n = new Node(); // create new Node
n->x = val; // set value
n->next = head; // make the node point to the next node.
// If the list is empty, this is NULL, so the end of the list --> OK
head = n; // last but not least, make the head point at the new node.
}
string popValue(){
Node *n = head;
string ret {};
if (!head) /* validate head not nullptr */
return ret;
ret = n->x;
head = head->next;
delete n;
return ret;
}
private:
Node *head; // this is the private member variable. It is just a pointer to the first Node
};
int main (int argc, char **argv) { //linkedlist
LinkedList list;
// filestream variable file
fstream file;
string word, t, q, filename;
// opening file
if (argc < 2)
return 1;
file.open(argv[1]);
if (!file.is_open()) {
cerr << "file open failed.\n";
return 1;
}
// extracting words from the file
while (file >> word)
list.addValue(word);
while ((t = list.popValue()).length())
cout << t << '\n';
return 0;
}
Example Input File
$ cat dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.
Example Use/Output
$ ./bin/llwords dat/captnjack.txt
Seas.
Seven
the
On
Brave
So
Pirate
A
Sparrow
Jack
Captain
Of
tale
a
is
This
Lastly see Why is “using namespace std;” considered bad practice? and Why should I not #include <bits/stdc++.h>?

Program hangs up after loop counter input - no infinite loop or seg fault

I'm having an issue I can't figure out how to diagnose. It's been a while since I've worked in C++ and I decided to write a class based implementation of a LLL, with one class for the node and one for the list for the sake of practice. Once the list has been initialized in main, it prompts the user to input the length of the list from within the constructor. Then, for some reason, it hangs up instead of generating the list. I haven't gotten any error codes, and it doesn't seem to be stuck in a loop as best as I can tell. I'm very confused.
Main function:
int main() {
LLL * myList = new LLL();
int displayCount = 0;
displayCount = myList->display();
cout << "\n\n" << displayCount << " nodes were displayed\n\n";
delete myList;
return 0;
}
LLL constructor:
LLL::LLL() {
head = new node(rand() % 20);
node * current = head;
cout << "\n\nHow many nodes would you like this list to be? ";
int length = 0;
cin >> length;
cin.ignore(1000);
for (int i = 1; i <= length; ++i) {
node * temp = new node(rand() % 20);
current->attachNext(temp);
current = temp;
delete temp;
}
Node constructor:
node::node(int data) {
this->next = NULL;
this->data = data;
}
attachNext function:
bool node::attachNext(node *& toAttach) {
this->next = toAttach;
return true;
}
Header file:
#include <iostream>
#include <math.h>
using namespace std;
class node {
public:
node();
node(int data);
~node();
node * traverse();//returns obj->next node
bool checkNext();//returns true if obj->next exists
bool attachNext(node *& toAttach);
int display();
int deleteAll(int & count);
private:
node * next;
int data;
};
class LLL {
public:
LLL();
LLL(int length);
~LLL();
int display();
private:
node * head;
};
Ok, I figured it out. I called the cin.ignore function in the LLL and forgot to specify the delimiter.
This:
cin.ignore(1000);
Should have been:
cin.ignore(1000, '\n');

Moving data from one queue to another queue

I dequeue a queue and if the employee's salary is less than 50,000. I am not sure how to enqueue it into another queue as my enqueue function takes three parameters. My assignment says to create a class and then two queues in main. I made the queues being an object of the class, is this correct? How do I enqueue into the second queue with only having one enqueue function in the class which takes three parameters. Thanks for all the help.
#include <cstdlib>
#include <iostream>
#include <string>
#include <iomanip>
using std::cout;
using std::cin;
using std::endl;
using std::string;
using std::fixed;
using std::setprecision;
struct node{
string name;
int id;
int salary;
struct node *next;
};
node *rear;
node *front;
class DynEmpQueue{
private:
int counter = 0;
public:
void enqueue(string, int, int);
void dequeue();
void traverse()const;
DynEmpQueue()
{
rear = nullptr;
front = nullptr;
counter = 0;
}
};
void DynEmpQueue::enqueue(string localName, int localID, int localSalary)
{
node *temp;
temp = new (struct node);
temp -> name = localName;
temp -> id = localID;
temp -> salary = localSalary;
temp -> next = nullptr;
if (front == nullptr)
front = temp;
else
rear -> next = temp;
rear = temp;
counter++;
}
void DynEmpQueue::dequeue()
{
string localName;
int localID;
int localSalary;
node *temp;
if (front == nullptr)
cout << "The queue is empty.";
else
{
temp = front;
localName = temp -> name;
localID = temp -> id;
localSalary = temp -> salary;
front = front -> next;
delete temp;
counter--;
}
}
void DynEmpQueue::traverse()const
{
node *temp;
temp = front;
if (front == nullptr)
cout << "Queue is empty.";
else
{
cout << "Queue contains " << counter << " elements." << endl;
cout << "Queue elements:" << endl;
while (temp != nullptr)
{
cout << temp -> name << "\t" << temp -> id << "\t" << temp -> salary << endl;
temp = temp -> next;
}
}
}
int main()
{
const int NumberEmployees = 5;
DynEmpQueue originalQueue;
originalQueue.enqueue("Justin Gray", 100, 104000);
originalQueue.enqueue("Mike Smith", 200, 207000);
originalQueue.enqueue("Jose Cans", 400, 47000);
originalQueue.enqueue("Auston Matts", 300, 31000);
originalQueue.enqueue("Liz Learnerd", 600, 89100);
node object;
DynEmpQueue demandSalaryIncrease;
for (int i = 0; i < NumberEmployees; i++)
{
originalQueue.dequeue();
if (object.salary <= 50000)
demandSalaryIncrease.enqueue();
}
demandSalaryIncrease.traverse();
return 0;
}
You cannot know what employees exist in your queue. Look at how you defined your methods:
void enqueue(string, int, int);
void dequeue();
void traverse() const;
As you can see, no method returns either a node or the employee's data. So, as you currently declared the class, there is no way to get employees from your queue. And, since you can't even get employees are in the queue, you cannot add them into another queue.
Possible solution:
Modify your traverse() method so that it takes a salary as argument and returns an array (or even a queue) containing all the employees for which the salary is lower than that salary.
A better and much more flexible solution would be to use a predicate, but (since you are using global variables) it seems like you're not looking for perfect solutions anyway.

Insert 'n' nodes in a linked list and print their data (C++)

I don't understand what's wrong with my code here:
//Inserting n nodes, then print their values
#include <iostream>
#include <string>
using namespace std;
//Defining a node and it's head pointer
struct node
{
int data;
node *next;
};
node *head=NULL;
node *link;
node *tmp;
int main()
{
int n;
cin>>n;
while (n>0)
{
//Insert n nodes into the list
link=new node;
if (head==NULL)
{
head=link;
}
cin>>link->data;
link=link->next;
n--;
}
link=NULL;
//print data present in those n nodes
tmp=head;
while (tmp!=NULL)
{
cout<<tmp->data;
tmp=tmp->next;
}
return 0;
}
The first part of the code defines a node.
The second part (beginning of main function) is code for creating a linked list with n nodes in it. So I insert n nodes.
Finally, I output them using the pointer tmp. However, instead of getting the data values, I just get an infinite loop. What is going on here?
Thanks
#include <iostream>
#include <string>
using namespace std;
//Defining a node and it's head pointer
struct node
{
int data;
node *next=NULL;
};
node *head=NULL;
node *link;
node *tmp;
int main()
{
int n,limit;
cin>>n;
limit=n;
while (n>0)
{
tmp=link;
link=new node;
link->next=NULL;
cin>>link->data;
if (head==NULL)
{
head=link;
}
if(n!=limit) //check whether tmp is null initially tmp will be null for first element
{
tmp->next=link;
}
n--;
}
//print data present in those n nodes
tmp=head;
while (tmp!=NULL)
{
cout<<tmp->data<<"\n";
tmp=tmp->next;
}
return 0;
}
This code does what you want using std::list. I don't see why you should go on create your own crude and unsafe linked list. (I don't even see why you should use a linked list; in this particular a std::vector would be a more reasonable choice).
#include <iostream>
#include <list>
int main() {
std::list<int> linked_list;
// fill the list
std::cout << "Please enter the number of elements in the list: " << std::endl;
int n {};
std::cin>>n;
while (n-- > 0) {
std::cout << "Please enter the data for this item: " << std::endl;
int data {};
std::cin>>data;
linked_list.push_back(data);
}
// print out data the list
for (auto& data : linked_list)
std::cout << "printing data entry: " << data << std::endl;
return 0;
}
First of all it is c++. I recommend to use std::list:
#include <iostream>
#include <list> // list
int main()
{
int n;
std::cin >> n;
std::list<int> l;
while ( l.size() < n )
{
int data;
std::cin >> data;
l.push_back( data );
}
for ( int data : l )
std::cout << data << std::endl;
return 0;
}
But if you want to di it yourself you have to remember the tail of your list and add each new node as successor of the tail node. Further you should delete the list at the end of your program:
#include <iostream>
struct node
{
int data;
node *next;
};
node *head = NULL;
int main()
{
int n;
std::cin >> n;
node *tail = NULL;
while ( n>0 )
{
node *link = new node;
link->next = NULL; // successor of new node is NULL
std::cin >> link->data;
if ( head==NULL)
head = link; // if list is empty new node is head of list
else
tail->next = link; // successor of tail is new node
tail = link;
n--;
}
node *tmp = head;
while ( tmp != NULL) // delete the list from head to tail
{
std::cout << tmp->data << std::endl;
tmp = tmp->next;
}
while ( head != NULL)
{
tmp = head->next;
delete head;
head = tmp;
}
return 0;
}

The program does not give the desired output . Wrong implementation of FIFO ?

This is a FIFO program using linked list . The program does not give the desired output but generates a long loop which stops after sometime and there is a message that the program has stopped working. What is the problem ?
#include <iostream>
using namespace std;
struct node {
int data;
struct node* previous; // This pointer keeps track of the address of the previous node
};
struct queue {
node* first;
node* last;
};
node* dataNode_P_A;
bool loop = true;
struct node* enterData();
struct node* enter_N_Data();
void displayQueue();
int main() {
struct node* dataNode= enterData();
while( loop ) {
cout << "Want to enqueue ? Press y/n : ";
char ans;
cin >> ans;
if( ans == 'y' ) {
struct node* dataNode_N = enter_N_Data();
} else {
break;
}
}
displayQueue();
}
struct node* enterData() {
cout << "Enter the number : ";
dataNode_P_A = new node; // Now dataNode points to a chunk allocated to node
cin >> dataNode_P_A->data;
dataNode_P_A->previous = NULL; // this is set to NULL because no one follows till now
queue* q = new queue;
q->first = dataNode_P_A; // this pointer points to the first element
return dataNode_P_A;
}
struct node* enter_N_Data() {
cout << endl << "Enter the number : ";
node* dataNode = new node;
cin >> dataNode->data;
dataNode->previous = dataNode_P_A;
queue* q = new queue;
q->last = dataNode; // this pointer points to the last element
return dataNode;
}
void displayQueue() {
while( dataNode_P_A != NULL ) {
cout << dataNode_P_A->data << endl;
dataNode_P_A++;
}
}
You are constructing queues and then abandoning them.
You fail to update dataNode_P_A, so that you are not constructing a list so much as a tassel.
You invoke dataNode_P_A++ when you clearly don't know what it means.
You have written a long, complicated piece of code without testing it along the way.
You should start over, and go step by step.
Where to begin... First off the queue data structure isn't particularly used for anything. But that's not the root of your problem. That lies here:
void displayQueue() {
while( dataNode_P_A != NULL ) {
cout << dataNode_P_A->data << endl;
dataNode_P_A++;
}
}
When iterating through a linked list, you move to the next element by navigating to ->previous:
void displayQueue() {
while( dataNode_P_A != NULL ) {
cout << dataNode_P_A->data << endl;
dataNode_P_A = dataNode_P_A->previous;
}
}
Having said that, you're doing some other things that are questionable - like modifying your global list (dataNode_P_A). That's not a problem in your example, but it can be a problem if you ever want to do anything to the list other than display it.
Here's another version of displayQueue that doesn't have that problem:
void displayQueue() {
node *entry = dataNode_P_A;
while( entry != NULL ) {
cout << entry->data << endl;
entry = entry->previous;
}
}
You should edit your enter_N_Data() function like:
node* temp; // global as others in your program
struct node* enter_N_Data() {
cout << endl << "Enter the number : ";
node* dataNode = new node;
cin >> dataNode->data;
temp = new node;
temp = dataNode_P_A;
dataNode_P_A = dataNode; // update dataNode_P_A
dataNode->previous = temp;
queue* q = new queue;
q->last = dataNode; // this pointer points to the last element
return dataNode;
}
and keep everything same while following the suggestions by # Larry Osterman and # Beta.