C: Learning to Code in C with pointers, Header files etc - c

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.

Related

Is there a way in C to create new nodes in a linked list without memory allocation?

I just learned the concept of a linked list in C, and tried implementing it. What I did was create a pointer head, and a pointer itr. To create a new node I would initialize a node normally (without using pointers), and then attach a pointer to it.
struct node temp; //A single node contains a value 'num' and a pointer to the next node.
temp.num=x;
temp.next=NULL;
if(head==NULL){
head=&temp;
}
else{
itr=head;
while(itr->next!=NULL){
itr=itr->next;
}
itr->next=&temp;
}
This method is not working, and based on my limited knowledge of pointers in C, I cannot figure out why. I know that the right way to do it is by using malloc to create new nodes, but I need to know why this method does not work.
Full Program:
#include <stdio.h>
struct node{
int num;
struct node *next;
};
int main(){
struct node *head=NULL;
struct node *itr;
struct node temp;
int choice;
printf("1. Enter new Node, 2. Traverse all nodes, 3. Exit.");
int x;
while(1){
printf("\nEnter your choice: ");
scanf("%d", &choice);
if(choice==1){
printf("Enter value: ");
scanf("%d", &x);
temp.num=x;
temp.next=NULL;
if(head==NULL){
head=&temp;
}
else{
itr=head;
while(itr->next!=NULL){
itr=itr->next;
}
itr->next=&temp;
}
}
else if(choice==2){
if(head==NULL){
printf("Empty List");
continue;
}
printf("The values are: ");
itr=head;
printf("%d ", itr->num);
while(itr->next!=NULL){
itr=itr->next;
printf("%d ", itr->num);
}
}
else{
break;
}
}
}
A linked list generally consists of several nodes, in which each node points to the next node in the list. The last node in the linked list should point to NULL to mark the end of the list.
However, you have only allocated memory for a single node. Therefore, you will only be able to store a single node in the linked list.
The code for adding the first node to the linked list is correct. However, the code for adding a second node cannot work, because you have not allocated any memory for the second node.
What your code for adding the second node is actually doing is overwriting the first node, and making this first node point to itself. That is why you are getting an infinite loop, if you attempt to print the linked list afterwards.
Therefore, I suggest that you instead use malloc for allocating memory for the nodes. That way, you won't be limited to a single node.
You must show your whole code.
I guess , in your case, if you define a function like this, the temp elem is funciton local variable, you need use malloc to make it accessable out of the function.
int addNode(struct node *head, inx x) {
struct node temp; //A single node contains a value 'num' and a pointer to the next node.
temp.num=x;
temp.next=NULL;
if(head==NULL){
head=&temp;
}
else{
itr=head;
while(itr->next!=NULL){
itr=itr->next;
}
itr->next=&temp;
}
}

unable to print elements in a linked list in c

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);

Creating and displaying linear linked list in C(Recursively)

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.

Comparing a variable to a linked list's variable

