I think that I am having some issues with how linked lists work, please bear in mind that I am not an expert with C and that I have not worked with linked lists before.
I'm trying to take a text file with a list of things and store it in a linked list. I have the following code right now:
typedef struct linked_list {
struct linked_list *next_ptr;
char name;
float price1;
float price2;
}linked_list;
struct linked_list *first_ptr;
char name_temp;
int writeList(void) {
// read input files
FILE *sh_list;
sh_list=fopen("case1/shoppingList.dat", "rw");
if (sh_list == NULL) {
perror("Cannot open file, you seem to have something mixed up...");
exit(8);
}
struct linked_list *current_ptr;
current_ptr = first_ptr;
while ((fscanf(sh_list, "%s", &name_temp)) !=EOF) {
next_ptr = malloc(sizeof(linked_list));
strcpy(name, name_temp);
//move to next node and complete the same task
}
};
I stopped at the //move... because I am struggling to get the code correct - my IDE is giving me errors. Similarly, I can't get it to read the variable "name" which I need to do in order to copy the string to the node.
You are getting next_ptr as undeclared because you have not delcared it.
Your code should look something like this ...
linked_list *next_ptr;
char name_temp[MAX_SIZE];
while ((fscanf(sh_list, "%s", &name_temp)) !=EOF) {
next_ptr = malloc(sizeof(linked_list));
strcpy(next_ptr->name, name_temp);
next_ptr->next_ptr = first_ptr;
first_ptr = next_ptr;
}
You should also make the declaration of name in linked list to be:
char name[MAX_SIZE];
In your fscanf statement you specify that you're inputting a string, %s, but name_temp has type char. You're going to have to change it to a char array, like so:
char name_temp[100];
You'll have to make the array sufficiently big for your purposes. You'll also have to change the type of name:
char name[100];
The error you are getting is because name and next_ptr are part of the struct linked_list but you you have to create an instantiation of linked_list to access name. In your case, you have the current_ptr so you should change it to:
current_ptr->next_ptr = malloc(sizeof(linked_list));
strcpy(current_ptr->name, name_tmp);
it should be strcpy(current_ptr->name, name_temp);
You are trying to refer to the name variable in the structure, which needs to be accessed through the current_ptr.
so similarly it should be current_ptr->next_ptr = malloc(sizeof(linked_list));
To access variable in a structure, you need to use the . operator. When you are using a pointer to a structure, then you access its variables using the ->operator.
Related
#include<string.h>
#include<stdio.h>
struct Friend{
char name[50];
char surname[50];
char gender;
char date[50];
struct Friend * next;
};
struct Friend* initialize(char *);
int main(){
char name[100];
printf("ENter the name of the file\n")
gets(name);
struct Friend * head;
head=initialze(name);
}
struct Friend * initialize(char *name){
FILE * ffile;
ffile=fopen(name,"r");
if(ffile==NULL)
exit(1);
}
Here are my Function initizaliations in C. I need to take and open a file (example of how the file looks is below), and make a LINKED LIST which holds the NAME, SURNAME, GENDER AND DATE OF BIRTH of each person, and return the (HEAD pointer) start address of the linked list. I have finished the task by taking one character at a time, by having 3 nested while loops. But as you might have guessed this is a very inefficient solution.
The name of the file doesn't matter since I am prompting the used to write it. But here is how the FILE LOOKS LIKE
John;Lenny;M;13/01/1978;
Josh;Bush;M;15/05/1989;
Anjelica;Victoria;F;20/10/1990;
So as you see we have a semicolon(;) after each element
I would approach this a bit different.
you can either read the entire file to a buffer or read it and store after every time you encounter "\n"
Then you have to have a method that creates a node of the desired structure and fill in the data from the current line you've just read.
For example:
void create(Friend* Head)
{
struct Friend *new_node = malloc(sizeof(Friend));
new_node->whatever = whatever;
Head->Next = new_node;
}
I'm having some trouble accessing the checkups struct that is contained within dog. Since dog is contained within contained I assumed that I would just point to the checkups from dog from the container but that seems to be causing an error when trying to add a checkup date or replace one.
// used to create a linked list of containers, each contaning a "dog"
struct container {
struct dog *dog;
struct container *next;
} *list = NULL;
// used to hold dog information and linked list of "checkups"
struct dog {
char name[30];
char breed[30];
struct checkup *checkups;
};
// used to create a linked list of checkups containing "dates"
struct checkup {
char date[30];
struct checkup *next;
};
Here is the code where I try to add a new date to the checkups but when it tried to add it on my program crashes. Any direction on why this would be occurring would be greatly appreciated.
void add_checkup(char* name, char* date)
{
struct container *tempList = list;
struct checkup *tempCheck = (struct checkup *) malloc(sizeof(struct checkup));
while (tempList != NULL) {
if (strcmp(tempList->dog->name, name) == 0) {
strcpy(tempCheck->date, date);
strcpy(tempList->dog->checkups, tempCheck);
}
tempList->next;
}
}
Why are you using strcpy() to set the value of a struct checkup *? That attempts to copy the data pointed to by the source pointer to the array assumed to be pointed to by destination pointer, when in fact I see no particular reason to suppose that the destination pointer is even valid. Certainly there's no reason to suppose that the source data has the form of a null-terminated array of char, so your original code is badly wrong here.
Simple assignment is more likely to be correct:
tempList->dog->checkups = tempCheck;
Note, however, that that presents a serious risk of memory leakage because the previous value of tempList->dog->checkups is lost. Note also that it doesn't match the behavior implied by the add_ part of the function name -- it's more like set_. If you want to be able to maintain more than one checkup per dog then you would need to do more work.
So I'm trying to understand how a linked list works with storing string type pieces of data. As far as I know, a linked list uses a data structure to store data in a somewhat fashionable way so you can easily enter new pieces of data inside, remove them, and rearrange them as you please. My problem is, I need to take a string in from the user, assign it a spot in the linked list and move on to the next node in the list and do the same thing again. At this point however, I'm simply trying to take one string from the user, store it in the new_node value, (or (*new_node).value for those of you thinking in terms of pointers and not linked lists) and print it out. The main just asks the user for a string input, the add_to_list func takes the input and adds it to the beginning of the linked list, and the print func simply prints what ever is in the linked list. Where the problem lies in my understanding (at least what I think is the problem) is the point at which I assign the data structure the value of the input, new_node->value=*n should just make the value contain the input string as it would just giving another array the value of whatever the pointer *n is containing, unfortunately that's not the case and I'm not sure why that is. Here's the code for simplicity's sake.
EDIT: Thanks everyone for the responses and the explanation behind why strcpy is necessary when dealing with assigning the value of an array of characters to another array ie: strings!
#include <stdio.h>
#include <stdlib.h>
#define LARGE 10
struct node *add_to_list(struct node *list, char *n);
struct node{
char value[LARGE+1];
struct node *next;
};
struct node *first = NULL;
void print(void);
int main(void) {
char job[LARGE],*p;
printf("Please enter printing jobs\n");
scanf ("%s", job);
p=&job[0];
first = add_to_list(first, p);
print();
return 0;
}
struct node *add_to_list(struct node *list, char *n)
{
struct node *new_node;
new_node = malloc(sizeof(struct node));
if (new_node == NULL) {
printf("Error: malloc failed in add_to_list\n");
exit(EXIT_FAILURE);
}
new_node->value = *n;
new_node->next = list;
return new_node;
}
void print(void){
struct node *new_node;
for(new_node=first;new_node!= NULL; new_node=new_node->next){
printf("%s\n",new_node->value);
}
}
Use strcpy instead of assigning a char to an array, which doesn't compile. Arrays are not lvalues, and cannot be assigned to without subscripting, so any assignment with an array name by itself on the left will not compile. Change
new_node->value = *n;
to
#include <string.h>
...
strcpy(new_node->value, n);
you cannot assign string as normal integer assignment.
whenever you want to copy a array you have to use library functions like memcpy or strcpy. In your case its array of characters i.e string you have to use strcpy.
usage char *strcpy(char *dest, const char *src);
so in your code it has to be like strcpy(new_node->value,n); instead of new_node->value=*n;
Reason for using strcpy is mentioned in the link below
why strcpy function
I am trying to add users to a linked list. I have two structs and a method to add called add_friend that sets up the addition of the node. The program does not ask for user input but passes the info through parameters in the add_friend method: In addition to adding the node (user) to the list I have to check if user already exists. I am getting an error when I try to compare string to see if the user exists. Any help? Unfortunately C is my weakest programming language, Im having a hard time understanding the pointers
struct UserAccountNode {
struct UserAccount* content;
char circle;
struct UserAccountNode* next;
} *head = NULL;
struct UserAccount {
char username[255];
char lastnm [256];
char firstnm[256];
char password[256];
char gender;
int phone;
struct Post* post_list;
struct UserAccountNode* friend_list;
};
int add_friend(UserAccount* user, char Circle, UserAccount* Friend) {
struct UserAccountNode* friend_list;
friend_list = (struct UserAccountNode* ) malloc (sizeof(struct UserAccountNode));
while (friend_list != NULL)
if (stricmp(Circle, head->friend_list) == 0) {
friend_list -> next = head;
head = friend_list;
} else {
printf("%d, User Already Exists", Friend);
}
return 0;
}
The code does not compare strings. It compares char - Circle - with UserAccountNode* friend_list. But stricmp requires both arguments to be const char *. You have to do a loop through all items in friend_list and compare every username with a given one.
Another issue: you allocate memory for UserAccountNode but do not allocate memory for its internal field UserAccount* content. It may crash the application when you try to read the data.
type of Circle is char not char*,
type of head->friend_list is UserAccountNode*.
So, you try to compare non-string objects as strings here:
if (stricmp(Circle, head->friend_list) == 0)
I think your program can't be compiled.
I'm trying to read a text file and store each line in a node of a link list of type void*.
Here's the header file of the list.
#ifndef LINKEDL
#define LINKEDL
struct node_s {
void *data;
struct node_s *next;
};
struct node_s *node_create(void*);
struct node_s *list_insert_after(struct node_s*, void*);
struct node_s *list_insert_beginning(struct node_s*, void*);
int list_remove(struct node_s*, struct node_s*);
int list_foreach(struct node_s*, int(*)(void*));
int printstring(void *s);
#endif
All the linked list functions have been thoroughly tested, so I guess the problem is with how I use it. What I want to achieve is the have one line in each node and what I have now is last line in every node. I guess it has something to do with the char pointers but have already spent two hours on that without a spectacular breakthrough, so maybe someone could help?
Also the list I use is a modified list as seen here.
if (file == NULL)
{
perror("Error opening file");
}
else
{
char mystring[SIZE];
char temp[SIZE];
list = node_create((void*)mystring);
current = list;
while (fgets(mystring, SIZE, file) != NULL)
{
strcpy(temp, mystring);
printf("%d\t%s",counter++,temp);
current=list_insert_after(current, (void*)temp);
}
fclose(file);
}
UPDATE:
Thank you All.
You are creating each node using a single array, temp. Every time you read a line, you replace the contents of temp with the last line you read. That's why you have the last line on every node (you are referring to the same memory location in every node).
What you should do, is to allocate memory dynamically for each line using malloc. Thus, you should pass the pointer to the newly allocated memory to list_insert_after instead of passing temp.
Remove the line:
strcpy(temp, mystring);
And change the line:
current=list_insert_after(current, (void*)temp);
To
current=list_insert_after(current, strdup(mystring));
Think about this - you have a temporary char array on stack which is getting destroyed upon exiting out of the scope (of else block) and you are inserting pointer to that array into a list. So after all, the list will end up having pointers to destroyed/incorrect data. The behavior is undefined.
You have to allocate memory dynamically for each string (and not forget to clean it up). The strdup can be useful here. Just don't forget to call free when removing/dropping string from that list.