Having trouble creating a linked list - c

Sorry for the vague title, i'm not quite sure how to explain what is going on. I am attempting to create a linked list, with each entry of the linked list containing two character strings, one integer array that can hold four entries, and one float array that can hold four entries.
Here is the initialization of the main struct in a header file -
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
#define MAX_LENGTH 20
struct stock {
char ticker[MAX_LENGTH];
char comp[MAX_LENGTH];
int shares[4];
float price[4];
struct stock *next;
};
#endif
Here is the code from my main file -
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "functions.h"
void main(void) {
int choice,shr[4], i;
char tic[MAX_LENGTH];
char nam[MAX_LENGTH];
float pri[4];
struct stock *head = NULL;// entry point for linked list
struct stock *current; //pointer currently being used
printf("Press 1 to enter a new stock\n");
printf("Press 2 to find the LIFO and FIFO dollar cost average for the number of shares sold\n");
scanf("%d", &choice);
switch(choice)
{
case 1:
printf("Enter the stock ticker:\n");
scanf("%s", &tic);
printf("Enter the name of the stock:\n");
scanf("%s", &nam);
for(i = 1; i<=4; i++) {
printf("Enter the number of shares:\n");
scanf("%d",&shr[i] );
printf("Enter the price of the stock:\n");
scanf("%f", &pri[i]);
}
if(head == NULL) { //check to see if first element has been filled
head = (struct stock *)malloc(sizeof(struct stock));
current = head;
}
else { //if the first element is full, move on to the next entry
current->next = (struct stock *)malloc(sizeof(struct stock));
current = current->next;
}
strcpy(current->ticker, tic);
strcpy(current->comp, nam);
memcpy(current->shares, shr, sizeof(current->shares));
memcpy(current->price, pri, sizeof(current->price));
current->next = NULL;
}
printf("%s\n", current->ticker);
printf("%s\n", current->comp);
for(i = 1; i <= 4; i++) {
printf("%d\n", current->shares[i]);
printf("%f\n", current->price[i]);
}
}
The end goal of the program is to have two separate stock entries, and be able to calculate the FIFO/LIFO dollar cost average based on four different share purchases for each stock. But for now, i am only trying to be able to correctly enter the information into a linked list.
After the loop that asks the user four times for the number of shares, and price of a stock, the character string "nam" asked for previously seems to disappear, because if i try to access it or print it out later it prints nothing.
I am trying to use the memcpy function to copy an inputted array over to the one in the linked list. Whenever i try to print the array back out after i copied it to the linked list, it does not print properly. The first three entries of the shares and price arrays print properly, but the fourth share entry prints a huge number and the fourth float entry prints as zero.
Thanks for any help.

tic and nam are already pointers so change
scanf("%s", &tic);
scanf("%s", &nam);
to
scanf("%s", tic);
scanf("%s", nam);
Also, not directly related to your issue, but
head = (struct stock *)malloc(sizeof(struct stock));
current->next = (struct stock *)malloc(sizeof(struct stock));
would be better written as
head = malloc(sizeof(*head));
current->next = malloc(sizeof(*(current->next)));
There is no need to cast the return from malloc() and by using sizeof(*head) you are guaranteed to be using the correct type for sizeof.

Related

How do we create a nested linked list?

