Linked list program for student average - c

I am new to C programming especially linked list. Can someone please help me with my code? When I compile the program there is no error but when I try to run the program its output is wrong. I don't know if the storing is wrong or the printing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* self-referential structure */
struct listNode {
char name[80];
char subject[80]; /* each listNode contains a character */
float unit;
float grade;
struct listNode *nextPtr; /* pointer to next node */
}; /* end structure listNode */
typedef struct listNode ListNode; /* synonym for struct listNode */
typedef ListNode *ListNodePtr; /* synonym for ListNode* */
/* prototypes */
void insert(ListNodePtr *sPtr, char SUB[80], float grade, float unit, char NAME[80]);
int isEmpty(ListNodePtr sPtr);
void printList(ListNodePtr currentPtr, ListNodePtr *sPtr);
void instructions(void);
int main(void)
{
ListNodePtr startPtr = NULL; /* initially there are no nodes */
int choice; /* user's choice */
float grades, units;
char subn[80], stdn[80];
int i, j, std = 0, sub = 0;
instructions(); /* display the menu */
printf("? ");
scanf("%d", &choice);
/* loop while user does not choose 3 */
while (choice != 3) {
switch (choice) {
case 1: /* input data */
printf("Number of Students: (at least 5 students)\n");
scanf("%d", &std);
for (i = 0; i < std; i++) {
printf("\nStudent name: ");
scanf("%s", &stdn);
printf("How many subjects?\n");
scanf("%d", &sub);
for (j = 0; j < sub; j++) {
printf("\nSub­ject: ");
scanf("%s", &subn);
printf("Units­: ");
scanf("%f", &units);
printf("Final­ Grade: ");
scanf("%f", &grades);
insert(&startPtr, subn, grades, units, stdn);
}
}
break;
case 2:
printList(startPtr, &startPtr);
break;
default:
printf("Invalid choice.\n\n");
instructions();
break;
} /* end switch */
printf("\n\n? ");
scanf("%d", &choice);
} /* end while */
printf("End of run.\n");
return 0; /* indicates successful termination */
} /* end main */
/* display program instructions to user */
void instructions(void)
{
printf("Enter your choice:\n"
" 1 to Input Student Data.\n"
" 2 to Display Student Data.\n"
" 3 to end.\n");
} /* end function instructions */
/* for series */
void insert(ListNodePtr *sPtr, char SUB[80], float grade, float unit, char NAME[80])
{
ListNodePtr newPtr; /* pointer to new node */
ListNodePtr previousPtr; /* pointer to previous node in list */
ListNodePtr currentPtr; /* pointer to current node in list */
newPtr = malloc(sizeof(ListNode)); /* create node */
if (newPtr != NULL) { /* is space available */
strcpy(newPtr->na­me, NAME);
strcpy(newPtr->subject, SUB); /* place value in node */
newPtr->grade = grade;
newPtr->unit = unit;
newPtr->nextPtr = NULL; /* node does not link to another node */
previousPtr = NULL;
currentPtr = *sPtr;
/* insert new node at beginning of list */
if (previousPtr == NULL) {
newPtr->nextPtr = *sPtr;
*sPtr = newPtr;
} /* end if */
else { /* insert new node between previousPtr and currentPtr */
previousPtr->nex­tPtr = newPtr;
newPtr->nextPtr = currentPtr;
} /* end else */
} /* end if */
else {
printf("Student data not inserted. No memory available.\n");
} /* end else */
} /* end function insert */
int isEmpty(ListNodePtr sPtr)
{
return sPtr == NULL;
} /* end function isEmpty */
/* Print the list */
void printList(ListNodePtr currentPtr, ListNodePtr *sPtr)
{
float total = 0.00, total2 = 0.00;
/* if list is empty */
if (currentPtr == NULL) {
printf("List is empty.\n\n");
} /* end if */
else {
printf("\n");
printf("%-20s\t%s\­t%s\n", "Subject", "Units", "Final Grade");
/* while not the end of the list */
while (currentPtr != NULL) {
printf("Student­ Name: %s\n", currentPtr->name);
printf("%-20s\t%.2f\t%.2f\n­", currentPtr->subject, ­ currentPtr->unit, currentPtr->grade);
total += currentPtr->unit;
total2 += currentPtr->unit*cur­rentPtr->grade;
currentPtr = currentPtr->nextPtr;
} /* end while */
printf("\nWeight:­ %.2f", total2 / total);
printf("\n///////­/////////////////////­/////////////////////­///");
} /* end else */
} /* end function printList */

Heading
Hi,
I have not looked thoroughly in the code . But , in a quick look I spotted the following basic problem
nextPtr should be a pointer, you are creating an instance and copying the contents of the next structure. This is not efficient.
I will declare it as below
struct listNode *nextPtr; / pointer to next node */
Again , I will change the followingtypedef ListNode ListNodePtr;
typedef ListNode ListNodePtr;
to
typedef ListNode *ListNodePtr;
Try to restructure your code with this, and see how it goes. If not helping, I can have a detailed look in the evening.

Related

