I am just learning about linked list.
While I am trying to insert elements in linked list I am unable to print those inserted elements.
int main()
{
int i,x,n;
struct node* head = NULL;
printf("Enter number of elements to insert into likedlist :");
scanf("%d",&n);
printf("Enter elements: ");
for(i=0;i<n;i++)
{
scanf("%d",&x);
insert(head,x);
}
print(head);
}
struct node* insert(struct node* head,int x)
{
struct node* p = (struct node*)malloc(sizeof(struct node));
p->data = x;
p->next = NULL;
if(head == NULL)
{
head = p;
return head;
}
p->next = head;
head = p;
return head;
}
here I am adding the elements to a linked list by changing it's head node(insert_front).
void print(struct node* n)
{
while(n != NULL)
{
printf("%d -> ",n->data);
n = n->next;
}
printf("NULL");
}
So, what's wrong with this code.
Output is like this
Sample Input:
Enter number of elements to insert into likedlist :5
Enter elements: 1 2 3 4 5
Sample Output:
NULL
Read more about C programming (first some good tutorial book, then some reference site, and later refer to the C11 standard n1570). We cannot teach you it in a few paragraphs.
C uses a call-by-value evaluation strategy.
So, at least for newbies, it is conventionally recommended (but not required) to never use a formal argument as the left-side destination of some assignment, because any change to a formal argument is local to the function having that formal argument and does not impact the caller.
So, Compile with all warnings and debug info: gcc -Wall -Wextra -g with GCC. Use the debugger (e.g. gdb) to understand the behavior of your program (your bug is probably not in the code chunk you show us).
Ability to understand the behavior of an entire program, and to debug it, is an essential skill for developers. Both the compiler's warnings and the debugger can assist you in understanding the behavior of a program. See also http://norvig.com/21-days.html for a useful insight.
So the head formal argument in insert is a local copy of the actual argument from the caller.
In
if(head == NULL)
{
head = p;
return head;
}
you modify only that copy, not the original. So the head = p; above is completely useless (and confusing), you'll better just replace the block in braces above with simply return p;
We don't know how you call insert, and we cannot help more.
Perhaps insert should get the address of some pointer.... or perhaps your main should use the return value of it...
In your edited question, inside your main, replace
insert(head,x); //WRONG
(which does not change the local head declared in main, even if insert is changing its first formal, because of call by value argument passing) with
head = insert(head, x);
Related
I'm trying to creating linear linked list recursively with c language,
but keep sticking from here and the code is not working with the error "Linker Tools Error LNK2019". Sadly i can't understand what's the matter. Here is my code.
Thanks for your big help in advance.
#include <stdio.h>
#include <stdlib.h>
struct node
{
char num; //Data of the node
struct node *nextptr; //Address of the next node
};
typedef struct node element;
typedef element *link;
link head;
void displayList(); // function to display the list
int main()
{
char s[] = "abc";
link stol(s);
{
link head;
if (s[0] == '\0')return(NULL);
else {
head = (link)malloc(sizeof(element));
head->num = s[0];
head->nextptr = stol(s + 1);
return(head);
}
}
printf("\n\n Linked List : To create and display Singly Linked List :\n");
printf("-------------------------------------------------------------\n");
displayList();
return 0;
}
void displayList()
{
link tmp;
if (head == NULL)
{
printf(" List is empty.");
}
else
{
tmp = head;
while (tmp != NULL)
{
printf(" Data = %d\n", tmp->num); // prints the data of current node
tmp = tmp->nextptr; // advances the position of current node
}
}
}
You redefine a link object called head in your main() function. It hides the global head variable.
Removing the definition inside main would fix your problem, but you should consider passing a link* as a parameter to your displayList function in any case.
I've just noticed this statement return(head); in main(). You program exits prematurely as a result as well.
Everytime I look at your app, I find more issues. If I were you, I'd start by creating a function that adds a node to the list. It's much easier to add new nodes to the front of the list, so you should try that first. Try adding to the tail once you get this running. Adding to the tail is very similar, but you have to 'walkthe list first to get to the last element, exactly as you already do indisplayList()` Another way is keeping the address of the last node* you've added to the list. Like I said, it adds a bit of complexity, so get it working with addToHead first.
void addToHead(link* l, node* n)
{
n->nextptr = l->nextptr;
l->nextptr = n;
}
in your main, you can allocate one new node at a time, as you already do with malloc(). Initialize its contents num with an integer, and let addToHead deal with the pointer stuff. Your use of pointers is terrible, but lists are quite easy, and addToList pretty much shows what can and what should be put in pointers - namely other pointers.
You can remove almost everything in main() before the first printf. You'll have to
start loop:
write a prompt so the user knows what to do using printf()
read input from user using scanf("%d", &n), or equivalent.
break from the loop if user enters a negative value.
malloc() a new node
set its data num = n
call addToHead to add the node.
Loop until user enters an empty string, or -1.
That should take about 8 to 10 lines of code. if in doubt, you will easily find documentation on scanf, with google or on http://en.cppreference.com/w/c.
I declared a linked list implemented in C as follows:
struct node_List {
int i;
char * name;
struct node_List* next;
};
typedef struct node_List nodeList;
Then I declared the list head globally as:
nodeList list; // head of the list - does not contain relevant data
Finally, I have a function id(char * s) with a string s as th only argument.
nodeType id(char *s)
{
nodeType *p; // another List type
if ((p = malloc(sizeof(nodeType))) == NULL) {
// error: out of memory;
}
nodeList * node = &list;
// printf(" ");
while (node->next != NULL){
node = node->next;
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
}
// error: not found;
}
The problem is, when i run this program and call foo("somestring") the program executes the error: not found part and aborts execution, despite the string somestring being in the list.
I tried executing the very same program by inserting some printf() for debugging purposes, and it works perfectly, except it prints additional characters along with the output.
This happens each time I add some print lines, e.g. if I uncomment the two printf()s which I wrote in the example above (one of them or both, i get the same successful result). It doesn't work though if the printf is called with no arguments or with an empty string "".
I can't figure out what's happening, I double-checked the list creation and population functions and I am totally sure they work correctly. I tried changing the while break condition, but that didn't work, too. I have observed a similar behaviour on both Linux (with gcc) and Windows (using CodeBlocks editor's integrated compiler)
How could a printf directive affect a program so much?
EDIT: This code is part of a syntax analyzer written in Yacc. The whole code can be found below. It's a long read, and it is not completed, but the code above was tested and used to work as explained.
lexer: http://pastebin.com/1TEzzHie
parser: http://pastebin.com/vwCtMhX4
When looking in the provided source code, the algorithm to explore the linked list has two ways to miss node in the while-loop comparison.
Way 1 - starting only from the second node of the list.
Placing node = node->next; before the comparison will force the first comparison to be &(list)->next instead of &(list).
To start from the first node, simply place node = node->next; after
the comparison.
Way 2 - never ending to the last node of the list.
Using (node->next != NULL) in the while condition will force to exit from the loop before comparing the last node => node->next = NULL;.
To end by the last node, simply change the while condition to (node != NULL).
Solution:
while (node != NULL){ // end from the last node
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
node = node->next; // explore link after comparison
}
The actual error is a wrong type declaration of a variable returned by the function:
nodeType* createPoint(char* l){
nodeList* p;
if((p=malloc(sizeof(nodeList))) == NULL){
yyerror("out of memory");
} else {
// do stuff with p
}
return p;
}
The function return value was a nodeType* and p was instantiated as nodeList*.
The declaration of those two types was pretty simple, that's why the program could work.
the working code can be found here.
The strange behaviour with printf() was probably caused by the heap space needed for printf's arguments: since this function accepts an arbitrary number of parameters, it saves them in a list. This list is instantiated in the heap, there overwriting the old data left there from the wrong implementation of createPoint.
I've come across what seems to be a strange problem when implementing a singly linked list. I call a list_destroyer and pass the pointer to the head of the list, however when the method returns, the pointer that is passed still points to a full list. I don't believe I've passed a struct anywhere.
Here is my struct list, and typedef
typedef struct list list_t
struct list{
void* datum;
list_t* next;
};
And here is the code that is causing problem
void list_destroy(list_t *head){
list_t *destroy = head;
while(head){
//printf("%d \n", list_size(head));
head = head->next;
free(destroy);
destroy = head;
}
//printf("%d \n", list_size(head));
head = NULL;
//printf("%d \n", list_size(head));
}
The list_size functions have been commented out because they aren't necessary, but I use them to see the output of the code. The printf output shows that the size is decreasing. The two printf's surrounding the "head = NULL;" statement both print a size of zero. This is also confirmed with gdb. However, when I have this code (following) calling list_destroy, the pointer that is passed through is unchanged.
int main(){
list_t *test = NULL;
int a = 1;
int b = 2;
list_append(test,&a);
list_append(test,&b);
printf("%d \n", list_size(test));
list_destroy(test);
printf("%d \n", list_size(test));
}
I still get the printf above and below the list_destroy to both output 2. I haven't initialized a new list_t anywhere, so I don't see how the printf after the list_destroy would still output 2, (especially when the printf within the list_destroy says the list_t* passed in has a size of 0 at the end.
however when the method returns, the pointer that is passed still points to a full list.
That's incorrect: when the function returns, the pointer points to what used to be a full list. Chances are, your system would let you traverse the entire list without a break. However, dereferencing this pointer after the call is undefined behavior, so the same code could crash on other systems.
The problem has a name - head becomes a dangling pointer.
Fixing the problem is easy - pass a pointer to pointer, and set it to NULL upon completion:
void list_destroy(list_t **headPtr){
list_t *head = *headPtr;
list_t *destroy = head;
while(head){
head = head->next;
free(destroy);
destroy = head;
}
*headPtr = NULL;
}
I am trying to create a simple C program while learning about the concepts about pointers, linked list and header files.
I want to create a simple C program by clubbing all these concepts together for better understanding.
My code and its explanation is as follows:
I have a header file "header1.h " where I have declared the structure which is to be shared between various source files and also the "head" variable of the linked list.
The header file is as follows:
header1.h
struct node{
char * name;
struct node* next;
};
extern struct node* head;
Now, I have the main source-file named "start_prog.c" which has got the "main" function
and the menu which will control the execution of the of the program.
Menu has various options such as Add element ,Delete element , Reverse List etc (for simplicity I will only present two options here viz, Insert and Print list which are most important).
from the start_prog.c I call the "create" function which will add the element to the list.
If the list does not exist then it will create one else It will append the element to the list after the last element.
The create function is defined in another source file "create.c".
Both the files are as follows:
start_prog.c:
#include<stdio.h>
#include<stdlib.h>
#include "header1.h" //include the header file
struct node* head = NULL; //Define the external variable head to be null initially
struct node* create();
void main(void){
int option;
do{
printf("\nplease select the option : \n\t\t1)add element \n\t\t2)Print List\n");
scanf("\n%d",&option);
switch(option){
case 1:
head = create();
break;
case 2:
print_list();
break;
}
}while(option != 3);
}
and the create.c file is as follows:
#include<stdio.h>
#include<stdlib.h>
#include "header1.h"
//this function creates the linked list if the list is null or inserts the
//element at the end of the list.
struct node* create() {
if(head == NULL){
//create a new list and return head.
printf("\nhead is null\n");
struct node* newnode = (struct node*)malloc(sizeof(struct node));
char * new_name;
printf("\nplease enter the new name\n ");
scanf("%s\n", new_name);
newnode -> name = new_name;
newnode -> next = NULL;
head = newnode;
return head;
}
else if(head != NULL){
printf("\nhead is not null\n ");
struct node* newnode = (struct node*)malloc(sizeof(struct node));
char * new_name;
printf("\n Please Enter the new name \n");
scanf("%s\n", new_name);
newnode -> name = new_name;
newnode -> next = NULL;
struct node* ptr = NULL;
ptr = head;
while((ptr -> next) != NULL){
ptr = ptr -> next;
}
ptr -> next = newnode;
return head;
}
}
when I run all these programs together I get Garbage values in the head and Segmentation fault error. What is Wrong in my code. What is the thing that I am missing. I feel that I am close to understand the concepts but missing some important point due to which I am not
able to write the program properly. Please find the bug/error in my code and the fault in my understanding.
Thankyou!
Generally Segmentation fault occurs when you to try to access or assign value from/to memory which is not assigned to that process.
Normally check places where you are assigning values or retrieving it whether your the is assigned to it or not.
one think i saw was
char * new_name; // declaring the pointer
printf("\n Please Enter the new name \n");
scanf("%s\n", new_name);//reading the value from stdin to where pointer is pointing
when you declare the pointer its filled with garbage value. which may be out of range of your process assigned memory. and your asking your compiler to store the value there which is illegal hence the kernel raises a signal SIGSEGV and halts your process.
Assign memory before assigning the value
new_name = malloc(20); // how much ever you think is required
In your create.c file
char * new_name;
printf("\nplease enter the new name\n ");
scanf("%s\n", new_name);
How will that above code execute, Please try to use array to store name temporarily there.
if you want to use pointer there then you have to allocate memrory for that poiner too.
and dont use '\n' in the scanf like that or else, it will not stop even when you press enter key it will stop only when you press any non-white space charater,which would be awfull.
Say I have the following struct to define list nodes:
struct node {
int data;
struct node* next;
};
And I have this function to get the length of a list:
int Length(struct node* head) {
struct node* current = head;
int count = 0;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
Why would I want to do this: struct node* current = head; instead of just iterating over the head?
So, why would this not be ok:
int Length(struct node* head) {
int count = 0;
while (head != NULL) {
count++;
head = head->next;
}
return count;
}
Doesn't the head lose the scope once it gets inside the Length function, and therefore even if we do head = head->next it won't be affected outside the function?
Thanks
Your two codes snippets are equivalent.
However, there's a school of thought that says that you should never modify function arguments, in order to avoid potential programming errors, and to enhance readability (you're not really modifying the head). To that end, you will often see people defining as many arguments as possible as const.
A smart compiler will do that anyway. Some people do it for clarity as head to them means the head of the list and current is just the iterator, it's just for readability.
The programmers I know all intuitively assume that the value of an argument which is passed by-value (such as the address referenced by a pointer) remain unchanged throughout the function. Due to this assumption, it's easy to introduce little bugs when extending the function. Imagine I wanted to print a little bit of debug information to your Length function:
int Length(struct node* head) {
int count = 0;
while (head != NULL) {
count++;
head = head->next;
}
printf( "Length of list at %p is %d\n", head, count );
return count;
}
The larger the function gets (or the more contrived the logic is, or the less attention the guy doing the modification is paying...), the easier this kind of issue can happen.
For short functions, such as Length, I personally consider it to be fine (I do it as well).