A lecturer teaches 4 different classes.
The number of students in each class may differ from each other.
There are two different linked list structures for holding courses and students.
In the structure of the class (nodeClass), information about which class it is (classID) and the average of the midterm exams of the students in the class (classMidtermAverage) are kept. Besides these, there is a pointer pointing to the next class and a pointer pointing to a node belonging to the structure (nodeStudent) used to define students' information.
In the structure called nodeStudent, there is a student's id, midterm grade and a pointer showing the next student in the same class.
The program takes the student number and midterm grade from the user as input. Students whose student number starts with 66 are in the 1st class, with 77 in the 2nd class, students starting with 88 are in the 3rd class, and students starting with 99 are in the 4th class. Students must appear in the linked list sequentially. Sorting will be done in descending order according to the midterm grade. If the notes are the same, the lower number should be first in the list. The sorted list should be preserved by adding it to the correct location while adding. After all students are added to the list, the midterm average of each class will be calculated and kept in the classMidtermAverage variable of the node generated from the nodeClass structure of the relevant class.
I know we have to create a nested linked list but I am having a hard time inserting the data to the main linked list (being the classes linked list) and the child linked list (students list)
struct nodeClass
{
int classID;
double classMidtermAverage;
struct nodeClass *next;
struct nodeStudent *studentPtr;
};
struct nodeStudent
{
int studentID;
int midterm;
struct nodeStudent *next;
};
struct nodeClass* insert(struct nodeClass **head, int id, int midterm) {
struct nodeStudent* newPtr;
struct nodeClass* temp= (struct nodeClass*) malloc(sizeof(struct nodeClass*));
temp->studentPtr = (struct nodeStudent*) malloc(sizeof(struct nodeStudent));
temp->studentPtr->studentID=id;
temp->studentPtr->midterm=midterm;
long classcode=id;
while (classcode>=100){
classcode=classcode/10;
}
if (classcode=66) {
temp->classID=i;
head=temp;
}
else if( classcode=77) {
temp->classID=2;
head->next=temp;
struct nodeClass* class2= head->next;
}
else if( classcode=88) {
temp->classID=3;
head->next->next=temp;
struct nodeClass* class3= head->next->next;
}
else if( classcode=99) {
temp->classID=4;
head->next->next->next=temp;
struct nodeClass* class3= head->next->next->next;
}
return head;
}
struct nodeClass* computeClassAverage(*head) {
nodeClass* tmp;
for( tmp=head; tmp)
}
void printAll(*head);
and the main function is
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "function.h"
int main()
{
struct nodeClass *head = NULL;
int id, midterm;
scanf("%d", &id);
while(id!=-1)
{
scanf("%d", &midterm);
insert(&head, id, midterm);
scanf("%d", &id);
}
computeClassAverage(head);
printAll(head);
return 0;
}
You seem to have some misunderstanding of this subject matter which I can't quite see, so I doubt that this answer will satisfy you, but I'll go out on a limb.
Here is a way to insert new elements into the linked list:
nodeStudent* insertStudent(nodeStudent *head, nodeStudent *newp)
{
newp->next = head;
return newp;
}
nodeClass* insertClass(nodeClass *head, nodeClass *newp)
{
newp->next = head;
return newp;
}
Notice that these functions add the new elements at the head of the list. It is not difficult to write functions to add elements after a given element, or find the end of the list and insert the new element there.

Linked lists in C with chars and integers (troubleshooting)

I want to programm a linked list in C, trying to apply everything I've learned so far.
I wrote this program to create a linked list:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node *head = NULL;
//Define struct node
struct node{
char * name;
int num;
struct node * next;
};
//Print List
void printList(){
struct node * temp = head;
while (temp != NULL){
printf("%s", temp->name);
printf("%d", temp->num);
temp = temp->next;
}
}
//Create New Node
struct node * newNode (char * name, int num){
struct node * newNode = (struct node*)malloc(sizeof(struct node));
newNode->name = name;
newNode->num = num;
newNode->next = NULL;
return newNode;
}
//Function to insert and sort Elements
void insertSorted (char * name, int num){
//Empty Liste -> Head is NULL
if (head == NULL){
head = newNode(name, num);
}
else if (strcmp(name, head->name) <=0){
// strcmp-output = -1 ->string 1 > string 2; 0 -> both strings are the same
struct node * temp = newNode(name, num);
temp->next = head;
head = temp;}
struct node * current = head; struct node *prev = NULL;
if (strcmp(name, current->name)>0){ //-> 1, string1 < string 2 ->insert after
while(current != NULL && strcmp(name, current->name)<=0){
prev = current;
current = current->next;
}
struct node * temp = newNode(name, num);
prev->next = temp;
temp->next = current;
}
}
//Test of the linked list
int main()
{
char name; int num;
//Testprogram
printf("Enter a name\n");
scanf("%s", &name);
printf("Enter a number\n");
scanf("%d", &num);
insertSorted(&name, num);
char name2; int num2;
printf("Enter a name\n");
scanf("%s", &name);
printf("Enter a number\n");
scanf("%d", &num2);
insertSorted(&name2, num2);*/
char name3; int num3;
printf("Enter a name\n");
scanf("%s", &name);
printf("Enter a number\n");
scanf("%d", &num3);
insertSorted(&name3, num3);
printList();
return 0;
}
Output example:
Input: Anna 1, Claudio 2, Berta 3
Output: 32Berta1
It somehow...makes the Names vanish and the numbers are in the wrong order too. I'm pretty new to programming, so I have troubles fixing this by myself.
Any help would be hugely appreciated :) Not only to fix the error, but also tips on how to program more...elegantly, so to say.
Thanks :)
//Edit:
Thank you for all the input so far! I messed up the input of the string while testing the program.
As suggested I tried to skip the part with the input, testing the linked list like this in main() (thanks Julien!):
insertSorted("Anna", 1);
insertSorted("Claudio", 2);
insertSorted("Berta", 3);
printList();
it results in the programm not executing and exiting with a negative number error code. Does this point to an infinite loop?
I haven't looked at the linked list details, but one issue I see is that you are using single char variable to store the names (which should be an array or characters). This lack of enough space to store the input make you program have an undefined behaviour after the call to scanf.
As #franji1 stated, try working step by step. If you want to check the code of your list, try testing:
insertSorted("Anna", 1);
insertSorted("Claudio", 2);
insertSorted("Berta", 3);
And check the result is what you expect. Once this is working, add the code asking for input from the user using scanf.
Im not an expert at C but since you mentioned code elegancy I can tell you this. You didn't need to use all these different if statements, you could use the while loop from the begining and insert after you find a name that is bigger than current. This will work even if it has to be inserted before the head node as long as you check that prev is not null. I hope I helped you and that you will find a solution to your problem!