Why does it save only one element instead of the whole list? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 months ago.
Improve this question
I'm making a program where the user is supposed add a pack of pasta as the last element of a list, delete the first element of the list or visualize the whole list.
However, when I try to add new elements and visualize the list, it only shows the last element that I've introduced and only saves that element. The program is supposed to save the list in a txt file.
If there are some parts that are unclear, I apologize as English is not my first language and I do not program in English.
#include <stdio.h>
#include <stdlib.h>
/* struct to represent a pack of pasta */
struct Pasta {
char type[20];
char brand[20];
int time;
int raffInt;
};
typedef struct Pasta PASTA;
/* struct to represent a list */
struct Nodo {
PASTA p;
struct Nodo *next;
};
typedef struct Nodo *NODO;
/******************************************************************************
********************* ADD THE LAST ELEMENT OF THE LIST ***********************
******************************************************************************/
/* function that read a pack of pasta */
PASTA leggiPasta() {
PASTA pasta;
/* insert the type */
printf("What type of pasta?\n");
scanf("%s", &pasta.type);
/* insert the brand */
printf("Which brand?\n");
scanf("%s", &pasta.brand);
/* insert the time to be cooked */
printf("Time to be cooked?\n");
scanf("%d", &pasta.time);
/* determine if it is whole or refined*/
do {
printf("Is it whole (PRESS 1) or refined (PRESS 2)?\n");
scanf("%d", &pasta.raffInt);
/* if the value is not valid */
if(pasta.raffInt != 1 && pasta.raffInt != 2)
printf("Not valid\n");
} while(pasta.raffInt != 1 && pasta.raffInt != 2);
return pasta;
}
/* function to insert a pack of pasta at the bottom of the list */
NODO insert(NODO list) {
NODO new;
nuovo = malloc(sizeof(struct Nodo));
/* fill the parts of the pack */
nuovo -> p = leggiPasta();
printf("\n");
new -> next = NULL;
while (list -> next != NULL)
list = list -> next;
/* now list contains the address of the last element of the list */
list -> next = new;
return new;
}
/******************************************************************************
*********************************** PRINT ************************************
******************************************************************************/
/* function to print a pack of pasta */
void printPasta(PASTA p) {
/* print the type */
printf("Type: %s\n", p.typo);
/* print the brand */
printf("Brand: %s\n", p.brand);
/* print the time */
printf("Time to be cooked: %d min\n", p.time);
/* whole or refined */
if(p.raffInt == 1)
printf("Whole\n");
else
printf("Refined\n");
}
/* function to print a list */
void print(NODO list) {
NODO nodo = list;
/* if the list is empty, you don't have to do anything */
if(nodo != NULL) {
printf("\nHere's the list:\n");
while (nodo != NULL) {
printPasta(nodo -> p);
nodo = nodo -> next;
}
printf("\n\n");
}
else
printf("Nothing to print\n\n");
}
/******************************************************************************
************************** DELETE THE FIRST ELEMENT **************************
******************************************************************************/
/* function to delete the first element of the list */
NODO delete(NODO list) {
NODO current;
/* if the list is empty, you don't have to do anything */
if(list == NULL)
current = NULL;
else {
current = list -> next;
free(list);
printf("Deleted\n\n");
}
return current;
}
/******************************************************************************
************************************ FILE ************************************
******************************************************************************/
/* function for the acquisition of a list from a file */
NODO acquisition() {
FILE *fp = fopen("pasta.txt", "r"); //to read a txt file
NODO head = NULL; //head of the list
NODO current;
NODO previous;
PASTA pasta; //a pack of pasta
int read; //if it was read or not
/* if the file is empty, do nothing */
if(fp != NULL) {
ead r = fread(&pasta, sizeof(PASTA), 1, fp);
if (read) { //it was read
/* read the first one */
head = malloc(sizeof(struct Nodo));
head -> p = pasta;
/* keep track of the last one */
previous = head;
/* read the rest of them */
do {
/* read a new one */
read = fread(&pasta, sizeof(PASTA), 1, fp);
if (read) { //it was read
current = malloc(sizeof(struct Nodo));
current -> p = pasta;
/* connect it to the previous one */
previous -> next = current;
/* the new one becomes the precedent */
previous = current;
}
else
previous -> next = NULL;
} while(letto);
printf("List retrieved\n\n");
}
else
printf("List empty\n\n");
fclose(fp);
}
else
printf("Couldn't open it\n\n");
return head;
}
/* function to save a list in a file */
void save(NODO list) {
FILE *fp = fopen("pasta.txt", "w"); //to write a txt file
/* if it's empty do nothing */
if(fp != NULL) {
while (list != NULL) { //go ahead while it has elements
fwrite(&(list -> p), sizeof(struct Nodo), 1, fp);
lista = list -> next; //proceed
}
fclose(fp);
printf("Saved successfully\n\n");
}
else
printf("Couldn't save\n\n");
}
/* main function */
int main() {
NODO list = acquisition(); //create the list
int answer = -1; //to interact with the user
while (answer != 0) {
/* choose the operation */
printf("What do you want to do?\n");
printf("1 -> Insert a new pack of past\n");
printf("2 -> Delete the first element of the list\n");
printf("3 -> Visualise the list\n");
printf("0 -> Finish the program\n");
scanf("%d", &answer);
/* insert */
if(answer == 1) {
list = insert(list);
}
/* delete */
else if(answer == 2) {
list = delete(list);
}
/* visualise */
else if(answer == 3) {
print(list);
}
/* finish the program */
else if (answer == 0) {
printf("Finished, goodbye\n\n");
}
/* wrong number */
else if (answer != 0) {
printf("It has no meaning, \n\n");
}
}
save(list);
}
There are multiple problems in your code:
there were some translation errors: it is recommended to use English for all identifiers in your code to make it easier to collaborate with other programmers. I am not a native speaker either, but this habit proved very effective for me for the last 40 years.
hiding pointers behind typedefs is confusing and error prone. Use typedef struct Node Node; and use Node *.
the file pasta.txt is actually a binary file as you write the contents of the struct Pasta as stored in memory directly to it. You should use a different name and open it as binary with "rb" and "wb".
using a textual format instead of binary is much preferred for portability, readability, extensibility.
function acquisition() should not make a special case of the first element read.
the function insert() crashes is the list is empty. You should test for this and return nuovo if list is a null pointer.
the function insert() should return the list, not the last element added unless the list was initially empty. this is causing the problem stated.
do not use & in front of arrays passed to scanf() and do pass the maximum number of bytes to read:
scanf("%19s", pasta.typo);
when writing to the file, you should use the size of struct Pasta instead of struct Nodo. To avoid this silly mistake, use sizeof(list->p).
Here is a modified version you can study:
#include <stdio.h>
#include <stdlib.h>
/* struct to represent a pack of pasta */
typedef struct Pasta Pasta;
struct Pasta {
char type[20];
char brand[20];
int time;
int raffInt;
};
/* struct to represent a list */
typedef struct Node Node;
struct Node {
Pasta p;
Node *next;
};
/* function that read a pack of pasta */
Pasta leggiPasta(void) {
Pasta pasta;
/* insert the type */
printf("What type of pasta?\n");
scanf("%19s", pasta.type);
/* insert the brand */
printf("Which brand?\n");
scanf("%19s", pasta.brand);
/* insert the time to be cooked */
printf("Time to be cooked?\n");
scanf("%d", &pasta.time);
/* determine if it is whole or refined*/
for (;;) {
printf("Is it whole (PRESS 1) or refined (PRESS 2)?\n");
scanf("%d", &pasta.raffInt);
/* if the value is not valid */
if (pasta.raffInt == 1 || pasta.raffInt == 2)
break;
printf("Not valid\n");
}
printf("\n");
return pasta;
}
/* function to insert a pack of pasta at the bottom of the list */
Node *insert(Node *list) {
Node *new_node = calloc(sizeof(*new_node), 1);
/* fill the parts of the pack */
new_node->p = leggiPasta();
new_node->next = NULL;
if (list == NULL) {
list = new_node;
} else {
Node *tail = list;
while (tail->next != NULL)
tail = tail->next;
/* now tail contains the address of the last element of the list */
tail->next = new_node;
}
return list;
}
/* function to print a pack of pasta */
void printPasta(Pasta p) {
/* print the type */
printf("Type: %s\n", p.type);
/* print the brand */
printf("Brand: %s\n", p.brand);
/* print the time */
printf("Time to be cooked: %d min\n", p.time);
/* whole or refined */
if (p.raffInt == 1)
printf("Whole\n");
else
printf("Refined\n");
}
/* function to print a list */
void print(Node *list) {
Node *node = list;
/* if the list is empty, you don't have to do anything */
if (node != NULL) {
printf("\nHere's the list:\n");
while (node != NULL) {
printPasta(node->p);
node = node->next;
}
printf("\n\n");
} else {
printf("Nothing to print\n\n");
}
}
/* function to delete the first element of the list */
Node *delete(Node *list) {
Node *current;
/* if the list is empty, you don't have to do anything */
if (list == NULL) {
current = NULL;
} else {
current = list->next;
free(list);
printf("Deleted\n\n");
}
return current;
}
/* function for the acquisition of a list from a file */
Node *acquisition(void) {
FILE *fp = fopen("pasta.txt", "r"); //to read a txt file
Node *head = NULL; //head of the list
Node *tail = NULL;
Node *current;
Pasta pasta; //a pack of pasta
int count = 0;
/* if the file is empty, do nothing */
if (fp != NULL) {
char buf[100];
while (fgets(buf, sizeof buf, fp)) {
if (sscanf(buf, "%19[^,],%19[^,],%d,%d",
pasta.type, pasta.brand,
&pasta.time, &pasta.raffInt) == 4)
{
count++;
/* allocate a new node */
current = calloc(sizeof(*current), 1);
current->p = pasta;
current->next = NULL;
if (tail == NULL) {
tail = head = current;
} else {
tail = tail->next = current;
}
} else {
fprintf(stderr, "invalid format: %s", buf);
}
}
fclose(fp);
if (count) {
printf("List retrieved: %d elements\n\n", count);
} else {
printf("List empty\n\n");
}
} else {
printf("Couldn't open file\n\n");
}
return head;
}
/* function to save a list in a file */
int save(Node *list) {
FILE *fp = fopen("pasta.txt", "w"); //to write a txt file
if (fp != NULL) {
while (list != NULL) { //go ahead while it has elements
fprintf(fp, "%s,%s,%d,%d\n",
list->p.type, list->p.brand,
list->p.time, list->p.raffInt);
list = list->next; //proceed
}
fclose(fp);
printf("Saved successfully\n\n");
return 0;
} else {
printf("Couldn't save\n\n");
return 1;
}
}
/* main function */
int main() {
Node *list = acquisition(); //create the list
int answer; //to interact with the user
for (;;) {
/* choose the operation */
printf("What do you want to do?\n");
printf("1 -> Insert a new pack of past\n");
printf("2 -> Delete the first element of the list\n");
printf("3 -> Visualise the list\n");
printf("0 -> Finish the program\n");
if (scanf("%d", &answer) != 1)
break;
if (answer == 1) {
/* insert */
list = insert(list);
} else
if (answer == 2) {
/* delete */
list = delete(list);
} else
if (answer == 3) {
/* visualise */
print(list);
} else
if (answer == 0) {
/* finish the program */
printf("Finished, goodbye\n\n");
break;
} else {
/* wrong number */
printf("It has no meaning\n\n");
}
}
return save(list);
}

