For my C++ code below, I have declared a pointer of the "node" struct called "newNode" (node *newNode) and am trying to enter an id # and input it into newNode->id. After I enter in an id #, I get an error saying "exited, segmentation fault". I understand that this means we are trying to access a location in memory that we do not have access to, but am not aware how to fix this problem. I appreciate any feedback. Thank you.
#include <iostream>
using namespace std;
struct node
{
int id;
string name;
int age;
node *nxt;
};
node *head = NULL;
void InsertNode()
{
node *currentNode, *newNode, *nextNode;
cout << "You will now be prompted to enter the ID number, name, and age of a particular person..." << endl;
cout << "Enter ID number: ";
cin >> newNode->id;
cout << "Enter name: ";
cin >> newNode->name;
cout << "Enter age: ";
cin >> newNode->age;
currentNode = head;
while (currentNode != NULL)
{
if (newNode->id == currentNode->id)
{
cout << "The ID you entered was already assigned to another node. Please enter a different ID number for the node that you are inserting: " << endl;
cin >> newNode->id;
}else{
currentNode = currentNode->nxt;
}
}
if (head == NULL)
{
head = newNode;
}else{
currentNode = head;
while (currentNode != NULL)
{
nextNode = currentNode->nxt;
if (newNode->id < nextNode->id)
{
if(currentNode == head)
{
head = newNode;
newNode->nxt = nextNode;
}else if (nextNode->nxt == NULL && newNode->id > nextNode->id)
{
newNode->nxt = NULL;
nextNode->nxt = newNode;
}else{
newNode->nxt = nextNode;
}
}else{
currentNode = nextNode;
}
}
}
}
int main()
{
InsertNode();
return 0;
}
You have only created pointers that can point to a node of struct type but you haven't actually allocated memeory for these structures ..That is why you are getting segmentation fault as you are trying access a location that is not there .
First create a struct node via dynamic memory allocation say malloc and then try to assign I'd to it.
You have created a pointer to a struct, and when you're trying to insert something in the place of the pointer, but the pointer doesn't point to an object of the struct.
You need to dynamically allocate the node for insertion.
node *currentNode, *newNode, *nextNode;
newNode = new node(); // <- this is what you need to do, so you can insert.
cout << "You will now be prompted to enter the ID number, name, and age of a particular person..." << endl;
cout << "Enter ID number: ";
cin >> newNode->id;
cout << "Enter name: ";
cin >> newNode->name;
cout << "Enter age: ";
cin >> newNode->age;
Go forth and prosper.
Related
I am trying to get input of a queue with the linked list implementation. The issue is that the contents of the queue aren't being printed. I tried debugging but it says that in the function displayCar that pointer p is null regardless. I can't tell what's wrong with why pointer p is NULL. Is there a missing reference when I am trying to push from the carInput function?
#include <iostream>
#include <queue>
using namespace std;
class record
{
public:
string ownerID, plateNumber;
record* next;
};
void push(string ownerID1, string plateNumber1, record **head, record **tail) {
record *n = new record();
n->ownerID = ownerID1;
n->plateNumber = plateNumber1;
n->next = NULL;
if (*head == NULL) {
*head =*tail= n;
}
else {
(*tail)->next = n;
*tail = n;
}
}
void pop(record** head, record** tail) {
record* p = *head;
while (*head != NULL) {
*head = (*head)->next;
free(p);
p = *head;
}
if (*head == NULL)
{
*tail = NULL;
}
}
void carInput(record *head, record *tail) {
char choice = 'Y';
string ownTemp, plateTemp;
while (choice == 'Y') {
cout << "Enter Owner Name: ";
cin >> ownTemp;
cout << "Enter Plate Number: ";
cin >> plateTemp;
push(ownTemp,plateTemp,&head,&tail);
cout << "Press [Y] for next input: ";
cin >> choice;
}
}
void displayCar(record* head, record *tail) {
record* p = head;
cout << "List Of Cars: \n";
int i = 1;
while (p!= NULL) {
cout << i << ". Owner Name: " << p->ownerID << endl;
cout << i << ". Plate Number: " << p->plateNumber<< endl;
pop(&head,&tail);
i++;
}
}
void serviceCar(record *head,record*tail) {
record* p = head;
string plateTemp;
int i = 0, time = 0;
char choice = 'Y';
cout << "Enter Plate Number:";
cin >> plateTemp;
while (p!= NULL) {
if (p->plateNumber == plateTemp) {
cout << "There is [" << i << "] car in queue before your turn. Estimated time in queue: " << time;
}
else {
i++;
time = time + 45;
}
pop(&head,&tail);
}
}
int main() {
record* head = NULL;
record*tail = NULL;
cout << ":: Car Record::\n\n";
carInput(head,tail);
displayCar(head,tail);
serviceCar(head, tail);
}
I don't know why you are punishing yourself with code like this when you are in C++ and there are plenty easier ways to do the same, but I'll try to help anyway by underlining the main problems:
1). The main reason that you must be struggling is that in the first push, even after *head =*tail= n;, the *head->next is still NULL and later when you'll try to iterate from the head, as you do in pop, *head = (*head)->next; you will get nothing.
2). if you want to do pop, you should delete one element for each call, not the whole collection - so you need if instead of while.
You have while where you using pop for each iteration and in the pop you also have the while, so think about it.
Also, you should be returning the value to display it easily - or change the way you trying to cout p in displayCar.
3). When you want to display the collection you just have to iterate through the collection instead of deleting all the elements, which will leave you empty collection after one display. You just need to iterate and display them, not to delete, something like that:
record* p = *head;
int i = 0;
while (p != NULL) {
cout << i << ". Owner Name: " << p->ownerID << endl;
cout << i << ". Plate Number: " << p->plateNumber<< endl;
p = p->next;
i++;
}
There are some other points that should be mentioned, but I think that's enough to get the code right direction - anyway, my advice would be to try to take a good look for simple linked-list how it's done and then try Queue linked-list, or just check already written examples and then try it by yourself. GeeksForGeeks
Your carInput receives pointers by value, and modifying those pointers has no effect on the pointers you pass to it.
Thus, main's head and tail are always null.
(You solved this with the pushing and popping functions, but failed to apply the same principle here.)
void carInput(record **head, record **tail) {
char choice = 'Y';
string owner, plate;
while (choice == 'Y') {
cout << "Enter Owner Name: ";
cin >> owner;
cout << "Enter Plate Number: ";
cin >> plate;
push(owner, plate, head, tail);
cout << "Press [Y] for next input: ";
cin >> choice;
}
}
You need to combine this fix with the fixes pointed out in the comments.
compiler gives me segmentation fault when i have more than 2 structs in the linked list.
i have a struct Car that contains info about the car
struct Car {
string name;
string color;
int serialNumber;
int regestrationNumber;
int yearMade;
int yearInspection;
int price;
};
and i have a linked list
struct Node {
Car obj;
struct Node* next;
};
that i declare like that:
struct Node* head = NULL;
i collect info with this code block
cout << "name: " ;
getline(cin, newCar[size].name);
cout << "color: ";
getline(cin, newCar[size].color);
cout << "serial number: ";
cin >> newCar[size].serialNumber;
cout << "regestration number: ";
cin >> newCar[size].regestrationNumber;
cout << "year made: ";
cin >> newCar[size].yearMade;
cout << "inspection year: ";
cin >> newCar[size].yearInspection;
cout << "price: ";
cin >> newCar[size].price;
cin.get();
i add all this info to struct and push that struct to the linked-list with this function
void push(struct Node** head, Car node_obj)
{
Node* newNode = newNode;
newNode->obj = node_obj;
newNode->next = (*head);
(*head) = newNode;
}
and now the interesting part:
i use function void output(Car strk, int first) to print the content of struct like this (output() is basically a three printf() function)
while (headCopy != NULL) {
output(headCopy->obj, first);
headCopy = headCopy->next;
first = 1;
}
and now, when linked list has more than 2 elements in it it shows all the elements except for the first one, where it says segmentation fault.
i assume that the problem is that by the end headCopy = headCopy->next; simply doesn't point to anything or something, but then again, why doesn't it gives me that error when it has 1 or 2 elements.
as #mike vine said the problem was with line
Node* newNode = newNode;
where i should've typed
Node* newNode = new Node;
very stupid mistake.
This question already has an answer here:
How do I properly delete nodes of linked list in C++
(1 answer)
Closed 2 years ago.
I've been asked by a friend to help him with an exercise, basically the idea is like below.
Car number = fr50000 Car owner = AlexNelson Parking time = 3.5 hours.
He was told not to use stuff like string or getline, so it's simple app just to learn the idea of working with linked lists.
So I made this program. When I'm calling the remove() function the first time, it says the list is empty at the beginning (as it should do). But the second and third time, it's saying that the car is removed, but when I call the display() function, the car is still there (it didn't remove from the list)
Can you tell me what's wrong with my code?
#include <iostream>
using namespace std;
int length = 0;//variable of how many items in the list
struct node
{
char carNumber[15];
char carOwner[20];
float parkingTime;
node *link;
};
typedef struct node node;
node *head;//the begining of a list;
bool isempty()
{
if (length == 0)
return true;
else
return false;
}
void insert()
{
if (isempty())
{
head = new node;
cout << "Enter car number: ";
cin >> head->carNumber;
cout << "Enter Car owner: ";
cin >> head->carOwner;
cout << "Enter parking time: ";
cin >> head->parkingTime;
head->link = NULL;
length++;
}
else
{
node *p = head;
node *pnext = new node;
while (true)
{
if (p->link == NULL)
{
p->link = pnext;
break;
}
p = p->link;
}
cout << "Enter car number: ";
cin >> pnext->carNumber;
cout << "Enter Car owner: ";
cin >> pnext->carOwner;
cout << "Enter parking time: ";
cin >> pnext->parkingTime;
pnext->link = NULL;
length++;
}
}
void remove()
{
if (isempty())
{
cout << "List is empty\n";
return;
}
char carnumber[15];
cout << "Enter car number to remove: ";
cin >> carnumber;
node *p;
p = head;
while (p != NULL)
{
if (strcmp(p->carNumber, carnumber) == 0)
{
p = p->link;
cout << "Car removed\n";
return;
}
p = p->link;
}
cout << "Car was not found, check the number\n";
}
void display()
{
if (isempty())
{
cout << "List is empty\n";
return;
}
cout << "Car Number\t\tCar Owner\t\tParking Time\n";
node *p = head;
while (p != NULL)
{
cout << p->carNumber << "\t\t" << p->carOwner << "\t\t" << p->parkingTime << " Hours\n";
p = p->link;
}
}
int main()
{
string number;
display();
insert();
insert();
insert();
display();
remove();
display();
insert();
remove();
display();
}
Your remove() function is not actually removing (or destroying) a node from the list. You need to update the link of the previous node in the list to point to the next node in the list. And you need to update the head too, if removing the 1st node in the list.
Try this instead:
void remove()
{
if (isempty())
{
cout << "List is empty\n";
return;
}
char carnumber[15];
cout << "Enter car number to remove: ";
cin >> carnumber;
node *p = head;
node *prev = NULL;
while (p != NULL)
{
if (strcmp(p->carNumber, carnumber) == 0)
{
if (p == head)
head = p->link;
if (prev)
prev->link = p->link;
delete p;
cout << "Car removed\n";
return;
}
prev = p;
p = p->link;
}
cout << "Car was not found, check the number\n";
}
Alternatively:
void remove()
{
if (isempty())
{
cout << "List is empty\n";
return;
}
char carnumber[15];
cout << "Enter car number to remove: ";
cin >> carnumber;
node **p = &head;
while (*p != NULL)
{
if (strcmp((*p)->carNumber, carnumber) == 0)
{
node *n = *p;
*p = (*p)->link;
delete n;
cout << "Car removed\n";
return;
}
p = &(p->link);
}
cout << "Car was not found, check the number\n";
}
p = p->link; You're modifying the value of the local variable p, not the list. You need to modify the previous node's link field.
In the loop in remove, you are doing p = p->link, when p points to the node you want to remove. But you actually need to update the link field of the node that is pointing to p.
Here's a simple way of doing that:
node **p = &head;
while(*p)
if (strcmp((*p)->carNumber, carnumber) == 0)
break;
else p = &(*p)->link;
if (*p)
{
cout<<"Car removed\n";
delete std::exchange(*p, (*p)->link);
}
else cout << "Car was not found, check the number\n";
If you can't use std::exchange, then you can replace that with:
auto h = *p;
*p = (*p)->link);
delete h;
I have one serious problem. I need to write a program in which I input person details like first name, last name and age to a struct, which also contains pointer to the next person and than I need to write that to binary file. It must be ascending sorted by last name and than by first name, like linked list, using pointers, but only one pointer pointing to next struct. After entering all data it needs to go through file and find the struct with the lowest value and than using pointers print all data in ascending order.
This is the code I wrote but it's not working. I need help.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
using namespace std;
struct person{
char firstName[20], lastName[20];
int age;
person *next;
};
void insert(char filename[], int n){
person *head = NULL;
ofstream people(filename, ios::binary | ios::trunc);
for(int i=0; i<n; i++){
system("cls");
person *per = new person;
cout << "firstName: ";
cin >> (*per).firstName;
cout << "lastName: ";
cin >> (*per).lastName;
cout << "age: ";
cin >> (*per).age;
if(head == NULL) {
(*per).next = head;
head = per;
}
else{
person *curr = head;
person *prev = NULL;
bool end = false ;
while(!end){
if(strcmp((*curr).lastName, (*per).lastName) ||
(!strcmp((*curr).lastName, (*per).lastName) &&
strcmp((*curr).firstName, (*per).firstName))){
end = true;
}
else {
prev = curr;
curr = (*curr).next;
}
}
if(curr==head){
(*per).next= head;
head = per;
}
else{
(*per).next = curr;
(*prev).next = per;
}
}
people.write((char *)&(*per), sizeof(*per));
}
people.close();
}
void print(char filename[]) {
person *head = NULL;
person *el;
person c,min;
ifstream people(filename, ios::binary);
people.read((char *)&c, sizeof(c));
min = c;
while(!people.eof()){
people.read((char *)&c, sizeof(c));
if(strcmp(c.lastName,min.lastName)== -1 ||
(!strcmp(c.lastName,min.lastName) &&
strcmp(c.firstName,min.firstName)==-1)){
min = c;
}
}
head = &min;
while (head != NULL) {
cout << (*head).firstName << " " <<(*head).lastName <<" "<<
(*head).age << endl;
el = head;
head = (*head).next;
delete el;
}people.close();
}
int main() {
int n, a;
char filename[40];
cout << "filename: " << endl;
cin.getline(filename, 40);
do{
do{ system("cls");
cout << "Choose one of the options: "<<endl;
cout << "1. insert "<<endl;
cout << "2. print "<<endl;
cout << "0. exit "<<endl;
cin >> a;
} while(a<1||a>2);
switch(a){
case 1: cout << "How many people would you like to enter? ";
cin >> n;
insert(filename, n);
break;
case 2:print(filename);
}
} while(a!=0);
return 0;
}
Looks like you are trying to create a sorted list but your condition for place to insert new node is wrong
strcmp((*curr).lastName, (*per).lastName) ||
(!strcmp((*curr).lastName, (*per).lastName) &&
strcmp((*curr).firstName, (*per).firstName)
It essentially tells - insert new person before curr as soon as it is different from curr.
You have to change it to be - insert new person as soon as it is bigger than (less than) curr - depending on the order of sorting.
So instead of checking strcmp != 0 check strcmp >0 or <0
Of course replacing c-strings with std::string will make it a lot easier and safer
I am using cin and cout in my program. I starts off fine because it is not executing any of the functions, but after you type your name, it throws an exception in the iostream library. wondering if it is a problem with using cin through refrence.`
// linkedlists.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;
struct person {
string name;
int age;
struct person* next;
};
person *head = NULL;
int length() {
int count = 0;
person *current = head;
while (current->next != NULL) {
current = current->next;
count++;
}
return count;
}
void printlist() {
person *current = head;
while (current->next != NULL){
cout << "Name: " << current->name << " Age: " << current->age << "\n";
current = current->next;
}
}
void insert() {
// int choice;
person *newNode = (struct person*)malloc(sizeof(person));
//cout << "Press 1 to insert at beginning of list.\n";
//cin >> choice;
// switch (choice) {
//case 1:
newNode->next = head;
head = newNode;
cout << "What is this person's name?\n";
cin >> newNode->name;
cout << "\nWhat is the age of " << newNode->name << "?";
cin >> newNode->age;
cout << "The current list of people is " << length() << " long.\n";
printlist();
}
void menu() {
int choice;
cout << "Welcome to the person recorder! ";
bool inloop = true;
while (inloop) {
cout << "Press 1 to add more entries. Press 2 to print the entire list. Press 3 to exit the program.\n";
cin >> choice;
switch (choice) {
case 1:
insert();
case 2:
printlist();
case 3:
inloop = false;
}
}
}
/*void change(person* human) {
string temp_name;
int temp_age;
cout << "What is this person's name?\n";
cin >> temp_name;
cout << "\nWhat is this person's age?\n";
cin >> temp_age;
human->name = temp_name;
human->age = temp_age;
}
*/
int main()
{
menu();
}
using visual studio 2015, am a noob to c/c++ and trying to make a linked list.
The problem is caused by your allocation of person:
person *newNode = (struct person*)malloc(sizeof(person));
This will allocate memory on the heap for an instance of person, but it will not call the constructor of person and any of it's members. This does not matter for age and next since they are primitive types, but name is an std::string, which has a constructor that needs to be called for it to function properly.
In C++ you create instances of objects using the keyword new.
person *newNode = new person;
This will create a new instance of person, and also call its constructor, which will initialize name properly.
Once you are done with the instance of person, you will have use the keyword delete to clean it up.
delete newNode;
Similar to the difference between malloc and new, delete will free the memory, but also call the destructor, which is used by name to clean up any resources it may have allocated to store the string.