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.
Related
i have been given a structure and a pointer to an array.
each index of the array is a letter of the alphabet. i need to receive a name, last name and phone number, and allocate memory to a struct (phonebook).
then, each struct needs to be accessed from the array using the last name's first letter.
if the function is called again i need to use linked list to add another contact.
i dont know how to allocate memory for a certain index of an array. when i try to do
phonebook[letter] = (Contact**)malloc(sizeof(Contact));
i keep having de reference warnings, and i cant seem to figure out how to point the address of phonebook[letter] to a structure properly.
this is what i have tried:
typedef struct Contact {
char* firstName;
char* lastName;
char* phoneNum;
struct Contact* next;
} Contact;
int main(){
Contact* phonebook[26];
addNewContact(phonebook)
}
int addNewContact(Contact** phonebook) {
char newFirstName[SIZE], newLastName[SIZE], newPhoneNum[SIZE];
int letter;
printf("Enter a contact details \
(<first name> <last name> <phone number>):\n");
scanf("%s%s%s", newFirstName, newLastName, newPhoneNum);
//get number of the letter in the alphabet
letter = newLastName[0] - 'A';
//allocate memory to pointer
Contact *current;
phonebook = (Contact**)malloc(sizeof(Contact));
if (phonebook == NULL) {
printf("The addition of the contact has failed!");
//free
exit(1);
}
current = phonebook[letter];
//check if details are being used
do {
//if the name already exists
if (phonebook[letter]->firstName == newFirstName \
&& phonebook[letter]->lastName == newLastName) {
printf("The addition of the contact has failed, \
since the contact %s %s already exists!\n", newFirstName, newLastName);
//free
return 0;
}
//if the phone number already exists
if (phonebook[letter]->phoneNum == newPhoneNum) {
printf("The addition of the contact has failed, \
since the phone number %s already exists!", newPhoneNum);
//free
return 0;
}
current = current->next;
} while (current != NULL);
//assigning
phonebook[letter]->firstName = newFirstName;
phonebook[letter]->lastName = newLastName;
phonebook[letter]->phoneNum = newPhoneNum;
return 0;
}
in addition, i havent figured out the linked list part at all, i managed before to enter the details to the structure (though im not sure if i even pointed the struct to the right place) but i dont know how to iterate after the first addition of the name. if i intialize current->next to be NULL for the first time, it will also happen the next time i call the function.
currently the code stops due do access violation but it seemed that after the first name i had error with reading the inputs that only occured after the second time.
You are actually pretty close to making it work. Probably the main problem with this code is that it has only pointers to the data, doesn't have space to store the data. You are pointing to phonebook[letter]->lastName = newLastName, a local variable that is destroyed when the function returns. This will make your strings a dangling pointer; when you try to access this data, undefined things happen. Probably the easiest way to fix that is to make a char array of maximum length instead of the pointers. You don't need to typedef in most cases, and sometimes it's confusing. I would recommend that you take the typedef out and just have,
#define SIZE 128
struct Contact {
char firstName[SIZE];
char lastName[SIZE];
char phoneNum[SIZE];
struct Contact* next;
};
Double-pointer Contact** phonebook is valid, but a recipe for confusion. Instead of naked pointers, use struct to encapsulate a phone book, using a list of struct Contact.
struct Phonebook {
struct Contact *letter[26];
};
printf is defined in stdio.h. strcmp is defined in string.h. malloc and exit are stdlib.h.
See What's the correct declaration of main()? C doesn't scan ahead; switch the order of the functions or have a prototype above.
Perhaps in the future you will read from a file? It's easier do if you read the input separately from the interface. Maybe split it up into a separate function. This should be static, since it doesn't need to be published to other translation units.
static struct Contact *inputContact(void)
To allocate memory, current = malloc(sizeof *current);. Did you have a typo using phonebook? If you allocate it first, you can read directly into the allocated memory and not do any copying. Make sure you limit the size. (scanf is not meant for this.)
#define STR(n) STR2(n)
#define STR2(n) #n
if(scanf("%" STR(SIZE) "s%" STR(SIZE) "s%" STR(SIZE) "s",
current->firstName, current->lastName, current->phoneNum) != 3)
exit(EXIT_FAILURE);
Then,
static int addNewContact(struct Phonebook* phonebook, struct Contact *contact)
do-while checks that the current is valid after you use it; you want while.
//get number of the letter in the alphabet
int letter = contact->lastName[0] - 'A'; // might want to check that
struct Contact *current = phonebook->letter[letter];
//check if details are being used
while (current != NULL) {
In C, equality means they are the same memory location, not in general the same text. You probably want a library function strcmp. (But are you sure your logic is correct in that it prevents the same number in appearing with the same first letter of the last name?)
if (!strcmp(current->phoneNum, contact->phoneNum))
Assigning will just overwrite the one letter that is there. You probably meant for it to be appended to the list.
contact->next = phonebook->letter[letter];
phonebook->letter[letter] = contact;
return 1;
And lastly, be sure to initialize any data that is of automatic duration.
struct Phonebook phonebook = {0}; /* Initialize null lists. */
addNewContact(&phonebook, inputContact());
--edit
This can be seen as creating a static-26-bucket separately-chained hash-table, with your hash function being hash(struct Contact *entry) { return entry->lastName[0] - 'A'; }.
I think you are doing this, which also makes sense. Make sure that you allocate Contact and 3 text fields, for a total of 4 mallocs per entry. If you read the data into a temporary buffer, you can use strcpy to transfer it to a longer-lived string that you've just allocated.
Hi guys I'm learning C and there are some issues that I can't solve.
first of all, this are my data structure:
struct user_node {
void *name;
struct user_node *next;
struct msg_node *msgnext;
};
struct msg_node {
void *sender;
void *receiver;
void *title;
void *content;
struct msg_node *msgnext;
};
struct user_node *user_database = NULL;
The idea is that a user may have one or more messages.
Well I can create and delete users but I'm having problem storing messages, for example here:
The purpose of this function is to put temp as a message inside my data structure for a given user that we find in the message itself. (temp is already msg_node with data which I take from another function)
void sendMsg(struct msg_node* temp) {
//if list is empty
if (user_database == NULL) {
printf("There aren't users on the system.\n\n");
return;
}
struct user_node** ptr = &user_database;
while (*ptr) {
if (strncmp((*ptr)->name, (temp)->receiver, strlen(temp-
>receiver)) == 0) {
temp->msgnext = &user_database->msgnext;
user_database->msgnext = temp;
return;
}
ptr = &(*ptr)->next;
}
printf("User not found on the system\n\n");
return;
}
I know that the code is wrong but I been messing arround with this since yesterday and I can't figure it , may someone help me?
Thanks in advance
You can insert a node at the front of a linked list by sett ing the new node's next pointer to the list's head and then setting the lis's head to the new node. This works even for an empty list, when the list's head is NULL.
You've got this almost right, but the List's head is the one associated with the current user, not with the user list's head, i.e. the first user in the database.
The following code should do what you want:
int sendMsg(struct msg_node *msg)
{
struct user_node *user = user_database;
if (user == NULL) {
printf("There aren't users on the system.\n");
return -1;
}
while (user) {
if (strcmp(ptr->name, msg->receiver) == 0) {
msg->msgnext = user->msgnext;
user->msgnext = msg;
return 0;
}
user = user->next;
}
printf("User '%s' not found on the system.\n", msg->receiver);
return -1;
}
Notes:
I've renamed the pointers from the rather nondescript temp and ptr to the more descriptive msg and user.
I've made the function return a success code: 0 for success and −1 for failure.
strncmp will compare only a certain number of characters. I've changed this to strcmp, so that the users Paul and Pauline are considered different.
There's no need to make the traversing pointer a pointer to pointer to node. That technique is useful, but only when you want to insert or delete nodes. Inserting at the front is a special case where you won't need it. (And you insert a message, not a user, so if you wanted to insert the message somewhere else than at the front, you could iterate through the sub-list with a pointer to pointer to message node.)
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 only allowed to use following headers
#include <stdio.h>
#include <stdlib.h>
and I defined my struct student as following:
struct dict
{
char* word;
struct dict* link;
};
There are many functions, but only one function that I have problem right now.
This function inserts a struct dict with certain name at the end of the link.
struct student *Linsert(struct dict *list, char *name)
{
struct student *pnew;
struct student *pn;
int exist = 1;
pnew = (struct dict *)malloc(sizeof(struct dict));
pnew -> next = NULL;
pnew -> name = name;
if (list != NULL)
{
for (pn = list; pn -> next != NULL; pn = pn -> next) ;
pn -> next = pnew;
}
else
list = pnew;
return list;
}
Using the following function,
//print all the values in the list
void printList(struct dict* list);
I did this:
int main(void)
{
struct dict *list = NULL;
char *name;
while (1) {
scanf("%s", name);
if (name == 'Q')
break;
list = Linsert(list, name);
printList(list);
}
return 0;
}
Lets say for input, I typed three
apple banana and orange, my result shows three of my last input.
What is the issue here?
I see two problems with your code:
You need to pass scanf a char array of size sufficient to store the input string, not simply a char pointer.
You need to copy strings passed into Linsert (use strdup).
Your main snippet alone has a whole bunch of problems:
name is an uninitialized pointer; it's pointing to some unknown location in memory that you haven't allocated and are allowed to use, therefore causing undefined behaviour. Perhaps you want char name[20] to allocate an array of 20 chars on the stack, and have scanf store the input in this buffer.
You're comparing a char* (a pointer to the start of a string) to a single char 'Q' - you're comparing a pointer and an integer value as your compiler warnings will tell you. You're not comparing the contents of the string for the value 'Q', you're comparing the memory address of name and the integer value for 'Q'. If you want to compare the string name with the string "Q", use strcmp and check for a return value of 0.
You also want to be making a copy of the variable passed to Linsert otherwise, as you've noticed, you'll be passing a pointer to the same location in memory every time, and a change to this block of memory will change each of your items.
If you turn your compiler warnings up you'll get even more warnings.
You are not allocating any memory for the name, so scanf is writing to some random location, and overwriting that every time through the loop.
One issue is that you've not allocated storage for the word member to point to. You have also not allocated space for name to point at. That is a principle cause of trouble.
You need to allocate space for name; the easiest way is:
char name[128];
You need to allocate space to store the word, and you need to copy the contents of name into the word so that when the next line overwrites name, it does not destroy the saved word.
Adapting your code, you might use:
struct student *Linsert(struct dict *list, char *name)
{
struct student *pnew;
struct student *pn;
pnew = (struct dict *)malloc(sizeof(struct dict));
if (pnew == 0)
...error...
pnew->next = NULL;
pnew->word = malloc(strlen(name) + 1);
if (pnew->word == 0)
...error...
strcpy(pnew->word, name);
if (list != NULL)
{
for (pn = list; pn->next != NULL; pn = pn->next)
;
pn->next = pnew;
}
else
list = pnew;
return list;
}
Do not omit the error checks on memory allocation - painful though it be. It will bite you when you forget.
Stylistically, do not use spaces around either -> or .; they are operators that bind very tightly, and they should not be spaced out like other binary operators.
There's a convenient function, strdup(), the duplicates a string, but it is not standard C (it is standard POSIX).
Since name is a char pointer, your assignment to the field of each dict struct will use the latest value it points to.
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.