Having Trouble printing a doubly linked list

I am currently having trouble trying to print my doubly linked list out. The problem is either in the getSongInfo function or in the printSongInfo function. I am very new to coding and all the help is greatly appreciated. I also don't know how to use the tail pointer when using a doubly linked list.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<malloc.h>
#pragma warning(disable : 4996)
#pragma warning(disable : 6387)
#pragma once
//structs
typedef struct {
char* title;
char* artist;
int rating;
SongNode* next;
SongNode* prev;
}SongNode;
//Constants
#define kInfiniteLoop 1
#define kStringLength 30
//Prototypes
int getNum(void);
void eliminateEndOfLine(char* buffer);
void printSongInfo(SongNode* head);
SongNode* getSongInfo(SongNode** head, SongNode** tail, char title[], char artist[], int rating);
int main() {
char title[kStringLength];
char artist[kStringLength];
int rating = 0;
SongNode* head = NULL;
SongNode* tail = NULL;
printf("Enter Title, Artist and Rating\n");
printf("Enter'.' to get out of the loop and print list\n");
while (kInfiniteLoop) {
printf("Title: ");
fgets(title, kStringLength, stdin);
eliminateEndOfLine(title);
if (strcmp(title, ".") == 0) {
break;
}
printf("Artist: ");
fgets(artist, kStringLength, stdin);
eliminateEndOfLine(artist);
printf("Rating: ");
while (rating = getNum()) { // error check the rating this will check to make sure the rating is in the range 1-5.
if (rating < 1 || rating>5) {
printf("The number you have entered is invaild\n");
rating = 0;
printf("Rating: ");
continue;
}
break;
head=getSongInfo(&head, &tail, title, artist, rating);
printf("\n");
}
}
printSongInfo(head);
return 0;
}
/*===============================================================================================================*/
/*FUNCTION :getNum(void) */
/*PARAMETERS :void */
/*RETURNS :number */
/*DESCRIPTION:This function is the user input function to get a number rating */
/*===============================================================================================================*/
int getNum(void)
{/* the array is 121 bytes in size; we'll see in a later lecture how we can improve this code */
char record[121] = { 0 }; /* record stores the string */
int number = 0;
/* NOTE to student: indent and brace this function consistent with your others */
/* use fgets() to get a string from the keyboard */
fgets(record, 121, stdin);
/* extract the number from the string; sscanf() returns a number
* corresponding with the number of items it found in the string */
if (sscanf(record, "%d", &number) != 1)
{
/* if the user did not enter a number recognizable by
* the system, set number to -1 */
number = -1;
}
return number;
}
/*=======================================================================================================*/
/*FUCNTION :void eliminateEndOfLine */
/*PARAMETER :(char* buffer) */
/*RETURNS :void */
/*DESCRIPTION :This function takes a pointer to a string and looks through the string to find the */
/* newline.It takes the new line out of the string. */
/*=======================================================================================================*/
void eliminateEndOfLine(char* buffer)
{
char* target = strchr(buffer, '\n');
if (target != NULL)
{
*target = '\0';
}
}
SongNode* getSongInfo(SongNode** head, SongNode** tail, char title[], char artist[], int rating)
{
SongNode *newBlock = NULL;
newBlock = (SongNode*)malloc(sizeof(SongNode));
if (newBlock == NULL) {
printf("No memory to be Allocated\n");
return (*head);
}
newBlock->title=(char*)malloc(strlen(title) + 1);
if (newBlock->title == NULL) {
printf("No memory can be allocated for title\n");
return (*head);
}
newBlock->artist = (char*)malloc(strlen(artist) + 1);
if (newBlock->rating == NULL) {
printf("No memory can be alocated for artist\n");
return (*head);
}
newBlock->rating = (int)malloc(sizeof(int));
if (newBlock->rating == NULL) {
printf("No memory can be alllocated for rating \n");
return (*head);
}
strcpy(newBlock->title, title);
strcpy(newBlock->artist, artist);
newBlock->rating = rating;
newBlock->next = (*head);
newBlock->prev = NULL;
if ((*head) != NULL)
(*head)->prev = newBlock;
(*head) = newBlock;
return (*head);
}
void printSongInfo(SongNode* head) {
SongNode* ptr;
ptr = head;
printf("\n");
printf("%-35s %-35s %-35s\n", "Title", "Artist","Rating");
while (ptr != NULL) {
printf("%-35s %-35s %-35d\n", ptr->title, ptr->artist);
ptr = ptr->next;
}
}
You have a break statement in the while (rating = getnum()) loop that shouldn't be there. It will cause the loop to terminate before getting any song info.
Other problems:
newBlock->rating = (int)malloc(sizeof(int)); will leak memory, because you allocate some but never free it. Because rating is an int, memory does not need to be allocated for it. (Also, see Do I cast the result of malloc?).
getSongInfo should either return the new head, or update the current one, but not both.
Updating tail is similar to updating head, but does not need to be done all the time when inserting at the head (there's a condition that you'll need to check for).
You don't need #pragma once in a C source file. That should be in a header (and is only supported on some compilers).