weird number appears on output-C

I have made a simple list like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
struct node{
int am;
struct node *next;
};
typedef struct node node;
int main(){
int n;
node *head=(node *)malloc(sizeof(node));
node *cur=head;
printf("Give me a number:\n");
scanf(" %d",head->am);
cur=head;
while(1){
printf("Give me a number\n");
scanf(" %d",&n);
if(n==0)
break;
cur->am=n;
cur->next=(node *)malloc(sizeof(node));
cur=cur->next;
cur->next=null;
}
travel(head);
printf("Total nodes available :%d\n",count(head));
system("pause");
return 0;
}
Now travel is supposed to go through each node in the list and display the integer saved in each node.
void travel(node *h){
if(h==NULL)
return;
printf("Received data from node: \t %d\n",h->am);
travel(h->next);
}
Now the problem is that when travel is called it wont print the integer from the first node.It will also print another "Received data from node:" followed by a strange number.
For example
If i give 1,2,3,4 as inputs these are the results
Received data from node: 2
Received data from node: 3
Received data from node: 4
Received data from node: 4026432
Any ideas?
Now the problem is that when travel is called it wont print the
integer from the first node
This can be precisely known from this part of the main() function
printf("Give me a number:\n");
scanf(" %d",head->am); //this is wrong use of scanf("%d",&head->am);
cur=head;
while(1){
printf("Give me a number\n");
scanf(" %d",&n);
if(n==0)
break;
cur->am=n;
as I've mentioned you're scanning wrongly but that doesn't matter because later in the code in while loop you replace it this way...
you scan number and store it at head->am
then you assign head to cur so head->am and cur->am are both the same now... so in while loop when you first assign n to cur->am, it gets assigned to head->am. so this explains why you never get to print first node.
Solution:
to overcome it ... in while loop, before assigning cur->am=n try doing:
cur->next=(node *)malloc(sizeof(node));
cur=cur->next;
//then... assign
curr->am=n;
this way you'll not lose first node.
suggestion:
As someone has already said it's much easier to traverse/ travel the list using loops (never mind... if you want to do it recursively)
here's how you do it with the loops:
void travel(node *h)
{
if(h==NULL)
return; //list is empty,consider printing "list empty" :)
while(h!=NULL)
{
printf("Received data from node: \t %d\n",h->am);
h=h->next;
}
}
To put all together your code without changing the travel() function as suggested would be:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int am;
struct node *next;
};
typedef struct node node;
void travel(node *h);
int main() //I have a habit of returning values from main() :)
{
int n;
node *head=(node *)malloc(sizeof(node));
node *cur=head;
printf("Give me a number:\n");
scanf(" %d",&head->am);
cur=head;
while(1)
{
printf("Give me a number\n");
scanf(" %d",&n);
if(n==0)
break;
cur->next=(node *)malloc(sizeof(node));
cur=cur->next;
cur->am=n; //NOTE:here's the change!
cur->next=NULL;
}
travel(head);
return 0; //just to signify successful compilation
}
void travel(node *h)
{
if(h==NULL)
return;
printf("Received data from node: \t %d\n",h->am);
travel(h->next);
}
Sample Input : 5 6 3 1 0
Sample Output :
Give me a number:
5
Give me a number
6
Give me a number
3
Give me a number
1
Give me a number
0
Received data from node: 5
Received data from node: 6
Received data from node: 3
Received data from node: 1
There are (at least) those issues:
The line scanf(" %d",head->am) is wrong since scanf() expects an address of the memory location of the expected value meaning &head->am.
Your loop scans a number and puts it in the current node and only after it creates a new node. Therefore, the first number you enter will be overridden (after fixing the first issue) and the last node created will contain random data because the loop will terminate after entering 0 but before putting anything in the last node.
I propose like this:
int main(void){
int n;
node anchor = {0, NULL};//dummy head
node *head, *cur = &anchor;
while(1){
printf("Give me a number\n");
scanf("%d", &n);
if(n==0)
break;
cur->next = malloc(sizeof(node));
cur = cur->next;
cur->am = n;
cur->next = NULL;
}
head = anchor.next;
travel(head);
printf("Total nodes available :%d\n", count(head));
return 0;
}
You are missing & at the first scanf:
scanf(" %d", &head->am);
But it could be made to do all the scanf inside the while:
int main(){
node *head=0;
node *cur=0;
node *prev=0;
while(1){
prev = cur;
cur=(node *)malloc(sizeof(node));
cur->next=NULL;
printf("Give me a number\n");
scanf("%d",&cur->am);
if(cur->am==0)
break;
if(head == NULL) head = cur;
if(prev != NULL) prev->next = cur;
}
travel(head);
printf("Total nodes available :%d\n",count(head));
return 0;
}
I hope I didnt make any mistake as I wrote it in this SO editor..
and as someone said, you should free the linked list .. but thats out of scope here..
HTH

