I'm trying to insert a hard coded string into a char array value in a struct using only C, so I used memcpy, following the example in another post. But for some reason, I keep getting what looks like an address as output, I'm not sure why.
my console prints out: [ (2,7532592) (1,7524424) ] and other long numbers like that every time. I've checked so many examples on how to copy a sequence of characters into a c string, and it seems like this one was exactly the same. I might just be having trouble understanding pointers. Im not sure why it's spitting out the address value. Can anyone point out what I'm doing wrong? I apologize for any lack of knowledge on my part. My shortened down code is below:
struct node
{
int key;
char month[20];
struct node *next;
};
struct node *head = NULL;
struct node *current = NULL;
//display the list
void printList()
{
struct node *ptr = head;
printf("\n[ ");
//start from the beginning
while(ptr != NULL)
{
printf("(%d,%d) ",ptr->key,ptr->month);
ptr = ptr->next;
}
printf(" ]");
}
//insert link at the first location
void insertFirst(int key, char * month)
{
//create a link
struct node *link = (struct node*) malloc(sizeof(struct node));
link->key = key;
memcpy(link->month, month, 20);
link->month[19] = 0; // ensure termination
//point it to old first node
link->next = head;
//point first to new first node
head = link;
}
int main() {
insertFirst(1,"Jan");
insertFirst(2,"March");
printf("Original List: ");
//print list
printList();
}
You are printing the pointer ptr->month, not the actual string.
Try: printf("(%d,%s) ",ptr->key,ptr->month); (%s instead of %d).
Try
printf("(%d,%s) ",ptr->key,ptr->month);
instead for the "curious output" problem.
Related
I'm still learning how to program in C and I've stumbled across a problem.
Using a char array, I need to create a linked list, but I don't know how to do it. I've searched online, but it seems very confusing. The char array is something like this char arr[3][2]={"1A","2B","3C"};
Have a look at this code below. It uses a Node struct and you can see how we iterate through the list, creating nodes, allocating memory, and adding them to the linked list. It is based of this GeeksForGeeks article, with a few modifications. I reccommend you compare the two to help understand what is going on.
#include <stdio.h>
#include <stdlib.h>
struct Node {
char value[2];
struct Node * next;
};
int main() {
char arr[3][2] = {"1A","2B","3C"};
struct Node * linked_list = NULL;
// Iterate over array
// We calculate the size of the array by using sizeof the whole array and dividing it by the sizeof the first element of the array
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
// We create a new node
struct Node * new_node = (struct Node *)malloc(sizeof(struct Node));
// Assign the value, you can't assign arrays so we do each char individually or use strcpy
new_node->value[0] = arr[i][0];
new_node->value[1] = arr[i][1];
// Set next node to NULL
new_node->next = NULL;
if (linked_list == NULL) {
// If the linked_list is empty, this is the first node, add it to the front
linked_list = new_node;
continue;
}
// Find the last node (where next is NULL) and set the next value to the newly created node
struct Node * last = linked_list;
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// Iterate through our linked list printing each value
struct Node * pointer = linked_list;
while (pointer != NULL) {
printf("%s\n", pointer->value);
pointer = pointer->next;
}
return 0;
}
There are a few things the above code is missing, like checking if each malloc is successful, and freeing the allocated memory afterwards. This is only meant to give you something to build off of!
I have a text file consists of multiple journal entries which I can read it and store it into a struct called Journal. But my problem now is that I dont know how to add it into the linked list 1 by 1.
this is my insert method
void insertStart (LinkedList *list, Journal *JEntry) {
Node *newNode;
newNode = (Node*)malloc(sizeof(Node));
newNode->data.day = JEntry->day;
newNode->data.month = JEntry->month;
newNode->data.year = JEntry->year;
strcpy(newNode->data.entry, JEntry->entry);
if (list == NULL) {
list->head = newNode;
}
else {
newNode->next = list->head;
list->head = newNode;
}
printf("Inserted Entry = %d/%d/%d :%s\n", newNode->data.day, newNode->data.month, newNode->data.year, newNode->data.entry);
}
and this is
fscanf(fo, "%d", &numEntry);
journal = (Journal *)malloc(numEntry * sizeof(Journal));
for (i=0; i<numEntry;i++) {
fscanf(fo, "%d/%d/%d\n", &journal[i].day, &journal[i].month, &journal[i].year);
fgets(journal[i].entry, SIZE, fo);
}
insertStart(list, journal);
index = atoi(argv[1]);
printf("%d-%02d-%02d: %s\n", journal[index].year, journal[index].month, journal[index].day, journal[index].entry);
free(journal);
fclose(fo);
}
this is my struct
#define SIZE 102
typedef struct {
int day;
int month;
int year;
char entry[SIZE];
} Journal;
typedef struct Node {
Journal data;
struct Node *next;
} Node;
typedef struct {
Node *head;
} LinkedList;
if I put the insertStart in the for loop, yes it entered 4 times, but its the same result over and over again.
if i put it to where it is shown above, it will only run 1 time.
my question now is how can i store the rest of the entry into the linked list? thank you
this is the content of the text file
4
12/04/2010
Interview went well I think, though was told to wear shoes.
18/04/2010
Doc advised me to concentrate on something... I forget.
03/05/2010
Was asked today if I was an art exhibit.
19/05/2010
Apparently mudcakes not made of mud, or angry wasps.
the first number 4 is the number of entries in case anyone's wondering.
Have you considered just storing JEntry in the node instead of making a copy?
typedef struct
{
Journal* data;
struct Node* next'
}
Node;
That way this can be simplified
void insertStart (LinkedList *list, Journal *JEntry)
{
Node* newNode = malloc(sizeof(Node));
newNode->data = JEntry;
newNode->next = NULL;
instead of having a
struct { Node* head } LinkedList
just declare it
Node* list;
if you want to change the pointer pass it in as a double pointer
void insertStart( Node** list, Journal* JEntry) /* insertStart(&list,journal + i) */
If list already has an entry, make sure your new node points to that
if (*list != NULL)
{
newNode->next = *list;
}
Now make your list point to the new node
*list = newNode;
When printing use -> for JEntry as well.
printf("Inserted Entry = %d/%d/%d :%s\n", newNode->data->day, newNode->data->month, newNode->data->year, newNode->data->entry);
First, you need to set list->head to NULL when you create it (or use calloc instead of malloc).
However, your problem comes from the line insertStart(list,journal);. Although journal is the pointer to the beginning of an array of Journal objects, insertStart doesn't know that. It dereferences the pointer and only adds the first journal entry to the list.
I've tried to look up the solution to this problem through various other threads but my search was unsuccessful. I'm new to C and also new to this site so I apologize in advance if I'm incorrect in phrasing this question. I kinda have an idea of what's going on, but at the same time I might be entirely wrong. I have a linked list and I'm trying to insert at the end of the list. But when Xcode gets to the statement while(ptr->next!=NULL) it throws the error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x800000012)
I read somewhere before that it was because I'm accessing something that doesn't exist or I'm failing to initialize node->next to NULL but I did in the previous "if statement". I'm pretty new at coding with pointers and linked lists and again I apologize for any weird stuff that might be in my code ):
////LIST AND NODE STRUCTURES
//data nodes
typedef struct node{
int data;
int ID;
struct node* prev;
struct node* next;
} node;
typedef struct ListInfo{
int count; //numnodes
struct node *list; //list of nodes
} ListInfo;
////INSERT FUNCITON
void insert(ListInfo *H, node *n){
if(n == NULL)
return;
node* ptr = H->list;
if(H==NULL){
ptr = n;
ptr->next = NULL;
}
else{
while(ptr->next!=NULL){ //Thread 1: EXC_BAD_ACCESS (code=1, address=0x800000012)
ptr = ptr->next;
}
ptr = n;
ptr->next = NULL;
}
// End of function
return;
}
////MAIN
int main(){ // No Edititng is needed for the main function.
ListInfo H;
H.count =0;
node *n;
int Data = 0,ID =0 ;
do{
printf("Enter an ID and a Value to add to the list, Enter -1 to stop: ");
//Get value from user to store in the new linked list node later.
scanf("%d %d",&ID,&Data);
// Check if the user entered "-1", if so exit the loop.
if(Data == -1||ID == -1)
return 0;
// Allocate memory for a new Node to be added to the Linked List.
n = malloc(sizeof(node));
// Put the Data from the user into the linked list node.
n->data = Data;
n->ID = ID;
//Increment the number of nodes in the list Header.
// If the current node count is zero, this means that this node is the first node
// in this list.
if(H.count++ == 0)
H.list = n;
// Otherwise, just use the insert function to add node to the list.
else insert(&H,n);
}while(Data != -1);
// Display all nodes in the list.
DisplayList(&H);
//Remove a node from the list, and display the list each time.
while(H.count != 0){
Delete(&H,H.list->data);
DisplayList(&H);
}
// Display the list, this should be empty if everything was correct.
DisplayList(&H);
}
When you allocate n you never set n->next. When you pass it to insert() you try to access the bad pointer and crash. When you set n->ID you should set n->next to NULL.
In a program I'm writing I need a linked list, so it's a pretty specific implementation. It needs:
the ability to add a node to the end
the ability to remove a node whose data matches a specified value
The data is a cstring, no more than 20 characters in length. I'm not very experienced with C and am getting errors with the following signature void addToEnd(llist root, char entery[51]). I tried replacing llist with node but then the error is "unknown type name node". How can I get rid of this?
Here's the code
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct node
{
char entery[51];
struct node* next;
} llist;
/*may be losing root address permanently*/
void addToEnd(llist root, char entery[51])
{
while(root->next != NULL)
root = root->next;
node last = malloc(sizeof(struct node));
root->next = last;
strcpy(last, entery);
}
int main()
{
struct node *root = malloc(sizeof(struct node));
root->next = NULL;
strcpy(root->entery, "Hello");
struct node *conductor = root;//points to a node while traversing the list
if(conductor != 0)
while(conductor->next != 0)
conductor = conductor->next;
/* Creates a node at the end of the list */
conductor->next = malloc(sizeof(struct node));
conductor = conductor->next;
if (conductor == NULL)
{
printf( "Out of memory" );
return EXIT_SUCCESS;
}
/* initialize the new memory */
conductor->next = NULL;
strcpy(conductor->entery, " world\n");
addToEnd(root, " at the");
addToEnd(root, " end");
/*print everything in list*/
conductor = root;
if(conductor != NULL)
{
while(conductor->next != NULL)
{
printf("%s", conductor->entery);
conductor = conductor->next;
}
printf("%s", conductor->entery);
}
return EXIT_SUCCESS;
}
One thing I'm unclear about, is in all the examples I've seen is they typedef the struct. Why? Let me elaborate: how do you know if you want to be passing just node or struct node. Also I don't really see the point, struct node isn't that much longer than a single typedef'd name.
Problems:
line 12: void addToEnd(llist root, char entery[51]) shall be void addToEnd(llist *root, char entery[51]). Here root must be a pointer type or you actually can not modify its value inside the function and make it visible outside the function.
line 16: node last = malloc(sizeof(struct node)); shall be struct node *last = malloc(sizeof(struct node));. Since in C you must reference a type name with the keyword struct, and also it shall be a pointer or it cannot be initialized with malloc.
As for your typedef question, I believe it is optional and people use it only for convenience. Personally I don't use typedef on a struct very often.
EDITED:
Also your code comes with bugs. Sorry I was only focusing on the syntax before.
Please notice that malloc in C don't assure you that the allocated memory is zeored, it's actually could be anything inside. So you need to fill it manually: to add a line last->next = NULL; at the end of addToEnd.
To refer to your struct of the linked list, use struct node, after the typedef, you can also use llist. You can also ues, as the linked question uses.
typedef struct node
{
char entery[51];
struct node* next;
} node;
In this style, you can use node the same as struct node.
The syntax error you are facing is, you misused the arrow operator ->, it's used with pointers of struct. For struct, use the dot operator .
So for the function
void addToEnd(llist root, char entery[51])
{
while(root->next != NULL)
root = root->next;
You should pass in a pointer:
void addToEnd(llist* root, char entery[51])
Consider the following code snippet
struct node {
char *name;
int m1;
struct node *next;
};
struct node* head = 0; //start with NULL list
void addRecord(const char *pName, int ms1)
{
struct node* newNode = (struct node*) malloc(sizeof(struct node)); // allocate node
int nameLength = tStrlen(pName);
newNode->name = (char *) malloc(nameLength);
tStrcpy(newNode->name, pName);
newNode->m1 = ms1;
newNode->next = head; // link the old list off the new node
head = newNode;
}
void clear(void)
{
struct node* current = head;
struct node* next;
while (current != 0)
{
next = current->next; // note the next pointer
/* if(current->name !=0)
{
free(current->name);
}
*/
if(current !=0 )
{
free(current); // delete the node
}
current = next; // advance to the next node
}
head = 0;
}
Question:
I am not able to free current->name, only when i comment the freeing of name, program works.
If I uncomment the free part of current->name, I get Heap corruption error in my visual studio window.
How can I free name ?
Reply:
#all,YES, there were typos in struct declaration. Should have been char* name, and struct node* next. Looks like the stackoverflow editor took away those two stars.
The issue was resolved by doing a malloc(nameLength + 1).
However,If I try running the old code (malloc(namelength)) on command prompt and not on visual studio, it runs fine.
Looks like, there are certain compilers doing strict checking.
One thing that I still do not understand is , that free does not need a NULL termination pointer, and chances to overwrite the allocated pointer is very minimal here.
user2531639 aka Neeraj
This is writing beyond the end of the allocated memory as there is no space for the null terminating character, causing undefined behaviour:
newNode->name = (char *) malloc(nameLength);
tStrcpy(newNode->name, pName);
To correct:
newNode->name = malloc(nameLength + 1);
if (newNode->name)
{
tStrcpy(newNode->name, pName);
}
Note calling free() with a NULL pointer is safe so checking for NULL prior to invoking it is superfluous:
free(current->name);
free(current);
Additionally, I assume there are typos in the posted struct definition (as types of name and next should be pointers):
struct node {
char* name;
int m1;
struct node* next;
};