Insertion sort parameter chooser for linked list filled with data from a csv file in C

i guess this is question is as custom as it can get because i haven't found anything like it online.
i am doing a homework for school where i am supposed to create a program that takes as input a file of type csv containing student information(first name, last name , phone number, class, etc ), creates and fills up a chained list from the info in that file, sorts it using a column of the user's choice, then displays the sorted list.
i got the program to work, but the part where the user can choose a sort column i haven't written it yet; right now, the sort parameter is injected inside the sort function.
i need your help to find out how i can take the input of the user and get it inside the sort function..
which data type points to the sort column inside the linked list? i tried pointers but i got nowhere..
here is the code:
// ============================
// BEGINNING OF CODE
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <conio.h>
#include <string.h>
// ============================
// DEFINE
#define FILE_TO_READ "TPP_TP_Data_2019_base.csv"
// ============================
// GLOBAL VARIABLES
typedef struct node
{
char Lastname[50];
char Firstname[50];
char Initials[50];
char Mobile[50];
char Class[50];
char InitialSort[50];
char RandomSort[50];
struct node *next;
} node;
node *HEAD=NULL;
// ============================
// FONCTION PROTOTYPE DECLARATIONS
node * Read();
void Display(node *);
void Sort();
void InsertionSort(node **);
void sortedInsert(node** ,node*);
// ============================
// MAIN
int main()
{
HEAD=Read();
Display(HEAD);
printf("\n\n\n");
Sort();
printf("\n\n\n");
InsertionSort(&HEAD);
return 0;
}
// ============================
// FUNCTIONS
node * Read()
{
FILE *fPointer;
fPointer = fopen(FILE_TO_READ,"r");
if (fPointer == NULL)
{
printf("\nCould not open file %s",FILE_TO_READ);
exit(1);
}
//reading the file and creating liked list
char parsedLine[100];
node *head = NULL;
node *p = NULL;
while(fgets(parsedLine, 100, fPointer) != NULL)
{
node * temp=malloc(sizeof(node));
char *getNom = strtok(parsedLine, ";");
strcpy(temp->Lastname, getNom);
char *getPrenom = strtok(NULL, ";");
strcpy(temp->Firstname, getPrenom);
char *getInitials = strtok(NULL, ";");
strcpy(temp->Initials, getInitials);
char *getMobile = strtok(NULL, ";");
strcpy(temp->Mobile, getMobile);
char *getClasse = strtok(NULL, ";");
strcpy(temp->Class, getClasse);
char *getTriInitial = strtok(NULL, ";");
strcpy(temp->InitialSort, getTriInitial);
char *getTriAleatoire = strtok(NULL, ";");
strcpy(temp->RandomSort, getTriAleatoire);
temp->next = NULL;
if(head == NULL) // if first is empty, then make temp the first node
{
head = temp;
}
else
{
p=head;
while(p->next != NULL)
p=p->next;
p->next=temp;
}
}
fclose(fPointer);
return head;
}
void Display(node * head) // prints out the contents of the linked list // done
{
node *temp=head;
while(temp!=NULL)
{
printf("%s %s %s %s %s %s %s \n",temp->Lastname,temp->Firstname,temp->Initials,temp->Mobile,temp->Class,temp->InitialSort,temp->RandomSort);
temp = temp->next;
}
printf("\n");
printf("===========================================");
}
void Sort()
{
char SortParameter;
// declare SortChoice here;
printf("\n Enter sort Parameter : ");
printf("\n P - Firstname");
printf("\n N - Lastname");
printf("\n I - Initials");
printf("\n M - Mobile");
printf("\n C - Class");
printf("\n X - Tri Initial");
printf("\n Z - Tri Aleatoire");
printf("\n Your Choice : ");
fflush(stdin);
SortParameter=getch();
/*
switch(SortParameter)
{
case 'P': SortChoice = ;
case 'N': SortChoice = ;
case 'I': SortChoice = ;
case 'M': SortChoice = ;
case 'C': SortChoice = ;
case 'X': SortChoice = ;
case 'Z': SortChoice = ;
}
*/
putch(SortParameter);
printf("\n\n");
printf("\n Sorting done, Here is the Sorted list : \n");
InsertionSort(&HEAD);
Display(HEAD);
}
void InsertionSort(node **head_ref) // function to sort a singly linked list using insertion sort
{
// Initialize sorted linked list
node *sorted = NULL;
// Traverse the given linked list and insert every node to sorted
node *current = *head_ref;
while (current != NULL)
{
// Store next for next iteration
node *next = current->next;
// insert current in sorted linked list
sortedInsert(&sorted, current);
// Update current
current = next;
}
// Update head_ref to point to sorted linked list
*head_ref = sorted;
}
void sortedInsert(node** head_ref,node* new_node)
{
node* current;
// Special case for the head end
if (*head_ref == NULL || (*head_ref)->Firstname >= new_node->Firstname)
{
new_node->next = *head_ref;
*head_ref = new_node;
}
else
{
// Locate the node before the point of insertion
current = *head_ref;
while (current->next!=NULL && strcmp(current->next->Firstname, new_node->Firstname)<0 )
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
}
}
//=========================================================

