Im writing database program for my c class for few days now im trying to figure out how to work with singly linked lists its pretty hard to understand I would say ,well at least for me. Overall I got part of code necessary for my project, basicaly I got functions to add client and items to client thanks to help of somebody from stackoverflow I kinda figured how to add multiple items to 1 client but now I'm in trouble figuring out how exactly can I print it ,tried to do it the way you can see im my display function but it doesnt work for items linked to client what should I change to make it work?
#include <stdio.h>
#include <stdlib.h>
struct item{
char item_name[30];
struct item *NextItem;
};
struct client{
struct client *NextClient;
char name[30];
char last_name[30];
struct item *firstItem;
struct item *lastItem;
};
struct client *head = NULL;
/////////////////////////////
struct client* FindTailClient(struct client* head)
{
struct client *temp = head;
while( temp->NextClient != NULL)
{
temp = temp->NextClient;
}
return temp;
}
/////////////////////////////
////////
struct client *GetClientData()
{
char data[30];
struct client *temp;
temp = (struct client*)malloc(sizeof(struct client));
printf("Enter the person's name--->");
scanf("%s",data);
strcpy(temp->name,data);
printf("Enter the person's last name--->");
scanf("%s",data);
strcpy(temp->last_name,data);
temp->NextClient = NULL;
return temp;
}
///////////
struct item *GetItemData()
{
struct item *temp;
char data[30];
temp = (struct item*)malloc(sizeof(struct item));
printf("Enter the item name--->");
scanf("%s",data);
strcpy(temp->item_name,data);
temp->NextItem = NULL;
return temp;
}
///////////
//////////////
struct client* AddClient()
{
struct client *temp,temp1;
temp=head;
struct client *data = GetClientData();
if(head == NULL)
{
head=data;
head->NextClient = NULL;
}
else
{
while(temp->NextClient != NULL)
{
temp=temp->NextClient;
}
data->NextClient=NULL;
temp->NextClient=data;
}
}
///////////////////
///////////////////
///////////////////
void display()
{
struct client *CurrentClient = head;
struct item *ItemCurrent = head->firstItem;
while(CurrentClient != NULL)
{
printf(" -> %s ->%s \n",CurrentClient->name,CurrentClient->last_name);
while(ItemCurrent != NULL)
{
printf(" -> %s\n",ItemCurrent->item_name);
ItemCurrent=ItemCurrent->NextItem;
}
CurrentClient=CurrentClient->NextClient;
}
}
///////////////////
void AddItemToClient(struct client* head, struct item *item)
{
item->NextItem = NULL;
if(head->firstItem == NULL) {
head->firstItem = item;
} else {
head->lastItem->NextItem = item;
}
head->lastItem = item;
}
///////////////////
struct client *find(struct client *head, char name[])
{
while (head->NextClient != NULL )
{
if (strcmp(head->name,name) == 0)
{
printf("Target found: %s\n",head->name);
return head;
}
head = head->NextClient;
}
printf("target not found");
return NULL;
}
//////////////////
int main()
{
int i;
char data[30];
char name[30];
struct client *temp;
struct client *head;
struct item *data1;
for(i=0;i<2;i++)
{
AddClient();
}
printf("Insert name to find:");
scanf("%s",name);
temp = find(&head,name);
data1 = GetItemData();
AddItemToClient(temp,&data1);
display();
}
In this line: "while(ItemCurrent != ItemLast)" - ItemLast is undeclared. Maybe you wanted to write head->lastItem, or better ItemCurrent->next != NULL.
Also, make sure you store the clients you just created to be able to access them: head = AddClient(); instead of simply AddClient();
Related
I don't program in C for a good 2 years, I recently was ordered to make a program that uses a FIFO system, I'm really confused about how I'm going to search for a name using this method.
This is my struct:
struct Node {
int price;
char plat[25];
char name[50];
struct Node *next;
};
typedef struct Node node;
This is where I insert:
void insert(node *LINE) {
line *new = alocar();
new->next = NULL;
if (empty(LINE))
LINE->next = new;
else {
node *tmp = LINE->next;
while (tmp->next != NULL)
tmp = tmp->next;
tmp->next = new;
}
size++;
}
Here is where I'm struggling, I'm just freestyling at this point, trying to figure out what works but nothing seems to be working, I'm trying to search for the name inside the struct using the nameu variable.
void search(node*LINE)
{
if(empty(LINE))
{
printf("Line empty!\n\n");
return;
}
// -------------------test----------------------
char nameu[10];
node *tmp;
node n;
if (scanf("%9s", nameu) != 1) return;
while( tmp != NULL && strcmp(nameu, n.name) == 0)
{
printf("%6s", tmp->name);
tmp = tmp->prox;
}
}
The full code is in Portuguese so I only placed snippets of code that I translated, I'll post here the full code with translations only in the menu so that anyone trying to use it can comprehend what's going on.
https://pastebin.com/ZytqhcWF
Edit: Thanks to Dimitri and the others I found the cause of it not printing, here is the result.
void search(node*LINE)
{
if(empty(LINE))
{
printf("Line empty!\n\n");
return;
}
// -------------------test----------------------
char nameu[10];
node *tmp;
tmp = LINE->next;
node n;
if (scanf("%9s", nameu) != 1) return;
while (tmp)
{
if (!strcmp(nameu, tmp->name))
{
printf("%6s", tmp->name);
break;
}
tmp = tmp->next;
}
So I'm creating a linked list in C and adding some nodes to it that contain information. I have an if else statement where I create the linked list's head and then add nodes to it. The problem is that when I add a new node I seem to lose the old one. Not sure why this is happening or how to fix this.
Edit: I have made some updates to make it a runnable program.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdint.h>
#include<regex.h>
int main(int argc, char argv[]) {
int head=0, i=0;
char tempCourseID[10], tempCourseGrade[10], tempCourseCH[10];
static struct LinkedList {
char *CourseName;
char *CourseGrade;
char *CourseCreditHours;
struct LinkedList *next;
} LinkedList;
static struct LinkedList *first, *savefirst, *headlist;
first = malloc(sizeof ((*first)));
savefirst = first;
headlist = first;
for(i ; i<5; i++){
printf("Enter Course name");
fgets(tempCourseID, sizeof(tempCourseID), stdin);
printf("Enter Course grade");
fgets(tempCourseGrade, sizeof(tempCourseGrade), stdin);
printf("Enter Course credit hours");
fgets(tempCourseCH, sizeof(tempCourseCH), stdin);
//checks to see if linked list head exists
if (head == 0) {
printf("No head has been found.\n");
headlist->CourseName = tempCourseID;
headlist->CourseGrade = tempCourseGrade;
headlist->CourseCreditHours = tempCourseCH;
headlist->next = NULL;
printf("A head has been created\n");
printf("A node has been added\n");
head = 1;
} else {
printf("Ahead already exists\n");
first = malloc(sizeof ((*first)));
first->CourseName = tempCourseID;
first->CourseGrade = tempCourseGrade;
first->CourseCreditHours = tempCourseCH;
first->next = NULL;
savefirst->next = first;
savefirst = first;
printf("A node has been add\n");
head = 1;
}
}
while (headlist != NULL) {
printf(" %s ", headlist->CourseName);
printf(" %s ", headlist->CourseGrade);
printf("%s \n", headlist->CourseCreditHours);
headlist = headlist->next;
}
return 0;
}
You have char tempCourseID[10] and char* CourseName
It is legal to use CourseName = tempCourseID; however tempCourseID is temporary, and so the string will be lost soon. In this case we need to allocate separate memory for CourseName, and then copy the value from tempCourseID
Use instead
CourseName = malloc(strlen(tempCourseID) + 1);//add +1 for null-character
strcpy(CourseName, tempCourseID);
//or
CourseName = strdup(tempCourseID)//shortcut!
There are problem with the linked list. You have too many variables with similar names. A linked list needs only head. You can introduce a temporary variable node for adding new nodes. If you are adding nodes to the tail, then save the last node in the list, lets call it savenode
In this example I removed fgets functions and replaced it with sprintf, that's just to make it easier to run the program and debug. You can put back fgets later.
int main(int argc, char argv[])
{
struct LinkedList
{
char *CourseName;
char *CourseGrade;
char *CourseCreditHours;
struct LinkedList *next;
};
int i;
char tempCourseName[100], tempCourseGrade[100], tempCourseCH[100];
struct LinkedList *head = NULL;
struct LinkedList *node = NULL;
struct LinkedList *savenode = NULL;
for(i = 0; i < 5; i++)
{
sprintf(tempCourseName, "CourseName %d", i);
sprintf(tempCourseGrade, "tempCourseGrade %d", i);
sprintf(tempCourseCH, "tempCourseCH %d", i);
node = malloc(sizeof(*node));
node->CourseName = strdup(tempCourseName);
node->CourseGrade = strdup(tempCourseGrade);
node->CourseCreditHours = strdup(tempCourseCH);
node->next = NULL;
if(head == NULL)
head = node;
//check savenode exists
//this will be the last node (tail) in the existing list
//get it to point to our new node
if(savenode)
savenode->next = node;
//now we have a new tail
savenode = node;
}
//walk through the list
node = head;
while(node)
{
printf("%s, %s, %s\n",
node->CourseName, node->CourseGrade, node->CourseCreditHours);
node = node->next;
}
return 0;
}
I'm writing a function that places new nodes alphabetically into a linked list structure by sorting them by the name field. Here is my program, intended to test that it can successfully insert a new node into an existing structure:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
#define MAX_JOB_LENGTH 100
struct Employee
{
/* Employee details */
char name[MAX_NAME_LENGTH+1]; /* name string */
char sex; /* sex identifier, either ’M’ or ’F’ */
int age; /* age */
char job[MAX_JOB_LENGTH+1]; /* job string */
/* pointers to previous and next employee structures in the linked list
(for if you use a linked list instead of an array) */
struct Employee *prev, *next;
};
void place_alpha(struct Employee *new, struct Employee **root);
int main(){
struct Employee *a;
struct Employee *c;
struct Employee *b;
a = malloc(sizeof(struct Employee));
c = malloc(sizeof(struct Employee));
b = malloc(sizeof(struct Employee));
strcpy(a->name, "A");
a->sex = 'F';
a->age = 42;
strcpy(a->job, "Optician");
a->prev = NULL;
a->next = c;
strcpy(c->name, "C");
c->sex = 'F';
c->age = 22;
strcpy(c->job, "Nurse");
c->prev = a;
c->next = NULL;
strcpy(b->name, "B");
b->sex = 'M';
b->age = 34;
strcpy(b->job, "Rockstar");
b->prev = NULL;
b->next = NULL;
place_alpha(b, &a);
if(a->prev == NULL)
{
printf("a->prev is correct\n");
}else{
printf("a->prev is INCORRECT\n");
}
if(a->next == b)
{
printf("a->next is correct\n");
}else{
printf("a->next is INCORRECT");
}
if(b->prev == a)
{
printf("b->prev is correct\n");
}else{
printf("b->prev is INCORRECT\n");
}
if(b->next == c)
{
printf("b->next is correct\n");
}else{
printf("b->next is INCORRECT\n");
}
if(c->prev == b)
{
printf("c->prev is correct\n");
}else{
printf("c->prev is INCORRECT\n");
}
if(c->next == NULL)
{
printf("c->next is correct\n");
}else{
printf("c->next is INCORRECT\n");
}
}
void place_alpha(struct Employee *new, struct Employee **root) //Places a new node new into the database structure whose root is root.
{
if(*root==NULL) //If there is no database yet.
{
*root = new;
(*root)->prev = NULL;
(*root)->next = NULL;
}
else
{
if(strcmp(new->name, (*root)->name)<=0) // if the new node comes before root alphabetically
{
new->next = *root;
new->prev = (*root)->prev;
if((*root)->prev != NULL)
{
(*root)->prev->next = new;
}
(*root)->prev = new;
*root = new;
return;
}
else if((*root)->next == NULL) // If the next node is NULL (we've reached the end of the database so new has to go here.
{
new->prev = *root;
new->next = NULL;
(*root)->next = new;
return;
}
else if(strcmp(new->name, (*root)->name)>0) // If the new node comes after root alphabetically
{
place_alpha(new, &(*root)->next);
return;
}
}
}
Sadly, the program is unsuccessful, as showcased by the output:
a->prev is correct
a->next is correct
b->prev is INCORRECT
b->next is correct
c->prev is INCORRECT
c->next is correct
Program ended with exit code: 0
I can't figure out why, as I've clearly set b->next to c and c->prev to b.
This was tricky: there is a subtile bug in your place_alpha() function: you update *root even if it is not the root node of the list. This causes the pointer b to be updated erroneously. place_alpha() should only be called with a pointer to the actual root node.
I modified your code to make it more readable and reliable:
I wrote a function to create a new node
I protected the string copies from overflow using calloc() and strncat(). Read about these functions in the manual.
I use place_alpha() to insert all 3 nodes into the list in the same order you do.
I use newp instead of new to avoid C++ keywords in C code.
Note that place_alpha() must be called with a pointer to the head pointer of the list, if you pass a pointer to an intermediary node, chaining back along the prev links would locate the first node, but if the new employee should be inserted at the head of the list, you would not have the address of the root node to update in the caller's scope. This is the reason many programmers prefer to use a specific structure for the list head.
Here is the updated code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 100
#define MAX_JOB_LENGTH 100
struct Employee {
/* Employee details */
char name[MAX_NAME_LENGTH + 1]; /* name string */
char sex; /* sex identifier, either 'M' or 'F' */
int age; /* age */
char job[MAX_JOB_LENGTH + 1]; /* job string */
/* pointers to previous and next employee structures in the linked list
(for if you use a linked list instead of an array) */
struct Employee *prev, *next;
};
void place_alpha(struct Employee *new, struct Employee **root);
struct Employee *new_employee(const char *name, char sex, int age, const char *job) {
struct Employee *newp = calloc(1, sizeof(*newp));
if (!newp) {
fprintf(stderr, "cannot allocate employee\n");
exit(1);
}
strncat(newp->name, name, MAX_NAME_LENGTH);
newp->sex = sex;
newp->age = age;
strncat(newp->job, job, MAX_JOB_LENGTH);
newp->next = newp->prev = NULL;
return newp;
}
int main(void) {
struct Employee *list = NULL;
struct Employee *a = new_employee("A", 'F', 42, "Optician");
struct Employee *b = new_employee("B", 'M', 34, "Rockstar");
struct Employee *c = new_employee("C", 'F', 22, "Nurse");
place_alpha(a, &list);
place_alpha(c, &list);
place_alpha(b, &list);
if (a->prev == NULL) {
printf("a->prev is correct\n");
} else {
printf("a->prev is INCORRECT\n");
}
if (a->next == b) {
printf("a->next is correct\n");
} else {
printf("a->next is INCORRECT");
}
if (b->prev == a) {
printf("b->prev is correct\n");
} else {
printf("b->prev is INCORRECT\n");
}
if (b->next == c) {
printf("b->next is correct\n");
} else {
printf("b->next is INCORRECT\n");
}
if (c->prev == b) {
printf("c->prev is correct\n");
} else {
printf("c->prev is INCORRECT\n");
}
if (c->next == NULL) {
printf("c->next is correct\n");
} else {
printf("c->next is INCORRECT\n");
}
return 0;
}
void place_alpha(struct Employee *newp, struct Employee **root) {
// Insert a new node newp into the database structure whose root is root.
struct Employee *ep;
if (*root == NULL) { // if there is no database yet.
newp->next = newp->prev = NULL;
*root = newp;
return;
}
if ((*root)->prev) {
// invalid call, should only pass the root node address
fprintf(stderr, "invalid call: place_alpha must take a pointer to the root node\n");
return;
}
if (strcmp(newp->name, (*root)->name) <= 0) {
// if the new node comes before root alphabetically
newp->next = *root;
newp->prev = NULL;
newp->next->prev = newp;
*root = newp;
return;
}
for (ep = *root;; ep = ep->next) {
if (ep->next == NULL) {
// If the next node is NULL, we've reached the end of the list
// so newp has to go here.
newp->prev = ep;
newp->next = NULL;
newp->prev->next = newp;
return;
}
if (strcmp(newp->name, ep->next->name) <= 0) {
// The new node comes between ep and ep->next alphabetically
newp->prev = ep;
newp->next = ep->next;
newp->prev->next = newp->next->prev = newp;
return;
}
}
}
EDIT: place_alpha was a bit redundant, so I cleaned it and got a much simpler version:
void place_alpha(struct Employee *newp, struct Employee **root) {
//Places a new node newp into the database structure whose root is root.
struct Employee **link = root;
struct Employee *last = NULL;
while (*link && strcmp(newp->name, (*link)->name) > 0) {
last = *link;
link = &last->next;
}
newp->prev = last;
newp->next = *link;
if (newp->next) {
newp->next->prev = newp;
}
*link = newp;
}
I'm doing a program to save a list of contacts in a file whit structs. I've tried a lot of things but when I try go read the file to the program, it doesn't read anything.
This is my program without opening files and saving to files:
#include <stdio.h>
#include <stdlib.h>
struct agenda {
int idContacte;
char name[50];
struct agenda *nextContacte;
};
struct agenda *pAgenda;
struct agenda *pFirst = NULL;
struct agenda *pIndex;
void insert();
void show();
int main()
{
//Menu
int opc;
while(1){
printf("1.Insert Contact.\n");
printf("2.Show Contacts.\n");
printf("3.Exit\n");
scanf("%d", &opc);
switch(opc){
case 1:
insert();
break;
case 2:
show();
break;
case 3:
return 0;
}
}
}
void insert(){
pAgenda = (struct agenda *)malloc(sizeof(struct agenda));
printf("Insert ID: ");
scanf("%d", &pAgenda->idContacte);
printf("Insert the name: ");
scanf("%s", pAgenda->name);
printf("\n");
if (pFirst==NULL || pAgenda->idContacte < pFirst->idContacte)
{
pAgenda->nextContacte=pFirst;
pFirst=pAgenda;
}
else if (pAgenda->idContacte > pFirst->idContacte){
pIndex=pFirst;
while(pIndex->nextContacte && pIndex->nextContacte->idContacte < pAgenda->idContacte)
{
pIndex = pIndex->nextContacte;
}
pAgenda->nextContacte = pIndex->nextContacte;
pIndex->nextContacte = pAgenda;
}
}
void show(){
pIndex = pFirst;
while(pIndex && pIndex->idContacte <= 100) {
printf("\nID: %d", pIndex->idContacte);
printf("\nNAME: %s", pIndex->name);
printf("\n\n");
pIndex = pIndex->nextContacte;
}
}
Can you help me how can I get contact at start of the program from a file, and then when insert a contact, rewrite the file and insert all the contacts again in the file?
When you end your program you should do the following
int save_list(struct agenda *head) {
FILE *save = fopen("file.name", "wb");
if(!save) return -1;
while(head) {
fwrite(head, sizeof *head - sizeof head, 1, save);
head = head->nextContacte;
}
fclose(save);
/* Somebody would free list memory after this function execution */
return 0;
}
At the start of your program you should do the following
struct agenda *restore_list() {
FILE *restore= fopen("file.name", "rb");
struct agenda *head = NULL;
struct agenda *cur = head;
struct agenda temp;
if(!restore) return head;
while( fwrite(&temp, sizeof temp - sizeof head, 1, save) == 1) {
struct agenda *node = malloc( sizeof(struct agenda) );
if(NULL == node) {
/* Handle out of memory error here, free list */
return NULL;
}
*node = temp;
node->nextContacte = NULL;
if(head) {
cur->nextContacte = node;
cur = node;
} else {
/* First node */
head = cur = node;
}
}
fclose(restore);
return head;
}
I have created the data needed for my node(car).
struct data {
char carReg[10];
char make[20], model[20], colour[20];
int numPrevOwners;
bool reserved;
float reserveAmount;
};
I've also created the template for the node and the declared the global variables.
struct node {
struct data *element;
struct node *next;
};
struct node *front = NULL;
struct node *last = NULL;
In my viewSpecific() method I want the user to enter in a unique carReg and it will then find the node in which this is stored in and display it.
This is what I have so far:
void viewSpecific() {
char result[10];
printf("Please enter the registration of the car yiew wish to view.");
scanf("%s", &result);
struct node *current, *previous;
bool notFound = true;
printf("\n");
if (isEmpty())
printf("Error - there are no nodes in the list\n");
else {
I'm not quite sure what to do after this.
Check if the carReg entered by the user is the same as the current node's carReg.
If it isn't advance to the next node.
If you reach the end of the list, it's because the carReg was not found.
/* basically, something like */
current = front;
while (current != NULL) {
if (strcmp(current->element->carReg, userCarReg) == 0) /* found */ break;
current = current->next;
}
if (current == NULL) {
printf("carReg not found\n");
} else {
printf("carReg: %s\n", current->element->carReg);
printf("make: %s\n", current->element->make);
printf("previous owners: %d\n", current->element->numPrevOwners);
}