I have a program where details are taken by a user for a survey. It contains details of a person with a pps as a unique identifier. When adding a newNode to the list and checking the PPS it does not recognise if the number is the same in any of the nodes. Adding a printf into the loop to show the current pps gives a nullptr exception. I have tried not using **head_ptr replacing with *head_ptr however this gives more errors down in the rest of the code where the node is added to the list.
//a new node is created which is filled with info. Some vaidation is done such as PPS number uniqueness and the node is added to the list
//in this function the node is added to the very front of the list. Note: the sorting does not happen here without sorting it would be a list of the most recently enetered items
//a second function will carry out the sort
void addSurvey(struct survey** head_ptr)
{
int inputPPS,inputAge,inputSmoker, inputDrink, inputExer, inputIncome;
int scanfBoolean;
struct survey *temp;
struct survey *newNode;
temp = *head_ptr;
newNode = (struct survey*)malloc(sizeof(struct survey));
printf("\nPlease enter your PPS number (Number must be unique)\n");
scanf("%d", &inputPPS);
while (temp != NULL)
{
if (inputPPS == temp->surveyDetails.ppsNo)
{
printf("\nPPS you have entered is not unique. \n\n");
free(newNode); free(temp);
return;
}
temp = temp->next;
printf("\nChecking list. PPS is %d\n\n", temp->surveyDetails.ppsNo);
}
newNode->surveyDetails.ppsNo = inputPPS;
You are freeing node once you found it
free(temp);
In this case after you return from this function addSurvey the pointer pointed to by struct survey** head_ptr points to freed memory and probably you use it incorrectly.
Even worse, when you assign new value to temp and you might have assigned a NULL to it, you are not checking this and you try to access pointer to that unknown memory to print integer:
temp = temp->next;
printf("\nChecking list. PPS is %d\n\n", temp->surveyDetails.ppsNo);
You do not link your new node (newNode) to the list leaving the list empty. You have to add
temp->next=newNode;
is an appropriate place

unable to access memory 0X.... C program (Ubuntu 12.10)

Purpose of code:
TO maintain a unique element link list...UFID is the keyword for unique
Structure declaration:
struct sharedFiles
{
char UFID[50];
int valid; //valid 1 if someone have this file in write mode
int shared; //no of user's reading this file
struct sharedFiles *next; //pointer to next node
}*sfstart,*sfend; //sfstart points to the first node of linked list and efend to the last node of linked list so that it will be easy to just insert at the end without traversing the linked list
Error Description:
The below code gives segmentation fault when I invoking it 2nd time.
I tried to debug with GDB and it says unable to access the location at line
if(strcmp(sftemp->UFID,ufid)==0)
In the above line it is unable to access sftemp->UFID
/*Function code*/
int addShareList(char *ufid,int mode) //mode=0 (read) and mode=1 (Write request)
{
struct sharedFiles *sftemp,*newnode;
sftemp=sfstart;
if(sfstart==NULL) //if list is empty add first node
{
sfstart=(struct sharedFiles *) malloc(sizeof(struct sharedFiles));
strcpy(sfstart->UFID,ufid);
sfstart->valid=mode;
sfstart->shared=1;
sfstart->next=NULL;
sfend=sfstart; //this node will also be last node of Linked list
return 0;
}
else //if list is not empty
{
while(sftemp->next != NULL) //traverse till last node
{
if(strcmp(sftemp->UFID,ufid)==0)
{
//here if same node found some manupulation to the struct variables
}
sftemp=sftemp->next;
} //while
if(sftemp->next==NULL) //procvess last node
{
if(strcmp(sftemp->UFID,ufid)!=0) //if last node not same add node at the end of Linked list
{
newnode=(struct sharedFiles *) malloc(sizeof(struct sharedFiles));
strcpy(newnode->UFID,ufid);
newnode->valid=mode;
newnode->shared=1;
newnode->next=NULL;
sftemp->next=newnode;
sfend=newnode;
return 0;
}
else //if last node is same
{
//some manipulations to struct variables
}
} //if
}
return -1;
}//addShareList
The above code works fine for inserting first element.When I invoke the same function for inserting second node in the linked list it unable to access the first node while comarision
in the line if(strcmp(sftemp->UFID,ufid)==0). Hope now the purpose of code is clear.
Thanks in advance..
In the while you check if sftemp!=NULL so we can be sure that in the second iteration, after line sftemp=sftemp->next; the pointer contain allocated memory.
But, since I don't know how the list it structured, I can't be sure that the content contains another node of sharedFiles type, it could contain an end-list node which not contains UFID attribute.
So, check in your list how to control if the list is finished.
Another solution can be to change your check this way:
while(sftemp->next!=NULL)
...
if(sftemp->next==NULL) {
//add the node in the right way, consider the end-list node
}
EDIT:
Furthermore, change in the first if the line sftemp->next = NULL; to sfnext->next = NULL;.
And be sure to initialize stnext = NULL.
EDIT 2:
Now that you post struct declaration I still cannot see when you initialize sfstart. Try to do this:
Structure declaration:
struct sharedFiles
{
char UFID[50];
int valid; //valid 1 if someone have this file in write mode
int shared; //no of user's reading this file
struct sharedFiles *next; //pointer to next node
}*sfstart = NULL,*sfend;
Normally the answer for this is that the pointer is NULL, which in your case means malloc has failed because you're out of memory - you really should be checking the return value.
The most likely cause for your problem is that you have corrupted the heap, so that sftemp no longer points to a valid memory address. Check what it's value is that might give you some more clues.

Resources