Having an issue with link lists in c

I am having problems with some code I have to add the option to input a person into my structure link list. I can add the person to the first node with an integer for an identifier but then when I come to add another it only asks for the integer not for the other details. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include "linkedlist.h" /* conatins structure definition */
/* Function Prototypes
Note that variable names have been removed as they are
not actually required - they are optional
*/
int fnTotalList(struct listnode *);
struct listnode *fnAddItem(struct listnode *, int);
void fnPrintList(struct listnode *);
int fnMenu(void);
struct listnode *fnRemoveEndItem(struct listnode *, int *);
struct listnode *fnRemoveStartItem(struct listnode *, int *);
void fnSearchList(struct listnode *, int);
int main(int argc, char *argv[])
{
struct listnode *ptrHead = NULL;
struct listnode *ptrTemp = NULL;
int nChoice = 0;
int nRun = 1;
int nItem = 0;
while(nRun)
{
nChoice = fnMenu();
switch(nChoice)
{
case 1: /* Add an item */
printf("Please enter an integer : ");
scanf("%d", &nItem);
ptrHead = fnAddItem(ptrHead,nItem);
break;
case 2: /* Print the list */
fnPrintList(ptrHead);
printf("The list total is %d\n", fnTotalList(ptrHead));
break;
case 3: /* Remove an end item */
ptrHead = fnRemoveEndItem(ptrHead, &nItem);
if(nItem == -9999)
printf("Nothing to remove - empty list\n\n");
else
printf("The removed value is %d\n\n", nItem);
break;
case 4: /* Remove a start item */
ptrHead = fnRemoveStartItem(ptrHead, &nItem);
if(nItem == -9999)
printf("Nothing to remove - empty list\n\n");
else
printf("The removed value is %d\n\n", nItem);
break;
case 5: /* Search the list */
printf("Please enter the search value : ");
scanf("%d", &nItem);
fnSearchList(ptrHead, nItem);
break;
case 6: /* Exit program */
nRun = 0; /* set to zero to stop the while loop */
break;
}
}
return 0;
}
struct listnode *fnAddItem(struct listnode *ptrH, int nNumber)
{
struct listnode *ptrTemp = NULL;
if(ptrH == NULL)
{
/* Special case - list empty */
ptrH = (struct listnode *)malloc(sizeof(struct listnode));
if(ptrH == NULL)
{
printf("Adding to empty list - malloc has failed\n");
exit(1);
}
/* malloc has worked - set values */
(*ptrH).nVal = nNumber;
printf("Please Enter First , Second & Last Name : ");
scanf("%s %s %s",(*ptrH).arcFirstName,(*ptrH).arcMiddleName,(*ptrH).arcLastName);
printf("Please Enter Sex M or F : ");
scanf("%s", (*ptrH).cSex);
printf("DOB - DDMMYYYY\n");
scanf("%i %i %i", &nD, &nM, &nY);
(*ptrH).strDOB.nDay=nD;
(*ptrH).strDOB.nMonth=nM;
(*ptrH).strDOB.nYear=nY;
ptrH->ptrNext = NULL; /* This is important as it signals
the last node within the list */
}
else
{
/* There are items already in the list
need to locate the end - use a while loop
to step through looking for ptrNext to
equal NULL */
ptrTemp = ptrH; /* Use a temp pointer */
while(ptrTemp->ptrNext != NULL)
{
/* As ptrNext has a value there is a node
hanging off it */
ptrTemp = ptrTemp->ptrNext;
}
/* ptrTemp is now pointing at the last node
within the list
Now, create a new node that "hangs off"
ptrNext within this last node */
ptrTemp->ptrNext = (struct listnode *)malloc(sizeof(struct listnode));
if(ptrTemp->ptrNext == NULL)
{
printf("Adding to end of list - malloc has failed\n");
exit(1);
}
ptrTemp->ptrNext->nVal = nNumber;
ptrTemp->ptrNext->ptrNext = NULL;
}
return ptrH; /* This is really only needed when adding the first item
to the list - but have to do it in all cases to avoid
error messages */
}
int fnMenu(void)
{
int nChoice;
printf("Choices menu\n\n");
printf("1.\tAdd an item\n");
printf("2.\tPrint list\n");
printf("3.\tRemove an end item\n");
printf("4.\tRemove a start item\n");
printf("5.\tSearch for a value\n");
printf("6.\tQuit\n\n");
printf("Please enter a choice :");
scanf("%d", &nChoice);
return nChoice;
}
void fnPrintList(struct listnode *ptrH)
{
if(!ptrH)
{
printf("\n\n\tEmpty list\n");
}
else
{
while(ptrH)
{
printf("%d\n", ptrH->nVal);
ptrH = ptrH->ptrNext;
}
printf("\nEnd of list\n\n");
}
}
struct listnode *fnRemoveEndItem(struct listnode *ptrH, int *ptrNum)
{
/* There are two special cases ...
1. When the list is empty
2. When there is only one node within the list
*/
struct listnode *ptrTemp = NULL;
if(!ptrH)
{
/* The list is empty */
*ptrNum = -9999; /* A value to signal empty list */
}
else if(!ptrH->ptrNext)
{
/* There is only one node in the list
as ptrNext within the first node
is NULL
*/
*ptrNum = ptrH->nVal;
free(ptrH); /* This releases the memory allocated
by malloc() back to the heap */
ptrH = NULL; /* As this was the last item to remove
need to return NULL so that ptrHead
is set to NULL */
}
else
{
/* There are more than one nodes in the list,
need to step through to find the last but
one node
*/
ptrTemp = ptrH;
while(ptrTemp->ptrNext->ptrNext)
{
ptrTemp = ptrTemp->ptrNext;
}
/* ptrTemp is now pointing to the last but
one node so can delete the last one
*/
*ptrNum = ptrTemp->ptrNext->nVal;
free(ptrTemp->ptrNext);
ptrTemp->ptrNext = NULL; /* Set to NULL as this is
now the last node
*/
}
return ptrH;
}
struct listnode *fnRemoveStartItem(struct listnode *ptrH, int *ptrNum)
{
struct listnode *ptrTemp = NULL;
if(!ptrH)
{
/* Empty list */
*ptrNum = -9999;
return ptrH;
}
else
{
ptrTemp = ptrH->ptrNext;
*ptrNum = ptrH->nVal;
free(ptrH);
return ptrTemp;
}
}
void fnSearchList(struct listnode *ptrH, int nSearchVal)
{
struct listnode *ptrTemp = ptrH;
int nCount = 0;
if(!ptrH)
{
/* Empty List */
printf("\n\nEmpty List \n\n");
}
else
{
while(ptrTemp->ptrNext)
{
if(ptrTemp->nVal == nSearchVal)
{
printf("The value %d has been located\n", ptrTemp->nVal);
nCount++;
}
ptrTemp = ptrTemp->ptrNext;
}
if(!nCount)
printf("\t\tValue not found within the list\n");
else
printf("\t\tA total of %d were found\n", nCount);
}
printf("The list totals %d\n", fnTotalList(ptrH));
}
int fnTotalList(struct listnode *ptrH)
{
struct listnode *ptrTemp = ptrH;
int nTotal = 0;
if(ptrTemp)
{
while(ptrTemp)
{
nTotal += ptrTemp->nVal;
ptrTemp = ptrTemp->ptrNext;
}
}
return nTotal;
}
In the function fnAddItem, there are two cases, one is when the pointer is NULL, that is List Empty and you are adding the first node correctly.
Another one is when there is already some node, you are traversing to the last and adding one node there, but did not ask for input. Thats why for 2nd node onwards you don't have other details.
After you malloc in the else part, you have to take input as you did in the if part.
struct listnode *fnAddItem(struct listnode *ptrH, int nNumber)
{
struct listnode *ptrTemp = NULL;
if(ptrH == NULL)
{
/* Special case - list empty */
ptrH = (struct listnode *)malloc(sizeof(struct listnode));
if(ptrH == NULL)
{
printf("Adding to empty list - malloc has failed\n");
exit(1);
}
/* malloc has worked - set values */
(*ptrH).nVal = nNumber;
printf("Please Enter First , Second & Last Name : ");
scanf("%s %s %s",(*ptrH).arcFirstName,(*ptrH).arcMiddleName,(*ptrH).arcLastName);
printf("Please Enter Sex M or F : ");
scanf("%s", (*ptrH).cSex);
printf("DOB - DDMMYYYY\n");
scanf("%i %i %i", &nD, &nM, &nY);
(*ptrH).strDOB.nDay=nD;
(*ptrH).strDOB.nMonth=nM;
(*ptrH).strDOB.nYear=nY;
ptrH->ptrNext = NULL; /* This is important as it signals
the last node within the list */
}
else
{
/* There are items already in the list
need to locate the end - use a while loop
to step through looking for ptrNext to
equal NULL */
ptrTemp = ptrH; /* Use a temp pointer */
while(ptrTemp->ptrNext != NULL)
{
/* As ptrNext has a value there is a node
hanging off it */
ptrTemp = ptrTemp->ptrNext;
}
/* ptrTemp is now pointing at the last node
within the list
Now, create a new node that "hangs off"
ptrNext within this last node */
ptrTemp->ptrNext = (struct listnode *)malloc(sizeof(struct listnode));
if(ptrTemp->ptrNext == NULL)
{
printf("Adding to end of list - malloc has failed\n");
exit(1);
}
/* malloc has worked - set values */
ptrTemp->ptrNext->nVal = nNumber;
printf("Please Enter First , Second & Last Name : ");
scanf("%s %s %s",ptrTemp->ptrNext->arcFirstName,ptrTemp->ptrNext->arcMiddleName,ptrTemp->ptrNext->arcLastName);
printf("Please Enter Sex M or F : ");
scanf("%s", ptrTemp->ptrNext->cSex);
printf("DOB - DDMMYYYY\n");
scanf("%i %i %i", &nD, &nM, &nY);
ptrTemp->ptrNext->strDOB.nDay=nD;
ptrTemp->ptrNext->strDOB.nMonth=nM;
ptrTemp->ptrNext->strDOB.nYear=nY;
ptrTemp->ptrNext->ptrNext = NULL; /* This is important as it signals
the last node within the list */
}
return ptrH; /* This is really only needed when adding the first item
to the list - but have to do it in all cases to avoid
error messages */
}
It is a bad design though, you should malloc once, take the inputs and fill the structure and then add it in appropriate place to the list. In that way you can omit a huge part of redundant code in the function.

