Inserting profile in a linked list - c

This code is for adding an employee profile at the beginning of a linked list. For some reason, which i cannot identify, this code worked once, and then it just printed the printf and then exited the loop. Even after entering numerous records, it was still doing the same thing. So can anyone identify the problem??
void insert_tobeg() {
char name[15];
struct employee *newPtr;
printf("\n\n\tEnter the record to be entered:");
gets(name);
if(strcmp(start->name, name) == 0) {
curr = (struct employee*)malloc(sizeof(struct employee));
employee_entry();
curr->newPtr = start;
start = curr;
printf("\n\n\tRecord has been added at the beggining!");
return;
}
}

You manage it incorrect, you overwrite the name in first element, you need to write to the currently allocated ellement.
Try something like this
curr = (struct employee*)malloc( sizeof(struct employee));
employee_entry();
if( strcmp( curr->name, name) == 0)
{
curr->newPtr=start;
start = curr;
printf("\n\n\tRecord has been added at the beggining!");
return;
}
else
{
free(curr);
}
And don't cast malloc result in C

Did you mean while loop instead if, and remove return statement.

Related

Add words received from the user to the linked-list in C programming

#include <stdio.h>
#include <stdlib.h>
struct node {
char *str;
struct node *next;
};
struct node *start = NULL;
struct node *temp = NULL;
struct node *q = NULL;
void sonaEkle(char *veri) {
struct node *eklenecek = (struct node *)malloc(sizeof(struct node));
eklenecek->str = veri;
eklenecek->next = NULL;
if (start == NULL) {
start = eklenecek;
} else {
q = start;
while (q->next != NULL) {
q = q->next;
}
}
}
void yazdir() {
q = start;
while (q->next != NULL) {
printf("%s", q->str);
q = q->next;
}
printf("%s", q->str);
}
int main() {
char *veri;
while (1 == 1) {
printf("enter string");
scanf("%s", veri);
sonaEkle(veri);
yazdir();
}
return 0;
}
I have created a Linked list.
This linked list adds the string it received from the user to the end. But my code is giving a loop error. How can I fix this?
for example: user input:abc bcd cde
output:abc => bcd => cde
This is an infinite loop
while(1 == 1) {
printf("enter string");
scanf("%s",veri);
sonaEkle(veri);
yazdir();
}
Rewrite it in this way
while( puts("enter string") && scanf("%s",veri) == 1 ) {
sonaEkle(veri);
yazdir();
}
And also you need to allocate memory for veri before you can use it in scanf. But you could as well just making it an array.
char veri[SIZE];
There are multiple problems with the code
char *veri;
while(1 == 1){
First statement veri needs memory, since it is a pointer, you need some thing like this veri = malloc(somesize);
Second statement is an infinite loop, you need some termination point, better use something like below to break the infinite loop.
while(1){
// after malloc
scanf("%s",veri);
//enter exit whenever you want to exit from program.
if(strcmp(veri,"exit") == 0)
break;
Function sonaEkle you are allocating memory for struct node* , but you are not returning updated nodes address start
you need to have sonaEkle like this struct node* sonaEkle(char *veri) and return start after every update and no need to cast malloc.
4)
else {
q=start;
while(q->next != NULL) {
q=q->next;
}
The above part just iterates list, you need to add new nodes to q->next when it reaches to NULL and return start afterwards in order to have next elements in the list.
Correct all those problems , to make you program work.
NOTE:
check the pointers for NULL after every malloc
free the malloc'ed memory once you are done with your program.

Getting input appended to linked list without getting the same input again - C

I am trying to get inputs from the user and then append the struct to the end of the linked list. This works fine but I want to add another feature that would prevent the input being added if all the details are exactly the same. (In this case email, class, first and last name)
The for loop I added in the middle is what I tried to do to achieve this feature. The program goes into the loop without any problems but the input will still be added. How would I fix this?
struct request *append(struct request *list){
char f_name[NAME_LEN+1];
char l_name[NAME_LEN+1];
char e_address[EMAIL_LEN+1];
char c_name[CLASS_LEN+1];
//get input
printf("\nEnter email: ");
scanf("%s", e_address);
printf("\nEnter class: ");
scanf("%s", c_name);
printf("\nEnter child first name: ");
scanf("%s", f_name);
printf("\nEnter child last name: ");
scanf("%s", l_name);
//allocate memory for the structure
struct request* p = (struct request*) malloc(sizeof(struct request));
struct request *temp = list;
//////////WHAT I TRIED BUT DIDN'T WORK
for (p = list, temp = NULL; p != NULL; temp = p, p = p -> next) {
if (strcmp(p -> first, f_name) == 0 && strcmp(p -> last, l_name) == 0 && strcmp(p -> email, e_address) == 0 && strcmp(p -> class, c_name) == 0) {
printf("Output: request already exists");
return list;
}
}
//store the data
strcpy(p->first, f_name);
strcpy(p->last, l_name);
strcpy(p->email, e_address);
strcpy(p->class, c_name);
p->next = NULL;
//if list is empty return pointer to the newly created linked list
if (list == NULL) {
return p;
}
//traverse to the end of the list and append the new list to the original list
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = p;
return list;
}
First off, with those scanf's you should do something like this to avoid buffer overflows.
As to your question, you should malloc p after your for-loop since we should only allocate it if there is no other node with the exact same info (And as paddy said, in your code it causes a memory leak because you set p to point to something else hence losing that newly malloc-ed data).
Your loop is more complex than it needs to be. Admittedly I can't see why the for-loop wouldn't detect a copy, maybe providing some input cases would help clear it up? Either way I'd replace that section of the code with this:
// Get a pointer to the head of the list
struct request *temp = list;
// Find and node with the exact same data
while(temp->next != NULL) {
if(!strcmp(temp->first, f_name) && !strcmp(temp->last, l_name) && !strcmp(temp->email, e_address) && !strcmp(temp->class, c_name)){
printf("Output: request already exists");
return list;
}
temp = temp->next;
}
// Allocate p and reset temp
struct request *p = (struct request*) malloc(sizeof(struct request));
temp = list;
// etc

Adding a node to random spot in linked list

So I have a function that adds a node to a linked list but instead of just adding the element at the end of the linked list I am trying to get user input for the spot the user wants to add it in. I then need to add it and shift everything else over without deleting anything else. I am having a lot of trouble with this.
Below I will show my code, its a bit messy but I will explain as best I can.
void InsertGraphicElement(struct RasterGraphic *pA) {
int counter = 1;
int response = 0;
char tempString[256];
struct GraphicElement *newNode = malloc(sizeof(*newNode));
if (newNode == NULL)
return;
newNode->fileName = malloc(256 * sizeof(char));
if (newNode->fileName == NULL)
return;
newNode->pNext = NULL;
printf("Insert a GraphicElement in the RasterGraphic\nPlease enter the GraphicElement filename: ");
scanf("%s", newNode->fileName);
if (pA->GraphicElements == NULL) {
pA->GraphicElements = newNode;
printf("This is the first GraphicElement in the list\n");
} else {
struct GraphicElement *tempHead = pA->GraphicElements;
struct GraphicElement *tempTail = pA->GraphicElements;
while (tempHead->pNext != NULL) {
tempHead = tempHead->pNext;
counter++;
}
tempHead->pNext = newNode;
printf("There are %d GraphicElement(s) in the list. Please specify the position (<= %d) to insert at :", counter, counter);
scanf("%d", &response);
if (response == counter) {
return;
} else {
while (response < counter) {
tempTail = tempTail->pNext;
response++;
}
}
}
return;
}
It is incomplete Ive been messing with the code trying to figure it out but as you can see I am able to add without a problem at the end of the list. What I am having trouble with is if there are 5 elements for example in the list 1,2,3,4,,5 and I add a sixth the list would obviously look like this 1,2,3,4,5,6. What I want to do is take user input such as they want to add the sixth element to maybe spot 3 so the list would look like this 1,2,6,3,4,5. Ive tried a bunch of things a point in the right direction or some help would be greatly appreciated. Thank you,
Below are my struct definitions
struct GraphicElement {
char *fileName;
struct GraphicElement *pNext;
};
struct RasterGraphic {
//int numNodes;
struct GraphicElement *GraphicElements;
};
You currently have the following:
if (response == counter) {
return;
}
else {
while(response < counter){
tempTail = tempTail->pNext;
response++;
}
}
I would revise this to be something like:
if (response > counter+1 || response < 1) { // These are all invalid values
return;
}
else if (response == 1) { // We are replacing the head node
newNode->pNext = tempTail->pNext;
pA->GraphicElements = newNode;
}
else {
while(response-- > 2) { // Responses are 1-indexed
tempTail = tempTail->pNext;
}
newNode->pNext = tempTail->pNext; // IMPORTANT: Update newNode reference FIRST
tempTail->pNext = newNode; // Update tempTail to point to newNode
}
Disclaimer - Not tested in any way
I tried to comment things I thought were important here and there. The key thing to remember here though is that in order to insert something into a singly-linked list, you must update your new node to point to the rest of the linked list BEFORE you update the reference of the node previous to it, or else the last bit of your list will be lost forever and you will have a circular reference to the last node.
As a side note, it looks like your are traversing your entire linked-list twice each time you want to add a new element to it. I might recommend keeping a rolling counter of how many items are in the linked list that you update each time you add something to it to avoid the overhead of recalculating this value if efficiency is something you value.
Hope this helps!
EDIT: You'd have to remove the line that adds the new node to the end of the list higher up in the function for this to work, however. "tempHead->pNext = newNode;"

adding a node to a linked list using a function

I currently have a linked list and need to add data to it that is inputted by the user from the keyboard so i have two structs:
struct CourseInfo {
int courseID;
char courseName[30];
};
typedef struct CourseInfo courseinfo;
struct StudentInfo {
char StudentID[10];
char FirstName[21];
char LastName[26];
int num_course;
courseinfo array[10];
struct StudentInfo *next;
};
So i have a linked list with 3 nodes currently. I then need to call a function and add a node. The node needs to be inserted in the correct place which is that the studentID before it needs to be less than it and the studentID after needs to be greater so the current IDs i have are 111111111, 333333333, and 444444444 and im trying to add 222222222 so it would go in the second spot so my function looks like:
studentinfo *addStudent(studentinfo *data) //returns type studentinfo* now
{
studentinfo *add;
add = malloc(sizeof(studentinfo));
add->next = NULL; //Now its set to NULL to begin
int knt;
printf("%s", "Adding new student:\nStudent ID: ");
scanf("%s", add->StudentID);
printf("%s", "First Name: ");
scanf("%s", add->FirstName);
printf("%s", "Last Name: ");
scanf("%s", add->LastName);
printf("%s", "Number of courses: ");
scanf("%d", &add->num_course);
for(knt = 0; knt < add->num_course; knt++) {
printf("%s", "Course ID: ");
scanf("%d", &add->array[knt].courseID);
printf("%s", "Course Name: ");
scanf("%s", add->array[knt].courseName);
}
if(searchStudentID(data, add->StudentID)) {
puts("immediately inside if");
while(data != NULL) {
puts("Immediately inside while");
if(strcmp(add->StudentID, data->StudentID) < 0) {
puts("inside if");
add->next = data;
data = add;
}
else {
puts("inside first else");
studentinfo *PrevPtr = data;
studentinfo *NPtr = data->next;
while(NPtr != NULL) {
("inside while(NPTR != NULL)");
if(strcmp(add->StudentID, NPtr->StudentID) < 0) {
add->next = PrevPtr;
PrevPtr->next = add;
break;
}
else {
puts("inside a differnet else");
PrevPtr = NPtr;
NPtr = NPtr->next;
}
}
if(PrevPtr->next == NULL) {
puts("inside last if");
add->next = NULL;
PrevPtr->next = add;
}
}
}
}
else {
puts("Found id");
}
return data; //returns data back to call
}
So i added all those puts statement because i wanted to see why the program kept crashing. So the puts statement puts("Inside a different else") is stuck in an infinite loop and keeps printing. The function searchStudentID simply returns 1 if we dont already have the ID and 0 if we already have it. I know that this function works so there is no need to post it.
I think the problem may be in the break; statement because it doesnt exit from the first while loop but only exits from the inner loop but im not positive.The call to this function look like:
list = addStudent(list); //Now the new data is stored in list
Where list is the linked list with 3 nodes
Linked list management is about managing node pointers, not just nodes. You want to do several things to make this considerably easier on yourself:
Separate the input step from the search+insertion step. They don't belong together regardless of how they may seem otherwise. The biggest benefit this brings to you is reducing your list insertion code to what it should be doing (and only what it should be doing): managing the linked list. I've kept yours intact, but you should really be error checking and doing the data reading somewhere else.
Use a pointer to pointer to walk the list. The biggest benefit from this is eliminating the need to special-case head-position insertion. If that is the position a new node will eventually occupy, so be it, but eliminating that special-case further reduces the complexity of the algorithm.
Don't search the list unless you're capable of retaining the search results to be used for insertion logic. It makes little sense to perform an O(N) scan of the linked list to determine if input data is already present, only to search it again to find the position said-data will actually be inserted. Do it once. Find the position where it belongs. If it is already there, do nothing, otherwise, you sit at the precipice of the proper insertion location already.
Finally, don't allocate a new node unless you know you need one. Use an automatic variable that helpfully self-discards if you end up doing nothing.
Putting all of that together gives something like this:
struct CourseInfo {
int courseID;
char courseName[30];
};
typedef struct CourseInfo CourseInfo;
struct StudentInfo {
char StudentID[10];
char FirstName[21];
char LastName[26];
int num_course;
CourseInfo array[10];
struct StudentInfo *next;
};
typedef struct StudentInfo StudentInfo;
StudentInfo *addStudent(StudentInfo *head)
{
StudentInfo **pp = &head, *p = NULL, rec;
int knt;
// TODO: error check your inputs!
printf("%s", "Adding new student:\nStudent ID: ");
scanf("%s", rec.StudentID);
printf("%s", "First Name: ");
scanf("%s", rec.FirstName);
printf("%s", "Last Name: ");
scanf("%s", rec.LastName);
printf("%s", "Number of courses: ");
scanf("%d", &rec.num_course);
for(knt = 0; knt < rec.num_course; knt++) {
printf("%s", "Course ID: ");
scanf("%d", &rec.array[knt].courseID);
printf("%s", "Course Name: ");
scanf("%s", rec.array[knt].courseName);
}
// walk the list pointers, starting with head, looking for
// a node that is equal or greater than the input node
while (*pp && (knt = strcmp((*pp)->StudentID, rec.StudentID)) < 0)
pp = &(*pp)->next;
// leave now if already present
if (*pp && knt == 0)
return head;
// allocate new node
p = malloc(sizeof *p);
if (p == NULL)
{
perror("Failed to allocate new node");
exit(EXIT_FAILURE);
}
// structure copy.
*p = rec;
// link into proper list position.
p->next = *pp;
*pp = p;
// always return the head (which may have updated above)
return head;
}
That's it. As mentioned, I would personally perform the input operation somewhere other than this function, but I leave that to you to consider.
Best of luck.
Since this function updates the list you either need it to be
studentinfo *addStudent(studentifo *data)
and return the updated head value. Or
void addStudent(studentifo **data)
and do
*data = <new thing>
Issues that I see:
You are not setting add->next to NULL.
You are changing data locally.
add->next = data;
data = add;
changes the value of data locally in the function. It does not change the value in the calling function.
You have the check
while(data != NULL)
following the if statement
if(searchStudentID(data, add->StudentID)) {
but I don't see any code to add the new student when searchStudentID(data, add->StudentID) returns false and when data == NULL to start with.

Segmentation Fault when using Linked Lists and Char arrays

I'm struggling through my programming homework and need a hand with Linked Lists. Basically we have to create a program that contains certain functions to manage linked lists. Fairly standard. I tried it last week and just couldn't get it. I'm trying to get it working this weekend and was making good progress until I ran into segmentation faults.
struct STUDENT
{
char *FirstName;
char *LastName;
char *PUID;
int age;
struct STUDENT *next;
};
This is the structure I'm trying to use. The first three values are char arrays and the fourth is just a number. Following this I tried to declare a starting and current node globally.
struct STUDENT *head = NULL;
struct STUDENT *curr = NULL;
Following this I have my create node function, which takes a user input and puts it into the list.
void *createListNode()
{
char first[MAXNAME];
char last[MAXNAME];
char ID[MAXID];
char *pfirst;
char *plast;
char *pID;
int tage;
struct STUDENT *temp = (struct STUDENT *) malloc (sizeof(struct STUDENT));
printf("Enter a first name: ");
scanf("%s", first);
pfirst = first;
printf("entered name: %s\n", pfirst);
printf("Enter a last name: ");
scanf("%s", last);
plast = last;
printf("entered name: %s\n", plast);
printf("Enter the Purdue ID: ");
scanf("%s", ID);
pID = ID;
printf("ID: %s\n", pID);
printf("Enter an age: ");
scanf("%d", &tage);
printf("age: %d\n", tage);
temp->FirstName = strdup(first);
printf("first\n");
temp->LastName = strdup(last);
printf("last\n");
temp->PUID = strdup(ID);
printf("id\n");
temp->age = tage;
printf("age\n");
temp->next = NULL;
printf("next\n");
if (curr == NULL)
{
printf("inside if\n");
head->next = temp; //-------SEGMENTATION FAULT---------------------
printf("line 107\n");
head = curr = temp;
printf("line 109\n");
}
else
{
curr = temp;
}
}
Background of what I'm done up to this point:
I was getting segmentation faults when I tried to assign my arrays to my 'temp' node, but by using malloc on it I solved that problem. Using print statements, I've tracked the problem to the indicated line. When I try to run the code, I get a segmentation fault. I tried the same malloc code above on the 'head' and 'curr' nodes, but that gave me:
carlton#carlton-Inspiron-N7010:~/CNIT315$ gcc lab5.c
lab5.c:20:64: error: invalid initializer
struct STUDENT head = (struct STUDENT *) malloc (sizeof(struct STUDENT));
This is where I believe the problem is, but I've been searching and experimenting for several hours and haven't gotten anywhere. And I just realized this is now a very long post. Thanks for reading it through and I appreciate any push in the right direction!
You initialize head to NULL. You can't dereference head before assigning a valid pointer to it. head->next = temp; gives you a segfault because head is a null pointer.
Thus, you need to review this part of the code:
if (curr == NULL)
{
printf("inside if\n");
head->next = temp; //-------SEGMENTATION FAULT---------------------
printf("line 107\n");
head = curr = temp;
printf("line 109\n");
} else
{
curr = temp;
}
Since it seems like you want to insert at the end of the list, I would suggest something like this:
temp->next = NULL;
if (head == NULL) {
curr = head = temp;
} else {
curr->next = temp;
curr = temp;
}
This makes curr always point to the last node, and head always points to the beginning of the list.
Am I wrong or do you set head->next = temp; but never set head to a valid object before?
You either have to initialize head with an 'empty' Student at the beginning or you just have to set head = temp;
Assuming that you've defined the head variable outside the createListNode() function, here's the problem:
Memory is never assigned to it, since you have never called malloc()

Resources