Creating and adding data in a linked Llist

I have started learning about Linked Lists, which through videos and multiple examples I have pretty much understood what a Linked List is and how it can be represented in a real life analogy. But when it comes to coding it I get lost I suppose through all the pointers I kind of get confused, it took a bit for me to get a stronger grasp on arrays so I assume it will be the same with Linked lists. So here is my code
/*
• The program will use dynamic memory to create a singly linked list(NO ARRAYS PERMITTED)
• The program will store unlimited number of student records(limited only by RAM).
• A student record will consist of Student Name, Age, and GPA…you may need to add additional fields to make this work(Next).
• The program will have a way for the user to add records(in order by name).You can assume that no two students have the same name.The list will always be in order.
• The program will have a way for the user to display ALL records.
• The program needs a way to quit.
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#pragma warning(disable: 4996)// disables warning
typedef struct{
char name[40];
int age;
float gpa;
struct NODE* next;
}NODE;
void addStudent();
int main(void){
NODE* head = NULL;
int userinput;
printf(" **********************************\n");
printf(" * MENU *\n");
printf(" * 1. Add Student *\n");
printf(" * 2. Display all student records*\n");
printf(" * 3. Quit *\n");
printf(" **********************************\n");
scanf_s("%d%*[^\n]", &userinput); '\n' == getchar();
switch (userinput)
{
case 1: do
{
addStudent(head);
printf("Add another record? 1(y) 2(n)\n");
scanf_s("%d%*[^\n]", &userinput); '\n' == getchar();
} while (userinput == 1);
break;
}
}
void addStudent(NODE* head){
head = malloc(sizeof(NODE));
if (head == NULL)
{
return;
}
NODE * current = head;
printf("Please Enter student name:\n");
fgets(current->name, 40, stdin);
printf("Enter student age:\n");
scanf("%d%*[^\n]", &current->age); '\n' == getchar();
printf("Enter student gpa:\n");
scanf("%f%*[^\n]", &current->gpa); '\n' == getchar();
current->next;
current->next = NULL;
while (current != NULL){
current = head;
printf("%s\n", current->name);
printf("%d\n", current->age);
printf("%0.2f\n", current->gpa);
current = current->next;
}
}
When I compile, it will always print the head I assume its because of current = head within the while loop, I understand why its printing the head over but I am lost on how to arrange this code So that I can create a new node when I add and print all the nodes, through the loop.
The problem is that you never create new nodes to add to the list but always just updating the head. In order to make it work you should:
Allocate a new NODE,
NODE *newNode = malloc(sizeof(NODE));
Load the data into this node
printf("Please Enter student name:\n");
fgets(&newNode->name, 40, stdin);
printf("Enter student age:\n");
scanf("%d%*[^\n]", &newNode->age); '\n' == getchar();
printf("Enter student gpa:\n");
scanf("%f%*[^\n]", &newNode->gpa); '\n' == getchar();
Update the node to point to the node currently pointed by the HEAD
newNode->next = head
Update the head to point to the new Node
head = newNode;

passing values in a linked list add function

I have spent the last 2.5 hours creating this linked list and trying to understand why it is not passing a memory address to the head of the list. I'm trying to understand linked lists in C before I move onto what my class is learning about data structures in java. I looked into other questions and I don't understand why it doesn't work. Please excuse the comments I've been making an effort to understand everything. Thanks in advance for your time and help!
The head variable is equal to NULL after the new assignment
head = addFamMember(NULL); in the main thread. But I can see that memory has been allocated inside the add function by printing it's members (name, age, and next pointer). Here's the output:
Enter command to add, print, or quit: add
Enter name and age: brett 28
Added:brett Age:28 POINTING to:(null)
Enter command to add, print, or quit:
Here's the code: I left he comments to possibly help describe my thinking and pinpoint where I'm going wrong.
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
typedef struct S_Family{
char name[16];
int age;
struct S_Family *next;
}Family;
//prototypes
Family *addFamMember (Family *previous);
void CleanUp(Family *start);
void PrintList(Family *start);
int main(){
setvbuf(stdout, NULL, _IONBF, 0);
printf("Enter command to add, print, or quit: ");
char input[16]; //fgets var to store input
char command[16]; //sscanf var to store read info from input
Family *head = NULL; //For a linked list we need to set up the first node and point it NULL
Family *newest = NULL; //We also need a pointer dedicated to updating the latest created node
//This while loop will continue to get input until the command "quit" is typed
//It includes the functionality of printing the list and adding new nodes
while( fgets(input, 15, stdin)){
sscanf(input, "%s", command);
if ( strcmp(command, "quit") == 0) {
printf("\n\nBreaking.........");
break;
} else if ( strcmp(command, "print") == 0) {
PrintList(head);
} else if ( strcmp(command, "add") == 0) {
if ( head = NULL){
head = addFamMember(NULL); //If there are no nodes give head a memory address so now we do (recursion somewhat?)
printf("head:%s ", head->name); //this doesn't print!! Head = NULL above for some reason.
newest = head; //newest cannot stay equal to NULL. this allows us to pass it as a param to add function w/out the start being NULL anymore
printf("newest:%s ", newest->name);
} else {
newest = addFamMember(newest); //Recursion where the new node gets a mem address and gets the previous node as guide to cont. the list
} //now we go to the add function
}
printf("\nEnter command to add, print, or quit: ");
}
CleanUp(head);
return 0;
}
/*We want to return a new family member structure
so we start of with a Family return type. The param
as mentioned before needs to be a pointer to the address
of the previous node. That node will be pushed away from the
NULL in a singly or doubly linked list */
Family *addFamMember (Family *previous) {
/*Now we need to get the member variable info for that newFamMember
and store into the newly created data structure newFamMember*/
char input[16];
printf("Enter name and age: ");
fgets(input,15, stdin);
Family *newFamMember = malloc(sizeof(Family)); //create new address for newFamMember
sscanf(input, "%s %d", newFamMember->name, &newFamMember->age); //takes the input (first a string then a integer) and stores it into its proper place
printf("Added:%s Age:%d POINTING to:%S \n\n",newFamMember->name,newFamMember->age, newFamMember->next->name);
newFamMember->next = NULL; //initialize it's pointer member var but more importantly maintains the linked list by pointing to null.
/*Now we tell the computer what to do if this isn't the first node
or not. If it is then there isn't a previous node so there is no
way to set any other nodes' pointers to point to something else*/
if ( previous != NULL){
previous->next = newFamMember; //if previous is not equal to NULL set the previous' next pointer to newFamMember
printf("previous:%s ", previous->next->name);
}
return newFamMember; //we always want to return a newly added family member. That's this function's purpose
}
/*now we can print the list*/
void PrintList (Family *head) { //start is a pointer so we can pass the value of start
Family *currentMember = head; //we create currentMember and set it equal to start so we can iterate through the list and print each one
int count = 0;
if (currentMember == NULL){
printf("There are no family members\n");
}
while (currentMember != NULL) {
count++;
printf("\n\nmember:%d Name:%s Age:%2d POINTING TO:%s\n",
count, currentMember->name,
currentMember->age,
currentMember->next->name);
currentMember = currentMember->next; //move to the next node in the list headed towards NULL
}
}
void CleanUp(Family *head){
Family *freeMe = head;
Family *holdMe = NULL;
while(freeMe != NULL) {
holdMe = freeMe->next;
printf("\nFree Name:%s Age:%d\n",
freeMe->name,
freeMe->age);
free(freeMe);
freeMe = holdMe;
//PrintList(*start);
}
}

Resources