Scanf Validation

Can someone help me validate the inputs for the Scanf's i have below. I want the programme to ask for the data to be re-entered if the Scanf's are within an incorrect range or not an interger. I put in a do while loop before with an if statement but when i compiled it the first printf and scanf just looped
#include <stdio.h>
#include <stdlib.h>
int MenuLoop = 0;
int MaxPackets = 4;
int currentPackets= 0;
int menu;
/*********************************************************
* Node to represent a Cat which includes a link reference*
* a link list of nodes with a pointer to a Cat Struct *
* would be better but this is for illustartion only! *
**********************************************************/
struct Packet {
int Source;
int Destination;
int Type;
int Port;
char *Data;
struct Packet *next; // Link to next Cat
};
typedef struct Packet node; // Removes the need to constantly refer to struct
/*********************************************************
* Stubs to fully declared functions below *
**********************************************************/
void outputPackets(node **head);
void push(node **head, node **aPacket);
node* pop(node **head);
void AddPacket();
void AddPacket();
void SavePacket();
void ShowCurrent();
void ExitProgramme();
main() {
do{
Menu();
} while(menu<4);
}
void AddPacket(){
int option;
/*********************************************************
* pointers for the link list and the temporary P to *
* insert into the list *
**********************************************************/
node *pPacket, *pHead = NULL;
/*********************************************************
* Create a cat and also check the HEAP had room for it *
**********************************************************/
pPacket = (node *)malloc(sizeof(node));
if (pPacket == NULL)
{
printf("Error: Out of Memory\n");
exit(1);
}
currentPackets++;
printf("Enter Source Number between 1-1024:\n");
scanf("%i", &pPacket->Source);
printf("Enter Destination Number between 1-1024:\n");
scanf("%i", &pPacket->Destination);
printf("Enter Type Number between 0-10:\n");
scanf("%i", &pPacket->Type);
printf("Enter Port Number between 1-1024:\n");
scanf("%i", &pPacket->Port);
printf("Enter Data Numberbetween 1-50:\n");
scanf("%s", &pPacket->Data);
printf("Do you want to Enter another Packet?");
pPacket->next = NULL;
/*********************************************************
* Push the Cat onto the selected Link List, the function *
* is written so the program will support multiple link *
* list if additional 'pHead' pointers are created. *
* Who says you cannot herd cats! *
**********************************************************
* NOTE: The push parameters are using references to the *
* pointers to get round the pass by value problem caused *
* by the way C handles parameters that need to be *
* modified *
**********************************************************/
push(&pHead, &pPacket);
pPacket = (node *)malloc(sizeof(node));
if (pPacket == NULL)
{
printf("Error: Out of Memory\n");
exit(1);
}
outputPackets(&pHead);
/*********************************************************
* Display the Link List 'pHead' is passed as a reference *
**********************************************************/
return 0;
do{
if(currentPackets == MaxPackets);
{
printf("Packet limit reached please save\n");
}
}while(currentPackets<MaxPackets);
return 0;
}
void outputPackets(node **head)
{
/*********************************************************
* Copy Node pointer so as not to overwrite the pHead *
* pointer *
**********************************************************/
node *pos = *head;
/*********************************************************
* Walk the list by following the next pointer *
**********************************************************/
while(pos != NULL) {
printf("Source: %.4i Destination: %.4i Type: %.4i Port: %.4i \n", pos->Source, pos->Destination, pos->Type, pos->Port);
pos = pos->next ;
}
printf("End of List\n\n");
}
void push(node **head, node **aPacket)
{
/*********************************************************
* Add the cat to the head of the list (*aCat) allows the *
* dereferencing of the pointer to a pointer *
**********************************************************/
(*aPacket)->next = *head;
*head = *aPacket;
}
node *pop(node **head)
{
/*********************************************************
* Walk the link list to the last item keeping track of *
* the previous. when you get to the end move the end *
* and spit out the last Cat in the list *
**********************************************************/
node *curr = *head;
node *pos = NULL;
if (curr == NULL)
{
return NULL;
} else {
while (curr->next != NULL)
{
pos = curr;
curr = curr->next;
}
if (pos != NULL) // If there are more cats move the reference
{
pos->next = NULL;
} else { // No Cats left then set the header to NULL (Empty list)
*head = NULL;
}
}
return curr;
}
void SavePacket(){
FILE *inFile ;
char inFileName[10] = { '\0' } ;
printf("Input file name : ") ;
scanf("%s", inFileName) ;
//Open file
inFile = fopen(inFileName, "w+");
if (!inFile)
{
fprintf(stderr, "Unable to open file %s", &inFile);
exit(0);
}
//fprintf(inFile, "Source: %i Destination: %i Type: %i Port: %i \n", pos->Source, pos->Destination, pos->Type, pos->Port);
fclose(inFile);
}
void ShowCurrent(){
}
void ExitProgramme(){}
void Menu(){
printf("********Welcome****** \n");
printf("Creator Ben Armstrong.\n\n");
printf("*Please Choose an option*\n");
printf("1. Add a new packet\n");
printf("2. Save current packet to file\n");
printf("3. Show current list of packets\n");
printf("4. Exit\n");
scanf("%i", &menu);
switch(menu)
{
case 1:
AddPacket();
break;
case 2:
SavePacket();
break;
case 3 :
ShowCurrent();
break;
case 4 :
ExitProgramme();
break;
}
}
This is my full code as u can see im trying to implement a link list which the data has to be validated for
Use the following macro
#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
char tmp;\
while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
|| !(COND)) {\
printf("Invalid input, please enter again: ");\
}\
} while(0)
You find in this topic the macro explaination
Example of using it :
int main()
{
.......
printf("Enter Source Number between 1-1024:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Source, (pPacket->Source>=1 && pPacket->Source<=1024);
printf("Enter Destination Number between 1-1024:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Destination, (pPacket->Destination>=1 && pPacket->Destination<=1024);
printf("Enter Type Number between 0-10:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Type, (pPacket->Type>=0 && pPacket->Type<=10);
printf("Enter Port Number between 1-1024:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Port, (pPacket->Port>=1 && pPacket->Port<=1024);
printf("Enter Data Numberbetween 1-50:\n");
SCAN_ONEENTRY_WITHCHECK("%i", &pPacket->Data, (pPacket->Data>=1 && pPacket->Data<=50);
}
Here is one approach using strtol:
#include <stdlib.h>
#include <stdio.h>
struct Packet {
int Source;
int Destination;
int Type;
int Port;
int Data;
};
void func(struct Packet *pPacket) {
char entry[100];
int i;
char *tail;
do {
printf("Enter Source Number between 1-1024:\n");
scanf("%99s", entry);
i = strtol(entry, &tail, 0);
} while (*tail || i < 1 || i > 1024);
pPacket->Source = i;
}
int main(int argc, char* argv[])
{
struct Packet pPacket;
func(&pPacket);
printf("pPacket->Source is now %i.\n", pPacket.Source);
return 0;
}

Resources